From 42d32569c00b1d5315320eb90bcd4f9c77c10c47 Mon Sep 17 00:00:00 2001 From: Anirudh Pillai Date: Thu, 5 Dec 2024 17:12:45 +0000 Subject: [PATCH] fix(exports): comparisons with breakdowns (#26636) --- posthog/tasks/exports/csv_exporter.py | 14 ++- .../tasks/exports/test/test_csv_exporter.py | 112 ++++++++++++++---- 2 files changed, 98 insertions(+), 28 deletions(-) diff --git a/posthog/tasks/exports/csv_exporter.py b/posthog/tasks/exports/csv_exporter.py index 751b8f5db70cc..7657db26c203f 100644 --- a/posthog/tasks/exports/csv_exporter.py +++ b/posthog/tasks/exports/csv_exporter.py @@ -170,19 +170,21 @@ def _convert_response_to_csv_data(data: Any) -> Generator[Any, None, None]: yield line return elif isinstance(first_result.get("data"), list): + is_comparison = first_result.get("compare_label") + + # take date labels from current results, when comparing against previous + # as previous results will be indexed with offset + date_labels_item = next((x for x in results if x.get("compare_label") == "current"), None) + # TRENDS LIKE for index, item in enumerate(results): label = item.get("label", f"Series #{index + 1}") compare_label = item.get("compare_label", "") series_name = f"{label} - {compare_label}" if compare_label else label - line = {"series": series_name} - # take labels from current results, when comparing against previous - if item.get("compare_label") == "previous": - label_item = results[index - 1] - else: - label_item = item + line = {"series": series_name} + label_item = date_labels_item if is_comparison else item action = item.get("action") if isinstance(action, dict) and action.get("custom_name"): diff --git a/posthog/tasks/exports/test/test_csv_exporter.py b/posthog/tasks/exports/test/test_csv_exporter.py index 29b57da6d7a0b..4d53742ed65bb 100644 --- a/posthog/tasks/exports/test/test_csv_exporter.py +++ b/posthog/tasks/exports/test/test_csv_exporter.py @@ -2,13 +2,13 @@ from typing import Any, Optional from unittest import mock from unittest.mock import MagicMock, Mock, patch, ANY +from dateutil.relativedelta import relativedelta from openpyxl import load_workbook from io import BytesIO import pytest from boto3 import resource from botocore.client import Config -from dateutil.relativedelta import relativedelta from django.test import override_settings from django.utils.timezone import now from requests.exceptions import HTTPError @@ -703,23 +703,75 @@ def test_csv_exporter_trends_query_with_compare_previous_option( self, ) -> None: _create_person(distinct_ids=[f"user_1"], team=self.team) - events_by_person = { - "user_1": [ - { - "event": "$pageview", - "timestamp": datetime(2023, 3, 21, 13, 46), - }, - { - "event": "$pageview", - "timestamp": datetime(2023, 3, 21, 13, 46), - }, - { - "event": "$pageview", - "timestamp": datetime(2023, 3, 22, 13, 47), - }, - ], - } - journeys_for(events_by_person, self.team) + + date = datetime(2023, 3, 21, 13, 46) + date_next_week = date + relativedelta(days=7) + + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date, + properties={"$browser": "Safari"}, + ) + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date, + properties={"$browser": "Chrome"}, + ) + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date, + properties={"$browser": "Chrome"}, + ) + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date, + properties={"$browser": "Firefox"}, + ) + + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date_next_week, + properties={"$browser": "Chrome"}, + ) + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date_next_week, + properties={"$browser": "Chrome"}, + ) + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date_next_week, + properties={"$browser": "Chrome"}, + ) + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date_next_week, + properties={"$browser": "Firefox"}, + ) + _create_event( + event="$pageview", + distinct_id="1", + team=self.team, + timestamp=date_next_week, + properties={"$browser": "Firefox"}, + ) + flush_persons_and_events() exported_asset = ExportedAsset( @@ -728,7 +780,10 @@ def test_csv_exporter_trends_query_with_compare_previous_option( export_context={ "source": { "kind": "TrendsQuery", - "dateRange": {"date_to": "2023-03-22", "date_from": "2023-03-22"}, + "dateRange": { + "date_from": date.strftime("%Y-%m-%d"), + "date_to": date_next_week.strftime("%Y-%m-%d"), + }, "series": [ { "kind": "EventsNode", @@ -738,7 +793,8 @@ def test_csv_exporter_trends_query_with_compare_previous_option( }, ], "interval": "day", - "compareFilter": {"compare": True}, + "compareFilter": {"compare": True, "compare_to": "-1w"}, + "breakdownFilter": {"breakdown": "$browser", "breakdown_type": "event"}, } }, ) @@ -747,5 +803,17 @@ def test_csv_exporter_trends_query_with_compare_previous_option( with self.settings(OBJECT_STORAGE_ENABLED=True, OBJECT_STORAGE_EXPORTS_FOLDER="Test-Exports"): csv_exporter.export_tabular(exported_asset) content = object_storage.read(exported_asset.content_location) # type: ignore - lines = (content or "").strip().split("\r\n") - self.assertEqual(lines, ["series,22-Mar-2023", "$pageview - current,1", "$pageview - previous,2"]) + + lines = (content or "").strip().splitlines() + + expected_lines = [ + "series,21-Mar-2023,22-Mar-2023,23-Mar-2023,24-Mar-2023,25-Mar-2023,26-Mar-2023,27-Mar-2023,28-Mar-2023", + "Chrome - current,2.0,0.0,0.0,0.0,0.0,0.0,0.0,3.0", + "Firefox - current,1.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0", + "Safari - current,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0", + "Chrome - previous,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0", + "Firefox - previous,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0", + "Safari - previous,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0", + ] + + self.assertEqual(lines, expected_lines)