def test_test_account_filters_with_groups(self): self.team.test_account_filters = [ {"key": "key", "type": "group", "value": "value", "group_type_index": 0}, ] self.team.save() GroupTypeMapping.objects.create(team=self.team, group_type="organization", group_type_index=0) create_group(self.team.pk, group_type_index=0, group_key="in", properties={"key": "value"}) create_group(self.team.pk, group_type_index=0, group_key="out", properties={"key": "othervalue"}) with freeze_time("2020-01-11T12:00:00Z"): Person.objects.create(distinct_ids=["person1"], team_id=self.team.pk) with freeze_time("2020-01-09T12:00:00Z"): Person.objects.create(distinct_ids=["person2"], team_id=self.team.pk) journeys_for( { "person1": [ {"event": "$pageview", "timestamp": datetime(2020, 1, 11, 12), "properties": {"$group_0": "out"},}, ], "person2": [ {"event": "$pageview", "timestamp": datetime(2020, 1, 9, 12), "properties": {"$group_0": "in"},}, {"event": "$pageview", "timestamp": datetime(2020, 1, 12, 12), "properties": {"$group_0": "in"},}, {"event": "$pageview", "timestamp": datetime(2020, 1, 15, 12), "properties": {"$group_0": "in"},}, ], }, self.team, ) result = ClickhouseTrends().run( Filter( data={ "date_from": "2020-01-12T00:00:00Z", "date_to": "2020-01-19T00:00:00Z", "events": [{"id": "$pageview", "type": "events", "order": 0}], "shown_as": TRENDS_LIFECYCLE, FILTER_TEST_ACCOUNTS: True, }, team=self.team, ), self.team, ) self.assertLifecycleResults( result, [ {"status": "dormant", "data": [0, -1, 0, 0, -1, 0, 0, 0]}, {"status": "new", "data": [0, 0, 0, 0, 0, 0, 0, 0]}, {"status": "resurrecting", "data": [1, 0, 0, 1, 0, 0, 0, 0]}, {"status": "returning", "data": [0, 0, 0, 0, 0, 0, 0, 0]}, ], )
def test_groups_usage(self) -> None: 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"}) with freeze_time("2021-11-11 00:30:00"): _create_event( event="event", lib="web", distinct_id="user_1", team=self.team, timestamp="2021-11-10 02:00:00", properties={"$group_0": "org:5"}, ) _create_event( event="event", lib="web", distinct_id="user_1", team=self.team, timestamp="2021-11-10 05:00:00", properties={"$group_0": "org:6"}, ) _create_event( event="event", lib="web", distinct_id="user_7", team=self.team, timestamp="2021-11-10 10:00:00", ) all_reports = send_all_reports(dry_run=True) org_report = self.select_report_by_org_id( str(self.organization.id), all_reports) self.assertEqual(org_report["group_types_total"], 2) self.assertEqual(org_report["event_count_in_month"], 3) self.assertEqual(org_report["event_count_with_groups_month"], 2)
def test_delete_groups(self): create_group(self.teams[0].pk, 0, "g0") create_group(self.teams[1].pk, 1, "g1") create_group(self.teams[2].pk, 2, "g2") delete_teams_data([self.teams[0].pk, self.teams[1].pk]) self.assertEqual(self.select_remaining("groups", "group_key"), ["g2"])
def test_empty_property_values(self): 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="org:1", properties={"industry": "finance"}) response = self.client.get( f"/api/projects/{self.team.id}/groups/property_values/?key=name&group_type_index=0" ).json() self.assertEqual(len(response), 0) self.assertEqual(response, [])
def test_aggregate_by_groups(self): self._create_multiple_people( period=timedelta(weeks=1), event_properties=lambda i: {"$group_0": f"org:{i // 2}"}, ) create_group(team_id=self.team.pk, group_type_index=0, group_key=f"org:0", properties={"industry": "technology"}) create_group(team_id=self.team.pk, group_type_index=0, group_key=f"org:1", properties={"industry": "agriculture"}) create_group(team_id=self.team.pk, group_type_index=0, group_key=f"org:2", properties={"industry": "technology"}) with freeze_time("2020-02-15T13:01:01Z"): data = get_stickiness_time_series_ok( client=self.client, team=self.team, request={ "shown_as": "Stickiness", "date_from": "2020-01-01", "date_to": "2020-02-15", "events": [{ "id": "watched movie", "math": "unique_group", "math_group_type_index": 0 }], "interval": "week", }, ) assert data["watched movie"][1].value == 2 assert data["watched movie"][2].value == 0 assert data["watched movie"][3].value == 1 with freeze_time("2020-02-15T13:01:01Z"): week1_actors = get_people_from_url_ok( self.client, data["watched movie"][1].person_url) week2_actors = get_people_from_url_ok( self.client, data["watched movie"][2].person_url) week3_actors = get_people_from_url_ok( self.client, data["watched movie"][3].person_url) assert sorted([p["id"] for p in week1_actors]) == sorted(["org:0", "org:2"]) assert sorted([p["id"] for p in week2_actors]) == sorted([]) assert sorted([p["id"] for p in week3_actors]) == sorted(["org:1"])
def test_retrieve_group(self): create_group( team_id=self.team.pk, group_type_index=0, group_key="key", properties={"industry": "finance", "name": "Mr. Krabs"}, ) create_group( team_id=self.team.pk, group_type_index=1, group_key="foo//bar", properties={}, ) fail_response = self.client.get(f"/api/projects/{self.team.id}/groups/find?group_type_index=1&group_key=key") self.assertEqual(fail_response.status_code, 404) ok_response = self.client.get(f"/api/projects/{self.team.id}/groups/find?group_type_index=0&group_key=key") self.assertEqual(ok_response.status_code, 200) self.assertEqual( ok_response.json(), { "created_at": "2021-05-02T00:00:00Z", "group_key": "key", "group_properties": {"industry": "finance", "name": "Mr. Krabs"}, "group_type_index": 0, }, ) ok_response = self.client.get(f"/api/projects/{self.team.id}/groups/find?group_type_index=1&group_key=foo//bar") self.assertEqual(ok_response.status_code, 200) self.assertEqual( ok_response.json(), { "created_at": "2021-05-02T00:00:00Z", "group_key": "foo//bar", "group_properties": {}, "group_type_index": 1, }, )
def test_property_definitions(self): create_group( team_id=self.team.pk, group_type_index=0, group_key="org:5", properties={"industry": "finance", "name": "Mr. Krabs"}, ) 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={"name": "Plankton"}) create_group(team_id=self.team.pk, group_type_index=1, group_key="company:2", properties={}) response = self.client.get(f"/api/projects/{self.team.id}/groups/property_definitions").json() self.assertEqual( response, { "0": [{"name": "industry", "count": 2}, {"name": "name", "count": 1}], "1": [{"name": "name", "count": 1}], }, )
def _create_groups(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=0, group_key="org:7", properties={"industry": "finance"}) create_group(team_id=self.team.pk, group_type_index=1, group_key="company:10", properties={"industry": "finance"})
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 test_groups_list(self): with freeze_time("2021-05-01"): create_group( team_id=self.team.pk, group_type_index=0, group_key="org:5", properties={"industry": "finance", "name": "Mr. Krabs"}, ) with freeze_time("2021-05-02"): 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={"name": "Plankton"}, ) response = self.client.get(f"/api/projects/{self.team.id}/groups?group_type_index=0").json() self.assertEqual( response, { "next": None, "previous": None, "results": [ { "created_at": "2021-05-02T00:00:00Z", "group_key": "org:6", "group_properties": {"industry": "technology"}, "group_type_index": 0, }, { "created_at": "2021-05-01T00:00:00Z", "group_key": "org:5", "group_properties": {"industry": "finance", "name": "Mr. Krabs"}, "group_type_index": 0, }, ], }, )
def test_unordered_funnel_with_groups(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={}) create_group(team_id=self.team.pk, group_type_index=1, group_key="company:2", properties={}) filters = { "events": [ { "id": "user signed up", "type": "events", "order": 0 }, { "id": "paid", "type": "events", "order": 1 }, ], "insight": INSIGHT_FUNNELS, "aggregation_group_type_index": 0, "date_from": "2020-01-01", "date_to": "2020-01-14", } filter = Filter(data=filters, team=self.team) funnel = ClickhouseFunnelUnordered(filter, self.team) _create_person(distinct_ids=["user_1"], team_id=self.team.pk) _create_event( team=self.team, event="user signed up", distinct_id="user_1", timestamp="2020-01-03T14:00:00Z", properties={"$group_0": "org:5"}, ) # different person, same group, so should count as step two in funnel _create_person(distinct_ids=["user_2"], team_id=self.team.pk) _create_event( team=self.team, event="paid", distinct_id="user_2", timestamp="2020-01-02T14:00:00Z", properties={"$group_0": "org:5"}, ) # same person, different group, so should count as different step 1 in funnel _create_event( team=self.team, event="user signed up", distinct_id="user_1", timestamp="2020-01-10T14:00:00Z", properties={"$group_0": "org:6"}, ) result = funnel.run() self.assertEqual(result[0]["name"], "user signed up") self.assertEqual(result[0]["count"], 2) self.assertEqual(result[1]["name"], "paid") self.assertEqual(result[1]["count"], 1)
def test_breakdown_group_props(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=0, group_key="org:7", properties={"industry": "finance"}) create_group(team_id=self.team.pk, group_type_index=0, group_key="org:8", properties={ "industry": "another", "out": 1 }) create_group(team_id=self.team.pk, group_type_index=1, group_key="company:10", properties={"industry": "foobar"}) # :TRICKY: Test group type overlapping create_group(team_id=self.team.pk, group_type_index=1, group_key="org:8", properties={"industry": "foobar"}) for org_index in range(5, 9): _create_event( event="$pageview", distinct_id="person1", team=self.team, properties={"$group_0": f"org:{org_index}"}, timestamp="2020-01-02T12:00:00Z", ) 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": "$pageview", "type": "events", "order": 0, }], "properties": [{ "key": "out", "value": "", "type": "group", "group_type_index": 0, "operator": "is_not_set" }], }, team=self.team, ) result = get_breakdown_prop_values(filter, filter.entities[0], "count(*)", self.team.pk, 5) self.assertEqual(result, ["finance", "technology"])
def test_group_query_includes_recording_events(self): GroupTypeMapping.objects.create(team=self.team, group_type="organization", group_type_index=0) create_group(team_id=self.team.pk, group_type_index=0, group_key="bla", properties={}) _create_session_recording_event( self.team.pk, "u1", "s1", timestamp=timezone.now(), ) _create_event( event="pageview", distinct_id="u1", team=self.team, timestamp=timezone.now(), properties={"$group_0": "bla"}, ) _create_event( event="pageview", distinct_id="u1", team=self.team, timestamp=timezone.now() + relativedelta(hours=2), properties={ "$session_id": "s1", "$window_id": "w1", "$group_0": "bla" }, uuid="b06e5a5e-e001-4293-af81-ac73e194569d", ) event = { "id": "pageview", "name": "pageview", "type": "events", "order": 0, "math": "unique_group", "math_group_type_index": 0, } filter = Filter( data={ "date_from": "2021-01-21T00:00:00Z", "date_to": "2021-01-22T00:00:00Z", "events": [event], "include_recordings": "true", }) entity = Entity(event) _, serialized_actors = ClickhouseTrendsActors(self.team, entity, filter).get_actors() self.assertCountEqual( serialized_actors[0].get("matched_recordings", []), [{ "session_id": "s1", "events": [{ "window_id": "w1", "timestamp": timezone.now() + relativedelta(hours=2), "uuid": UUID("b06e5a5e-e001-4293-af81-ac73e194569d"), }], }], )
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") p1 = Person.objects.create(uuid=uuid, team_id=self.team.pk, distinct_ids=["1", "2"]) p2 = Person.objects.create(team_id=self.team.pk, distinct_ids=["3"]) p3 = 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_filter_by_group_properties(self): p1, p2, p3, p4 = self._create_multiple_people( period=timedelta(weeks=1), event_properties=lambda i: { "$group_0": f"org:{i}", "$group_1": "instance:1" }, ) create_group(team_id=self.team.pk, group_type_index=0, group_key=f"org:1", properties={"industry": "technology"}) create_group(team_id=self.team.pk, group_type_index=0, group_key=f"org:2", properties={"industry": "agriculture"}) create_group(team_id=self.team.pk, group_type_index=0, group_key=f"org:3", properties={"industry": "technology"}) create_group(team_id=self.team.pk, group_type_index=1, group_key=f"company:1", properties={"industry": "technology"}) with freeze_time("2020-02-15T13:01:01Z"): data = get_stickiness_time_series_ok( client=self.client, team=self.team, request={ "shown_as": "Stickiness", "date_from": "2020-01-01", "date_to": "2020-02-15", "events": [{ "id": "watched movie" }], "properties": [{ "key": "industry", "value": "technology", "type": "group", "group_type_index": 0 }], "interval": "week", }, ) assert data["watched movie"][1].value == 1 assert data["watched movie"][2].value == 0 assert data["watched movie"][3].value == 1 with freeze_time("2020-02-15T13:01:01Z"): week1_actors = get_people_from_url_ok( self.client, data["watched movie"][1].person_url) week2_actors = get_people_from_url_ok( self.client, data["watched movie"][2].person_url) week3_actors = get_people_from_url_ok( self.client, data["watched movie"][3].person_url) assert sorted([p["id"] for p in week1_actors]) == sorted([str(p1.pk)]) assert sorted([p["id"] for p in week2_actors]) == sorted([]) assert sorted([p["id"] for p in week3_actors]) == sorted([str(p3.pk)])
def _create_groups_and_events(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={}) create_group(team_id=self.team.pk, group_type_index=1, group_key="company:2", properties={}) Person.objects.create(team=self.team, distinct_ids=["person1", "alias1"]) Person.objects.create(team=self.team, distinct_ids=["person2"]) Person.objects.create(team=self.team, distinct_ids=["person3"]) self._create_events([ ("person1", self._date(0), { "$group_0": "org:5", "$group_1": "company:1" }), ("person2", self._date(0), { "$group_0": "org:6" }), ("person3", self._date(0)), ("person1", self._date(1), { "$group_0": "org:5" }), ("person2", self._date(1), { "$group_0": "org:6" }), ("person1", self._date(7), { "$group_0": "org:5" }), ("person2", self._date(7), { "$group_0": "org:6" }), ("person1", self._date(14), { "$group_0": "org:5" }), ("person1", self._date(month=1, day=-6), { "$group_0": "org:5", "$group_1": "company:1" }), ("person2", self._date(month=1, day=-6), { "$group_0": "org:6" }), ("person2", self._date(month=1, day=1), { "$group_0": "org:6" }), ("person1", self._date(month=1, day=1), { "$group_0": "org:5" }), ("person2", self._date(month=1, day=15), { "$group_0": "org:6", "$group_1": "company:1" }), ])
def test_unordered_funnel_with_groups(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={}) create_group(team_id=self.team.pk, group_type_index=1, group_key="company:2", properties={}) filters = { "events": [ { "id": "user signed up", "type": "events", "order": 0 }, { "id": "paid", "type": "events", "order": 1 }, ], "insight": INSIGHT_FUNNELS, "aggregation_group_type_index": 0, "date_from": "2020-01-01", "date_to": "2020-01-14", "funnel_order_type": "unordered", } events_by_person = { "user_1": [ {"event": "user signed up", "timestamp": datetime(2020, 1, 3, 14), "properties": {"$group_0": "org:5"}}, { # same person, different group, so should count as different step 1 in funnel "event": "user signed up", "timestamp": datetime(2020, 1, 10, 14), "properties": {"$group_0": "org:6"}, }, ], "user_2": [ { # different person, same group, so should count as step two in funnel "event": "paid", "timestamp": datetime(2020, 1, 2, 14), "properties": {"$group_0": "org:5"}, } ], } created_people = journeys_for(events_by_person, self.team) params = FunnelRequest( events=json.dumps([ EventPattern(id="user signed up", type="events", order=0), EventPattern(id="paid", type="events", order=1), ]), date_from="2020-01-01", date_to="2020-01-14", aggregation_group_type_index=0, funnel_order_type="unordered", insight=INSIGHT_FUNNELS, ) result = get_funnel_ok(self.client, self.team.pk, params) assert result["user signed up"]["count"] == 2 assert result["paid"]["count"] == 1 assert result["paid"]["average_conversion_time"] == 86400 actors = get_funnel_actors_ok( self.client, result["user signed up"]["converted_people_url"]) assert len(actors) == 2