def test_get_earliest_timestamp(db, team): _create_event(team=team, event="sign up", distinct_id="1", timestamp="2020-01-04T14:10:00Z") _create_event(team=team, event="sign up", distinct_id="1", timestamp="2020-01-06T14:10:00Z") assert get_earliest_timestamp(team.id) == datetime(2020, 1, 4, 14, 10, tzinfo=pytz.UTC) _create_event(team=team, event="sign up", distinct_id="1", timestamp="1984-01-06T14:10:00Z") _create_event(team=team, event="sign up", distinct_id="1", timestamp="2014-01-01T01:00:00Z") _create_event(team=team, event="sign up", distinct_id="1", timestamp="2015-01-01T01:00:00Z") assert get_earliest_timestamp(team.id) == datetime(2015, 1, 1, 1, tzinfo=pytz.UTC)
def _create_sample_data(self): distinct_id = "user_one_{}".format(self.team.pk) _create_person(distinct_ids=[distinct_id], team=self.team) _create_event(event="viewed", distinct_id=distinct_id, team=self.team, timestamp="2021-05-01 00:00:00")
def test_prop_cohort_multiple_groups(self): _create_person(distinct_ids=["some_other_id"], team_id=self.team.pk, properties={"$some_prop": "something"}) _create_person(distinct_ids=["some_id"], team_id=self.team.pk, properties={"$another_prop": "something"}) _create_event( event="$pageview", team=self.team, distinct_id="some_id", properties={"attr": "some_val"}, ) _create_event( event="$pageview", team=self.team, distinct_id="some_other_id", properties={"attr": "some_val"}, ) cohort1 = Cohort.objects.create( team=self.team, groups=[ { "properties": [{ "key": "$some_prop", "value": "something", "type": "person" }] }, { "properties": [{ "key": "$another_prop", "value": "something", "type": "person" }] }, ], name="cohort1", ) filter = Filter(data={ "properties": [{ "key": "id", "value": cohort1.pk, "type": "cohort" }], }, team=self.team) query, params = parse_prop_grouped_clauses( team_id=self.team.pk, property_group=filter.property_groups) final_query = "SELECT uuid FROM events WHERE team_id = %(team_id)s {}".format( query) result = sync_execute(final_query, {**params, "team_id": self.team.pk}) self.assertEqual(len(result), 2)
def test_insight_paths_basic(self): _create_person(team=self.team, distinct_ids=["person_1"]) _create_event( properties={"$current_url": "/"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about"}, distinct_id="person_1", event="$pageview", team=self.team, ) response = self.client.get(f"/api/projects/{self.team.id}/insights/path",).json() self.assertEqual(len(response["result"]), 1)
def test_funnel_correlation_on_properties_with_recordings(self): p1 = _create_person(distinct_ids=["user_1"], team=self.team, properties={"foo": "bar"}) _create_event( event="$pageview", distinct_id="user_1", team=self.team, timestamp=timezone.now(), properties={"$session_id": "s2", "$window_id": "w1"}, event_uuid="11111111-1111-1111-1111-111111111111", ) _create_event( event="insight analyzed", distinct_id="user_1", team=self.team, timestamp=(timezone.now() + timedelta(minutes=3)), properties={"$session_id": "s2", "$window_id": "w2"}, event_uuid="21111111-1111-1111-1111-111111111111", ) _create_session_recording_event(self.team.pk, "user_1", "s2", datetime(2021, 1, 2, 0, 0, 0)) # Success filter filter = Filter( data={ "insight": INSIGHT_FUNNELS, "date_from": "2021-01-01", "date_to": "2021-01-08", "funnel_correlation_type": "properties", "events": [{"id": "$pageview", "order": 0}, {"id": "insight analyzed", "order": 1}], "include_recordings": "true", "funnel_correlation_property_values": [ {"key": "foo", "value": "bar", "operator": "exact", "type": "person"} ], "funnel_correlation_person_converted": "True", } ) _, results = FunnelCorrelationActors(filter, self.team).get_actors() self.assertEqual(results[0]["id"], p1.uuid) self.assertEqual( results[0]["matched_recordings"], [ { "events": [ { "timestamp": timezone.now() + timedelta(minutes=3), "uuid": UUID("21111111-1111-1111-1111-111111111111"), "window_id": "w2", } ], "session_id": "s2", } ], )
def test_prop_cohort_with_negation(self): team2 = Organization.objects.bootstrap(None)[2] _create_person(distinct_ids=["some_other_id"], team_id=self.team.pk, properties={"$some_prop": "something"}) _create_person(distinct_ids=["some_id"], team_id=team2.pk, properties={"$another_prop": "something"}) _create_event( event="$pageview", team=self.team, distinct_id="some_id", properties={"attr": "some_val"}, ) _create_event( event="$pageview", team=self.team, distinct_id="some_other_id", properties={"attr": "some_val"}, ) cohort1 = Cohort.objects.create( team=self.team, groups=[{ "properties": [{ "type": "person", "key": "$some_prop", "operator": "is_not", "value": "something" }] }], name="cohort1", ) filter = Filter(data={ "properties": [{ "key": "id", "value": cohort1.pk, "type": "cohort" }], }, team=self.team) query, params = parse_prop_grouped_clauses( team_id=self.team.pk, property_group=filter.property_groups) final_query = "SELECT uuid FROM events WHERE team_id = %(team_id)s {}".format( query) self.assertIn("\nFROM person_distinct_id2\n", final_query) result = sync_execute(final_query, {**params, "team_id": self.team.pk}) self.assertEqual(len(result), 0)
def test_entity_filtered_by_cohort(self): cohort = _create_cohort( team=self.team, name="cohort1", groups=[{ "properties": [{ "key": "name", "value": "test", "type": "person" }] }], ) filter = Filter( data={ "date_from": "2021-05-01 00:00:00", "date_to": "2021-05-07 00:00:00", "events": [ { "id": "$pageview", "order": 0, "properties": [{ "key": "id", "type": "cohort", "value": cohort.pk }], }, ], }) Person.objects.create(team_id=self.team.pk, distinct_ids=["p1"], properties={"name": "test"}) _create_event(team=self.team, event="$pageview", distinct_id="p1", timestamp="2020-01-02T12:00:00Z") Person.objects.create(team_id=self.team.pk, distinct_ids=["p2"], properties={"name": "foo"}) _create_event(team=self.team, event="$pageview", distinct_id="p2", timestamp="2020-01-02T12:01:00Z") self._run_query(filter)
def test_denormalised_props(self): filters = { "events": [ { "id": "user signed up", "type": "events", "order": 0, "properties": [{ "key": "test_prop", "value": "hi" }], }, ], "date_from": "2020-01-01", "properties": [{ "key": "test_prop", "value": "hi" }], "date_to": "2020-01-14", } materialize("events", "test_prop") Person.objects.create(team_id=self.team.pk, distinct_ids=["p1"], properties={"key": "value"}) _create_event( team=self.team, event="$pageview", distinct_id="p1", timestamp="2020-01-02T12:00:00Z", properties={"test_prop": "hi"}, ) Person.objects.create(team_id=self.team.pk, distinct_ids=["p2"], properties={"key_2": "value_2"}) _create_event( team=self.team, event="$pageview", distinct_id="p2", timestamp="2020-01-02T12:00:00Z", properties={"test_prop": "hi"}, ) filter = Filter(data=filters) _, query = self._run_query(filter) self.assertIn("mat_test_prop", query)
def test_breakdown_by_group_props_with_person_filter(self): self._create_groups() Person.objects.create(team_id=self.team.pk, distinct_ids=["person1"], properties={"key": "value"}) _create_event( event="sign up", distinct_id="person1", team=self.team, properties={"$group_0": "org:5"}, timestamp="2020-01-02T12:00:00Z", person_properties={"key": "value"}, group0_properties={"industry": "finance"}, ) _create_event( event="sign up", distinct_id="person2", team=self.team, properties={"$group_0": "org:6"}, timestamp="2020-01-02T12:00:00Z", person_properties={}, group0_properties={"industry": "technology"}, ) filter = Filter( data={ "date_from": "2020-01-01T00:00:00Z", "date_to": "2020-01-12T00:00:00Z", "breakdown": "industry", "breakdown_type": "group", "breakdown_group_type_index": 0, "events": [{"id": "sign up", "name": "sign up", "type": "events", "order": 0,}], "properties": [{"key": "key", "value": "value", "type": "person"}], } ) response = Trends().run(filter, self.team,) self.assertEqual(len(response), 1) self.assertEqual(response[0]["breakdown_value"], "finance") self.assertEqual(response[0]["count"], 1)
def _create_sample_data(self, num, delete=False): for i in range(num): person = _create_person(distinct_ids=[f"user_{i}"], team=self.team) _create_event( event="step one", distinct_id=f"user_{i}", team=self.team, timestamp="2021-05-01 00:00:00", properties={"$browser": "Chrome"}, ) if i % 2 == 0: _create_event( event="step two", distinct_id=f"user_{i}", team=self.team, timestamp="2021-05-01 00:10:00", properties={"$browser": "Chrome"}, ) _create_event( event="step three", distinct_id=f"user_{i}", team=self.team, timestamp="2021-05-01 00:20:00", properties={"$browser": "Chrome"}, ) if delete: person.delete()
def test_pagination(self): cache.clear() for i in range(10): _create_person(distinct_ids=[f"user_{i}"], team_id=self.team.pk) _create_event( team=self.team, event="user signed up", distinct_id=f"user_{i}", timestamp="2020-01-02T14:00:00Z", ) _create_event( team=self.team, event="positively_related", distinct_id=f"user_{i}", timestamp="2020-01-03T14:00:00Z", ) _create_event( team=self.team, event="paid", distinct_id=f"user_{i}", timestamp="2020-01-04T14:00:00Z", ) request_data = { "events": json.dumps( [{"id": "user signed up", "type": "events", "order": 0}, {"id": "paid", "type": "events", "order": 1},] ), "insight": INSIGHT_FUNNELS, "date_from": "2020-01-01", "date_to": "2020-01-14", "funnel_correlation_type": "events", "funnel_correlation_person_converted": "true", "funnel_correlation_person_limit": 4, "funnel_correlation_person_entity": json.dumps({"id": "positively_related", "type": "events"}), } response = self.client.get(f"/api/projects/{self.team.pk}/persons/funnel/correlation", data=request_data) self.assertEqual(response.status_code, status.HTTP_200_OK) j = response.json() first_person = j["results"][0]["people"][0] self.assertEqual(4, len(j["results"][0]["people"])) self.assertTrue("id" in first_person and "name" in first_person and "distinct_ids" in first_person) self.assertEqual(4, j["results"][0]["count"]) next = j["next"] response = self.client.get(next) self.assertEqual(response.status_code, status.HTTP_200_OK) j = response.json() people = j["results"][0]["people"] next = j["next"] self.assertEqual(4, len(people)) self.assertNotEqual(None, next) response = self.client.get(next) self.assertEqual(response.status_code, status.HTTP_200_OK) j = response.json() people = j["results"][0]["people"] next = j["next"] self.assertEqual(2, len(people)) self.assertEqual(None, j["next"])
def test_filtering_with_group_props(self): self._create_groups() Person.objects.create(team_id=self.team.pk, distinct_ids=["person1"], properties={"key": "value"}) _create_event( event="$pageview", distinct_id="person1", team=self.team, timestamp="2020-01-02T12:00:00Z", ) _create_event( event="$pageview", distinct_id="person1", team=self.team, properties={"$group_0": "org:5"}, timestamp="2020-01-02T12:00:00Z", ) _create_event( event="$pageview", distinct_id="person1", team=self.team, properties={"$group_0": "org:6"}, timestamp="2020-01-02T12:00:00Z", ) _create_event( event="$pageview", distinct_id="person1", team=self.team, properties={"$group_0": "org:6", "$group_1": "company:10"}, timestamp="2020-01-02T12:00:00Z", ) filter = Filter( { "date_from": "2020-01-01T00:00:00Z", "date_to": "2020-01-12T00:00:00Z", "events": [{"id": "$pageview", "type": "events", "order": 0}], "properties": [ {"key": "industry", "value": "finance", "type": "group", "group_type_index": 0}, {"key": "key", "value": "value", "type": "person"}, ], }, team=self.team, ) response = Trends().run(filter, self.team) self.assertEqual(response[0]["count"], 1)
def test_account_filters(self): Person.objects.create(team_id=self.team.pk, distinct_ids=["person_1"], properties={"name": "John"}) Person.objects.create(team_id=self.team.pk, distinct_ids=["person_2"], properties={"name": "Jane"}) _create_event(event="event_name", team=self.team, distinct_id="person_1") _create_event(event="event_name", team=self.team, distinct_id="person_2") _create_event(event="event_name", team=self.team, distinct_id="person_2") cohort = Cohort.objects.create( team=self.team, name="cohort1", groups=[{ "properties": [{ "key": "name", "value": "Jane", "type": "person" }] }], ) cohort.calculate_people_ch(pending_version=0) self.team.test_account_filters = [{ "key": "id", "value": cohort.pk, "type": "cohort" }] self.team.save() filter = Filter(data={ "events": [ { "id": "event_name", "order": 0 }, ], "filter_test_accounts": True }, team=self.team) self._run_query(filter)
def test_insight_paths_basic_exclusions(self): _create_person(team=self.team, distinct_ids=["person_1"]) _create_event( distinct_id="person_1", event="first event", team=self.team, ) _create_event( distinct_id="person_1", event="second event", team=self.team, ) _create_event( distinct_id="person_1", event="third event", team=self.team, ) response = self.client.get( f"/api/projects/{self.team.id}/insights/path", data={"exclude_events": '["second event"]'} ).json() self.assertEqual(len(response["result"]), 1)
def test_breakdown_with_filter_groups(self): self._create_groups() _create_event( event="sign up", distinct_id="person1", team=self.team, properties={"key": "oh", "$group_0": "org:7", "$group_1": "company:10"}, timestamp="2020-01-02T12:00:00Z", ) _create_event( event="sign up", distinct_id="person1", team=self.team, properties={"key": "uh", "$group_0": "org:5"}, timestamp="2020-01-02T12:00:01Z", ) _create_event( event="sign up", distinct_id="person1", team=self.team, properties={"key": "uh", "$group_0": "org:6"}, timestamp="2020-01-02T12:00:02Z", ) response = Trends().run( Filter( data={ "date_from": "2020-01-01T00:00:00Z", "date_to": "2020-01-12T00:00:00Z", "breakdown": "key", "events": [{"id": "sign up", "name": "sign up", "type": "events", "order": 0,}], "properties": [{"key": "industry", "value": "finance", "type": "group", "group_type_index": 0}], } ), self.team, ) self.assertEqual(len(response), 2) self.assertEqual(response[0]["breakdown_value"], "oh") self.assertEqual(response[0]["count"], 1) self.assertEqual(response[1]["breakdown_value"], "uh") self.assertEqual(response[1]["count"], 1)
def test_action_with_person_property_filter(self): Person.objects.create(team_id=self.team.pk, distinct_ids=["person_1"], properties={"name": "John"}) Person.objects.create(team_id=self.team.pk, distinct_ids=["person_2"], properties={"name": "Jane"}) _create_event(event="event_name", team=self.team, distinct_id="person_1") _create_event(event="event_name", team=self.team, distinct_id="person_2") _create_event(event="event_name", team=self.team, distinct_id="person_2") action = Action.objects.create(team=self.team, name="action1") ActionStep.objects.create( event="event_name", action=action, properties=[{ "key": "name", "type": "person", "value": "John" }], ) filter = Filter(data={ "actions": [ { "id": action.id, "type": "actions", "order": 0 }, ] }) self._run_query(filter)
def test_path_groupings(self): _create_person(team=self.team, distinct_ids=["person_1"]) _create_event( properties={"$current_url": "/about_1"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about_2"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/something else"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about3"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about4"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_person(team=self.team, distinct_ids=["person_2"]) _create_event( properties={"$current_url": "/about_1"}, distinct_id="person_2", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about_2"}, distinct_id="person_2", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/something else"}, distinct_id="person_2", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about3"}, distinct_id="person_2", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about4"}, distinct_id="person_2", event="$pageview", team=self.team, ) response = self.client.get( f"/api/projects/{self.team.id}/insights/path", data={"insight": "PATHS", "path_groupings": json.dumps(["/about*"])}, ).json() self.assertEqual(len(response["result"]), 2) response = self.client.get( f"/api/projects/{self.team.id}/insights/path", data={"insight": "PATHS", "path_groupings": json.dumps(["/about_*"])}, ).json() self.assertEqual(len(response["result"]), 3)
def test_breakdowns(self): request_data = { "insight": INSIGHT_FUNNELS, "interval": "day", "actions": json.dumps([]), "properties": json.dumps([]), "funnel_step": 1, "filter_test_accounts": "false", "new_entity": json.dumps([]), "events": json.dumps( [{"id": "sign up", "order": 0}, {"id": "play movie", "order": 1}, {"id": "buy", "order": 2},] ), "insight": INSIGHT_FUNNELS, "date_from": "2020-01-01", "date_to": "2020-01-08", "funnel_window_days": 7, "breakdown": "$browser", "funnel_step_breakdown": "Chrome", } # event _create_person(distinct_ids=["person1"], team_id=self.team.pk) _create_event( team=self.team, event="sign up", distinct_id="person1", properties={"key": "val", "$browser": "Chrome"}, timestamp="2020-01-01T12:00:00Z", ) _create_event( team=self.team, event="play movie", distinct_id="person1", properties={"key": "val", "$browser": "Chrome"}, timestamp="2020-01-01T13:00:00Z", ) _create_event( team=self.team, event="buy", distinct_id="person1", properties={"key": "val", "$browser": "Chrome"}, timestamp="2020-01-01T15:00:00Z", ) _create_person(distinct_ids=["person2"], team_id=self.team.pk) _create_event( team=self.team, event="sign up", distinct_id="person2", properties={"key": "val", "$browser": "Safari"}, timestamp="2020-01-02T14:00:00Z", ) _create_event( team=self.team, event="play movie", distinct_id="person2", properties={"key": "val", "$browser": "Safari"}, timestamp="2020-01-02T16:00:00Z", ) _create_person(distinct_ids=["person3"], team_id=self.team.pk) _create_event( team=self.team, event="sign up", distinct_id="person3", properties={"key": "val", "$browser": "Safari"}, timestamp="2020-01-02T14:00:00Z", ) response = self.client.get("/api/person/funnel/", data=request_data) self.assertEqual(response.status_code, status.HTTP_200_OK) j = response.json() people = j["results"][0]["people"] self.assertEqual(1, len(people)) self.assertEqual(None, j["next"]) response = self.client.get("/api/person/funnel/", data={**request_data, "funnel_step_breakdown": "Safari"}) self.assertEqual(response.status_code, status.HTTP_200_OK) j = response.json() people = j["results"][0]["people"] self.assertEqual(2, len(people)) self.assertEqual(None, j["next"])
def test_backfilling_data(self): sync_execute("ALTER TABLE events DROP COLUMN IF EXISTS mat_prop") sync_execute("ALTER TABLE events DROP COLUMN IF EXISTS mat_another") _create_event(event="some_event", distinct_id="1", team=self.team, timestamp="2020-01-01 00:00:00", properties={"prop": 1}) _create_event( event="some_event", distinct_id="1", team=self.team, timestamp="2021-05-02 00:00:00", properties={ "prop": 2, "another": 5 }, ) _create_event(event="some_event", distinct_id="1", team=self.team, timestamp="2021-05-03 00:00:00", properties={"prop": 3}) _create_event(event="another_event", distinct_id="1", team=self.team, timestamp="2021-05-04 00:00:00") _create_event( event="third_event", distinct_id="1", team=self.team, timestamp="2021-05-05 00:00:00", properties={"prop": 4}, ) _create_event( event="fourth_event", distinct_id="1", team=self.team, timestamp="2021-05-06 00:00:00", properties={"another": 6}, ) materialize("events", "prop") materialize("events", "another") self.assertEqual(self._count_materialized_rows("mat_prop"), 0) self.assertEqual(self._count_materialized_rows("mat_another"), 0) with freeze_time("2021-05-10T14:00:01Z"): backfill_materialized_columns( "events", ["prop", "another"], timedelta(days=50), test_settings={"mutations_sync": "0"}) _create_event( event="fifth_event", distinct_id="1", team=self.team, timestamp="2021-05-07 00:00:00", properties={"another": 7}, ) iterations = 0 while self._get_count_of_mutations_running() > 0 and iterations < 100: sleep(0.1) iterations += 1 self.assertGreaterEqual(self._count_materialized_rows("mat_prop"), 4) self.assertGreaterEqual(self._count_materialized_rows("mat_another"), 4) self.assertEqual( sync_execute( "SELECT mat_prop, mat_another FROM events ORDER BY timestamp"), [("1", ""), ("2", "5"), ("3", ""), ("", ""), ("4", ""), ("", "6"), ("", "7")], )
def _setup_actions_with_different_counts(self): action = _create_action(team=self.team, name="$pageview") Person.objects.create( team_id=self.team.pk, distinct_ids=["1"], properties={ "$some_prop": "something", "$another_prop": "something" }, ) _create_event( event="$pageview", team=self.team, distinct_id="1", properties={"attr": "some_val"}, timestamp=datetime.now() - timedelta(days=1, hours=12), ) _create_event( event="$pageview", team=self.team, distinct_id="1", properties={"attr": "some_val"}, timestamp=datetime.now() - timedelta(days=0, hours=12), ) Person.objects.create( team_id=self.team.pk, distinct_ids=["2"], properties={ "$some_prop": "something", "$another_prop": "something" }, ) _create_event( event="$pageview", team=self.team, distinct_id="2", properties={"attr": "some_val"}, timestamp=datetime.now() - timedelta(days=1, hours=12), ) _create_event( event="$pageview", team=self.team, distinct_id="2", properties={"attr": "some_val"}, timestamp=datetime.now() - timedelta(days=0, hours=12), ) Person.objects.create( team_id=self.team.pk, distinct_ids=["3"], properties={ "$some_prop": "something", "$another_prop": "something" }, ) _create_event( event="$pageview", team=self.team, distinct_id="3", properties={"attr": "some_val"}, timestamp=datetime.now() - timedelta(days=0, hours=12), ) Person.objects.create( team_id=self.team.pk, distinct_ids=["4"], properties={ "$some_prop": "something", "$another_prop": "something" }, ) Person.objects.create( team_id=self.team.pk, distinct_ids=["5"], properties={ "$some_prop": "something", "$another_prop": "something" }, ) return action
def _create_groups_test_data(self): GroupTypeMapping.objects.create(team=self.team, group_type="organization", group_type_index=0) GroupTypeMapping.objects.create(team=self.team, group_type="company", group_type_index=1) create_group(team_id=self.team.pk, group_type_index=0, group_key="org:5", properties={"industry": "finance"}) create_group(team_id=self.team.pk, group_type_index=0, group_key="org:6", properties={"industry": "technology"}) create_group(team_id=self.team.pk, group_type_index=1, group_key="company:1", properties={"another": "value"}) Person.objects.create(team_id=self.team.pk, distinct_ids=["p1"], properties={"$browser": "test"}) Person.objects.create(team_id=self.team.pk, distinct_ids=["p2"], properties={"$browser": "foobar"}) Person.objects.create(team_id=self.team.pk, distinct_ids=["p3"], properties={"$browser": "test"}) _create_event( team=self.team, event="$pageview", distinct_id="p1", timestamp="2020-01-02T12:00:00Z", properties={ "$group_0": "org:5", "$group_1": "company:1" }, ) _create_event( team=self.team, event="$pageview", distinct_id="p2", timestamp="2020-01-02T12:00:00Z", properties={ "$group_0": "org:6", "$group_1": "company:1" }, ) _create_event( team=self.team, event="$pageview", distinct_id="p1", timestamp="2020-01-02T12:00:00Z", properties={"$group_0": "org:6"}, ) _create_event( team=self.team, event="$pageview", distinct_id="p3", timestamp="2020-01-02T12:00:00Z", properties={"$group_0": "org:5"}, )
def _create_related_groups_data(self): GroupTypeMapping.objects.create(team=self.team, group_type="organization", group_type_index=0) GroupTypeMapping.objects.create(team=self.team, group_type="playlist", group_type_index=1) uuid = UUID("01795392-cc00-0003-7dc7-67a694604d72") Person.objects.create(uuid=uuid, team_id=self.team.pk, distinct_ids=["1", "2"]) Person.objects.create(team_id=self.team.pk, distinct_ids=["3"]) Person.objects.create(team_id=self.team.pk, distinct_ids=["4"]) create_group(self.team.pk, 0, "0::0") create_group(self.team.pk, 0, "0::1") create_group(self.team.pk, 1, "1::2") create_group(self.team.pk, 1, "1::3") create_group(self.team.pk, 1, "1::4") create_group(self.team.pk, 1, "1::5") _create_event( event="$pageview", team=self.team, distinct_id="1", timestamp="2021-05-05 00:00:00", properties={ "$group_0": "0::0", "$group_1": "1::2" }, ) _create_event( event="$pageview", team=self.team, distinct_id="1", timestamp="2021-05-05 00:00:00", properties={ "$group_0": "0::0", "$group_1": "1::3" }, ) _create_event( event="$pageview", team=self.team, distinct_id="1", timestamp="2021-05-05 00:00:00", properties={ "$group_0": "0::1", "$group_1": "1::3" }, ) # Event too old, not counted _create_event( event="$pageview", team=self.team, distinct_id="1", timestamp="2000-05-05 00:00:00", properties={ "$group_0": "0::0", "$group_1": "1::4" }, ) # No such group exists in groups table _create_event( event="$pageview", team=self.team, distinct_id="1", timestamp="2000-05-05 00:00:00", properties={ "$group_0": "0::0", "$group_1": "no such group" }, ) return uuid
def test_correlation_endpoint_with_properties(self): self.client.force_login(self.user) for i in range(10): _create_person(distinct_ids=[f"user_{i}"], team_id=self.team.pk, properties={"$browser": "Positive"}) _create_event( team=self.team, event="user signed up", distinct_id=f"user_{i}", timestamp="2020-01-02T14:00:00Z", ) _create_event( team=self.team, event="paid", distinct_id=f"user_{i}", timestamp="2020-01-04T14:00:00Z", ) for i in range(10, 20): _create_person(distinct_ids=[f"user_{i}"], team_id=self.team.pk, properties={"$browser": "Negative"}) _create_event( team=self.team, event="user signed up", distinct_id=f"user_{i}", timestamp="2020-01-02T14:00:00Z", ) if i % 2 == 0: _create_event( team=self.team, event="negatively_related", distinct_id=f"user_{i}", timestamp="2020-01-03T14:00:00Z", ) # We need to make sure we clear the cache other tests that have run # done interfere with this test cache.clear() api_response = get_funnel_correlation_ok( client=self.client, team_id=self.team.pk, request=FunnelCorrelationRequest( events=json.dumps([ EventPattern(id="user signed up"), EventPattern(id="paid") ]), date_to="2020-01-14", date_from="2020-01-01", funnel_correlation_type=FunnelCorrelationType.PROPERTIES, funnel_correlation_names=json.dumps(["$browser"]), ), ) self.assertFalse(api_response["result"]["skewed"]) result = api_response["result"]["events"] odds_ratios = [item.pop("odds_ratio") for item in result] expected_odds_ratios = [121, 1 / 121] for odds, expected_odds in zip(odds_ratios, expected_odds_ratios): self.assertAlmostEqual(odds, expected_odds) self.assertEqual( result, [ { "event": { "event": "$browser::Positive", "elements": [], "properties": {} }, "success_count": 10, "failure_count": 0, "success_people_url": ANY, "failure_people_url": ANY, # "odds_ratio": 121.0, "correlation_type": "success", }, { "event": { "event": "$browser::Negative", "elements": [], "properties": {} }, "success_count": 0, "failure_count": 10, "success_people_url": ANY, "failure_people_url": ANY, # "odds_ratio": 1 / 121, "correlation_type": "failure", }, ], )
def test_backwards_compatible_path_types(self): _create_person(team=self.team, distinct_ids=["person_1"]) _create_event( properties={"$current_url": "/"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/about"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$current_url": "/something else"}, distinct_id="person_1", event="$pageview", team=self.team, ) _create_event( properties={"$screen_name": "/screen1"}, distinct_id="person_1", event="$screen", team=self.team, ) _create_event( distinct_id="person_1", event="custom1", team=self.team, ) _create_event( distinct_id="person_1", event="custom2", team=self.team, ) response = self.client.get( f"/api/projects/{self.team.id}/insights/path", data={"path_type": "$pageview", "insight": "PATHS",} ).json() self.assertEqual(len(response["result"]), 2) response = self.client.get( f"/api/projects/{self.team.id}/insights/path", data={"path_type": "custom_event", "insight": "PATHS"} ).json() self.assertEqual(len(response["result"]), 1) response = self.client.get( f"/api/projects/{self.team.id}/insights/path", data={"path_type": "$screen", "insight": "PATHS"} ).json() self.assertEqual(len(response["result"]), 0)
def test_entity_filtered_by_session_duration(self): filter = Filter( data={ "date_from": "2021-05-02 00:00:00", "date_to": "2021-05-03 00:00:00", "events": [ { "id": "$pageview", "order": 0, "properties": [{ "key": "$session_duration", "type": "session", "operator": "gt", "value": 90 }], }, ], }) event_timestamp_str = "2021-05-02 00:01:00" # Session starts before the date_from _create_event( team=self.team, event="start", distinct_id="p1", timestamp="2021-05-01 23:59:00", properties={"$session_id": "1abc"}, ) # Event that should be returned _create_event( team=self.team, event="$pageview", distinct_id="p1", timestamp=event_timestamp_str, properties={"$session_id": "1abc"}, ) # Event in a session that's too short _create_event( team=self.team, event="$pageview", distinct_id="p2", timestamp="2021-05-02 00:02:00", properties={"$session_id": "2abc"}, ) _create_event( team=self.team, event="final_event", distinct_id="p2", timestamp="2021-05-02 00:02:01", properties={"$session_id": "2abc"}, ) # Event with no session _create_event( team=self.team, event="$pageview", distinct_id="p2", timestamp="2021-05-02 00:02:00", ) results, _ = self._run_query(filter) self.assertEqual(len(results), 1) self.assertEqual(results[0][0].strftime("%Y-%m-%d %H:%M:%S"), event_timestamp_str)
def test_entity_filtered_by_multiple_session_duration_filters(self): filter = Filter( data={ "date_from": "2021-05-02 00:00:00", "date_to": "2021-05-03 00:00:00", "events": [ { "id": "$pageview", "order": 0, "properties": [ { "key": "$session_duration", "type": "session", "operator": "gt", "value": 90 }, { "key": "$session_duration", "type": "session", "operator": "lt", "value": 150 }, ], }, ], }) event_timestamp_str = "2021-05-02 00:01:00" # 120s session _create_event( team=self.team, event="start", distinct_id="p1", timestamp="2021-05-01 23:59:00", properties={"$session_id": "1abc"}, ) _create_event( team=self.team, event="$pageview", distinct_id="p1", timestamp=event_timestamp_str, properties={"$session_id": "1abc"}, ) # 1s session (too short) _create_event( team=self.team, event="$pageview", distinct_id="p2", timestamp="2021-05-02 00:02:00", properties={"$session_id": "2abc"}, ) _create_event( team=self.team, event="final_event", distinct_id="p2", timestamp="2021-05-02 00:02:01", properties={"$session_id": "2abc"}, ) # 600s session (too long) _create_event( team=self.team, event="$pageview", distinct_id="p2", timestamp="2021-05-02 00:02:00", properties={"$session_id": "3abc"}, ) _create_event( team=self.team, event="final_event", distinct_id="p2", timestamp="2021-05-02 00:07:00", properties={"$session_id": "3abc"}, ) results, _ = self._run_query(filter) self.assertEqual(len(results), 1) self.assertEqual(results[0][0].strftime("%Y-%m-%d %H:%M:%S"), event_timestamp_str)
def test_strict_funnel_correlation_with_recordings(self): # First use that successfully completes the strict funnel p1 = _create_person(distinct_ids=["user_1"], team=self.team, properties={"foo": "bar"}) _create_event( event="$pageview", distinct_id="user_1", team=self.team, timestamp=timezone.now(), properties={"$session_id": "s2", "$window_id": "w1"}, event_uuid="11111111-1111-1111-1111-111111111111", ) _create_event( event="insight analyzed", distinct_id="user_1", team=self.team, timestamp=(timezone.now() + timedelta(minutes=3)), properties={"$session_id": "s2", "$window_id": "w2"}, event_uuid="31111111-1111-1111-1111-111111111111", ) _create_event( event="insight analyzed", # Second event should not be returned distinct_id="user_1", team=self.team, timestamp=(timezone.now() + timedelta(minutes=4)), properties={"$session_id": "s2", "$window_id": "w2"}, event_uuid="41111111-1111-1111-1111-111111111111", ) _create_session_recording_event(self.team.pk, "user_1", "s2", datetime(2021, 1, 2, 0, 0, 0)) # Second user with strict funnel drop off, but completed the step events for a normal funnel p2 = _create_person(distinct_ids=["user_2"], team=self.team, properties={"foo": "bar"}) _create_event( event="$pageview", distinct_id="user_2", team=self.team, timestamp=timezone.now(), properties={"$session_id": "s3", "$window_id": "w1"}, event_uuid="51111111-1111-1111-1111-111111111111", ) _create_event( event="insight loaded", # Interupting event distinct_id="user_2", team=self.team, timestamp=(timezone.now() + timedelta(minutes=3)), properties={"$session_id": "s3", "$window_id": "w2"}, event_uuid="61111111-1111-1111-1111-111111111111", ) _create_event( event="insight analyzed", distinct_id="user_2", team=self.team, timestamp=(timezone.now() + timedelta(minutes=4)), properties={"$session_id": "s3", "$window_id": "w2"}, event_uuid="71111111-1111-1111-1111-111111111111", ) _create_session_recording_event(self.team.pk, "user_2", "s3", datetime(2021, 1, 2, 0, 0, 0)) # Success filter filter = Filter( data={ "insight": INSIGHT_FUNNELS, "date_from": "2021-01-01", "date_to": "2021-01-08", "funnel_order_type": "strict", "funnel_correlation_type": "properties", "events": [{"id": "$pageview", "order": 0}, {"id": "insight analyzed", "order": 1}], "include_recordings": "true", "funnel_correlation_property_values": [ {"key": "foo", "value": "bar", "operator": "exact", "type": "person"} ], "funnel_correlation_person_converted": "True", } ) _, results = FunnelCorrelationActors(filter, self.team).get_actors() self.assertEqual(len(results), 1) self.assertEqual(results[0]["id"], p1.uuid) self.assertEqual( results[0]["matched_recordings"], [ { "events": [ { "timestamp": timezone.now() + timedelta(minutes=3), "uuid": UUID("31111111-1111-1111-1111-111111111111"), "window_id": "w2", } ], "session_id": "s2", } ], ) # Drop off filter filter = Filter( data={ "insight": INSIGHT_FUNNELS, "date_from": "2021-01-01", "date_to": "2021-01-08", "funnel_order_type": "strict", "funnel_correlation_type": "properties", "events": [{"id": "$pageview", "order": 0}, {"id": "insight analyzed", "order": 1}], "include_recordings": "true", "funnel_correlation_property_values": [ {"key": "foo", "value": "bar", "operator": "exact", "type": "person"} ], "funnel_correlation_person_converted": "False", } ) _, results = FunnelCorrelationActors(filter, self.team).get_actors() self.assertEqual(results[0]["id"], p2.uuid) self.assertEqual( results[0]["matched_recordings"], [ { "events": [ { "timestamp": timezone.now(), "uuid": UUID("51111111-1111-1111-1111-111111111111"), "window_id": "w1", } ], "session_id": "s3", } ], )
def test_funnel_correlation_with_event_properties_autocapture(self): self.client.force_login(self.user) # Need a minimum of 3 hits to get a correlation result for i in range(3): _create_person(distinct_ids=[f"user_{i}"], team_id=self.team.pk) _create_event( team=self.team, event="user signed up", distinct_id=f"user_{i}", timestamp="2020-01-02T14:00:00Z", ) _create_event( team=self.team, event="$autocapture", distinct_id=f"user_{i}", elements=[ Element(nth_of_type=1, nth_child=0, tag_name="a", href="/movie") ], timestamp="2020-01-03T14:00:00Z", properties={ "signup_source": "email", "$event_type": "click" }, ) _create_event( team=self.team, event="paid", distinct_id=f"user_{i}", timestamp="2020-01-04T14:00:00Z", ) # Atleast one person that fails, to ensure we get results _create_person(distinct_ids=[f"user_fail"], team_id=self.team.pk) _create_event( team=self.team, event="user signed up", distinct_id=f"user_fail", timestamp="2020-01-02T14:00:00Z", ) with freeze_time("2020-01-01"): response = get_funnel_correlation_ok( client=self.client, team_id=self.team.pk, request=FunnelCorrelationRequest( events=json.dumps([ EventPattern(id="user signed up"), EventPattern(id="paid") ]), date_to="2020-01-14", date_from="2020-01-01", funnel_correlation_type=FunnelCorrelationType. EVENT_WITH_PROPERTIES, funnel_correlation_event_names=json.dumps(["$autocapture" ]), ), ) assert response == { "result": { "events": [ { "success_count": 3, "failure_count": 0, "success_people_url": ANY, "failure_people_url": ANY, "odds_ratio": 8.0, "correlation_type": "success", "event": { "event": '$autocapture::elements_chain::click__~~__a:href="/movie"nth-child="0"nth-of-type="1"', "properties": { "$event_type": "click" }, "elements": [{ "event": None, "text": None, "tag_name": "a", "attr_class": None, "href": "/movie", "attr_id": None, "nth_child": 0, "nth_of_type": 1, "attributes": {}, "order": 0, }], }, }, ], "skewed": False, }, "last_refresh": "2020-01-01T00:00:00Z", "is_cached": False, } assert get_people_for_correlation_ok( client=self.client, correlation=response["result"]["events"][0]) == { "success": ["user_0", "user_1", "user_2"], "failure": [], }
def create_all_events(all_events: List[dict]): for event in all_events: _create_event(**event)
def test_element(self): _create_event( event="$autocapture", team=self.team, distinct_id="whatever", properties={"attr": "some_other_val"}, elements=[ Element( tag_name="a", href="/a-url", attr_class=["small"], text="bla bla", attributes={}, nth_child=1, nth_of_type=0, ), Element(tag_name="button", attr_class=["btn", "btn-primary"], nth_child=0, nth_of_type=0), Element(tag_name="div", nth_child=0, nth_of_type=0), Element( tag_name="label", nth_child=0, nth_of_type=0, attr_id="nested", ), ], ) _create_event( event="$pageview", team=self.team, distinct_id="whatever", properties={"attr": "some_val"}, elements=[ Element( tag_name="a", href="/a-url", attr_class=["small"], text="bla bla", attributes={}, nth_child=1, nth_of_type=0, ), Element(tag_name="button", attr_class=["btn", "btn-secondary"], nth_child=0, nth_of_type=0), Element(tag_name="div", nth_child=0, nth_of_type=0), Element( tag_name="img", nth_child=0, nth_of_type=0, attr_id="nested", ), ], ) filter = Filter( data={ "events": [ { "id": "event_name", "order": 0 }, ], "properties": [{ "key": "tag_name", "value": ["label"], "operator": "exact", "type": "element" }], }) self._run_query(filter) self._run_query( filter.with_data({ "properties": [{ "key": "tag_name", "value": [], "operator": "exact", "type": "element" }], }))