"""Integration tests for video and channel endpoints. Endpoints tested: - /top-video-metrics (TestTopVideoMetrics) - /top-channel-metrics (TestTopChannelMetrics) - /ugc-video-metrics (TestUgcVideoMetrics) - /videos//top-countries (TestTopCountriesVideo) - /channels//top-countries (TestTopCountriesChannels) - /videos//top-traffic-sources (TestTopVideoTrafficSources) - /channels//top-traffic-sources (TestTopChannelTrafficSources) - /channels//top-videos (TestChannelTopVideos) - /video-metrics-bulk (TestVideoMetricsBulk) - /all-time-video-metrics/ (TestAllTimeVideoMetrics) - /channel-metrics/ (TestChannelMetrics) - /all-time-channel-metrics/ (TestAllTimeChannelMetrics) Every test class parametrizes shape checks on ALL_HEADERS (6 auth profiles) and adds an emptiness test that asserts the response is populated for headers with access to the test entity (a Frenchkiss-owned video / channel / ISRC) and empty otherwise. """ import pytest from analytics import config from analytics.config import BASE_URL from tests.integration.endpoints.conftest import ( ALL_HEADERS, FRENCHKISS, FRENCHKISS_CHANNEL_ID, FRENCHKISS_DATE_RANGE, FRENCHKISS_UGC_ISRC, FRENCHKISS_VIDEO_ID, INSIGHTS_D3, INSIGHTS_EMPLOYEE, INSIGHTS_LABEL, INSIGHTS_LABEL_AND_SUBACCOUNT, assert_endpoint, has_video_access, ) class TestTopVideoMetrics: """Integration tests for /top-video-metrics. Verifies top video metrics with various filter combinations: country codes, participant IDs, and channel IDs. Groups: 1. Default and filtered params — response shape (30 tests) """ def _url(self, params=""): return config.TOP_VIDEO_METRICS_URL + params # ── Group 1: Default and filtered params ────────────────────────── # # 6 headers × 5 param variants = 30 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "params", [ pytest.param("", id="defaults"), pytest.param( "?limit=10&offset=0&country_code=UA&country_code=NO" "&country_code=DE&country_code=US&country_code=GB" "&order_by=views_1_month_back&order_dir=ASC", id="country_and_ordering", ), pytest.param( "?limit=10&offset=0&country_code=UA&country_code=NO" "&country_code=DE&country_code=US&country_code=GB" "&order_by=views_1_month_back&order_dir=ASC" "&global_participant_ids=90097833-cc23-470e-8643-2268e156497f", id="participant_and_country", ), pytest.param( "?limit=10&offset=0" "&order_by=views_1_month_back&order_dir=ASC" "&global_participant_ids=90097833-cc23-470e-8643-2268e156497f", id="participant_only", ), pytest.param( "?limit=10&offset=0" "&order_by=views_1_month_back&order_dir=ASC" "&channel_ids=UC3OgJ6pt7VmQa9WIL9GTAQg", id="channel_filter", ), ], ) def test_top_video_metrics(self, hdrs, params): """Top video metrics returns items with all expected fields. Exercises 5 code paths: default, country filter, participant+country, participant only, and channel filter. Each applies different SQL WHERE clauses. """ payload = assert_endpoint( self._url(params), headers=hdrs, expect_payload_keys=[ "items", "sources", "total_results", "last_available_date", ], ) assert isinstance(payload["items"], list) if payload["items"]: for field in [ "video_id", "channel_id", "subscriber_count", "total_views", "total_estimated_gross_revenue", "average_view_duration_seconds", "views_1_month_back", "growth_2_to_1_months_back", "views_2_months_back", "growth_3_to_2_months_back", "views_3_months_back", "growth_4_to_3_months_back", "views_last_28_days", "views_last_7_days", ]: assert field in payload["items"][0] @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_top_video_metrics_emptiness(self, hdrs): """Response is populated iff the caller has access to the channel. Scopes the query to a Frenchkiss-only channel. Headers in ACCESS_RULES[6971] (excluding artist) match the page filter's per-row IFF; everyone else either fails the IFF (other label users) or short-circuits to ``clause = " false "`` (subaccount, artist). Combined-grant callers (label_and_subaccount) see data because the model skips auto-populating the permission-derived subaccount filter when label_ids is non-empty. """ url = self._url(f"?channel_ids={FRENCHKISS_CHANNEL_ID}") payload = assert_endpoint( url, headers=hdrs, expect_payload_keys=[ "items", "sources", "total_results", "last_available_date", ], ) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert payload["items"], "non-empty expected" else: assert payload["items"] == [], "empty expected" class TestTopChannelMetrics: """Integration tests for /top-channel-metrics. Verifies top channel metrics with various filter combinations: country codes and participant IDs. Groups: 1. Default and filtered params — response shape (24 tests) """ def _url(self, params=""): return config.TOP_CHANNEL_METRICS_URL + params # ── Group 1: Default and filtered params ────────────────────────── # # 6 headers × 4 param variants = 24 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "params", [ pytest.param("", id="defaults"), pytest.param( "?limit=10&offset=0&country_code=UA&country_code=NO" "&country_code=DE&country_code=US&country_code=GB" "&order_by=views_1_month_back&order_dir=ASC", id="country_and_ordering", ), pytest.param( "?limit=10&offset=0&country_code=UA&country_code=NO" "&country_code=DE&country_code=US&country_code=GB" "&order_by=views_1_month_back&order_dir=ASC" "&global_participant_ids=90097833-cc23-470e-8643-2268e156497f", id="participant_and_country", ), pytest.param( "?limit=10&offset=0" "&order_by=views_1_month_back&order_dir=ASC" "&global_participant_ids=90097833-cc23-470e-8643-2268e156497f", id="participant_only", ), ], ) def test_top_channel_metrics(self, hdrs, params): """Top channel metrics returns items with expected fields. Exercises default, country filter, participant+country, and participant only code paths. """ payload = assert_endpoint( self._url(params), headers=hdrs, expect_payload_keys=[ "items", "total_results", "last_available_date", "sources", ], ) if payload["items"]: for field in [ "channel_id", "subscriber_count", "total_views", "views_1_month_back", ]: assert field in payload["items"][0] @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_top_channel_metrics_emptiness(self, hdrs): """Listing returns channels iff the caller has any label access. Employee (full access), single-label profiles (D3 / RIMAS, label / Frenchkiss), and combined-grant profiles (label_and_subaccount) see their own catalog. Subaccount-only and artist-only callers hit the page filter's ``clause = " false "`` short-circuit and see empty. """ payload = assert_endpoint( self._url(), headers=hdrs, expect_payload_keys=[ "items", "total_results", "last_available_date", "sources", ], ) if hdrs in ( INSIGHTS_EMPLOYEE, INSIGHTS_D3, INSIGHTS_LABEL, INSIGHTS_LABEL_AND_SUBACCOUNT, ): assert payload["items"], "non-empty expected" else: assert payload["items"] == [], "empty expected" class TestUgcVideoMetrics: """Integration tests for /ugc-video-metrics. Verifies UGC video metrics with filtered params. The endpoint cannot serve unfiltered requests for employees (full-catalog profiles): the SQL aggregates the entire V_METRICS_UGC_BY_VIDEO_ASSET_FEED_DISTRIBUTOR_ROLLUP view before LIMIT is applied, which times out. Every variant therefore includes at least a narrowing filter (track_isrcs or asset_ids). Note: ``claim_statuses=blocked`` is broken on master and QA — the BLOCKED branch references ``s.claim_policy`` which does not exist on ``V_METRICS_UGC_BY_VIDEO_ASSET_FEED_DISTRIBUTOR_ROLLUP``. The migration preserves this bug verbatim and is not in scope to fix. Groups: 1. Filtered params — response shape (24 tests) 2. Emptiness against Frenchkiss ISRC (6 tests) """ def _url(self, params=""): return config.UGC_VIDEO_METRICS_URL + params # ── Group 1: Filtered params ────────────────────────────────────── # # 6 headers × 4 param variants = 24 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "params", [ pytest.param( "?limit=10&track_isrcs=USXDR1700554", id="isrc_only", ), pytest.param( "?offset=0&store_ids=453&asset_ids=A511674538219960" "&limit=10&track_ids=23754052&track_isrcs=USXDR1700554" "&countries=US&claim_types=AUDIO&claim_statuses=ACTIVE", id="all_filters", ), pytest.param( "?limit=10&track_isrcs=USXDR1700554&countries=US", id="country_only", ), pytest.param( "?limit=10&track_isrcs=USXDR1700554" "&order_by=premium_views&order_dir=ASC", id="custom_ordering", ), ], ) def test_ugc_video_metrics(self, hdrs, params): """UGC video metrics returns items with expected fields. Variants exercise distinct SQL branches: - isrc_only: no-country view branch. - all_filters: by-country view + every filter subquery. - country_only: by-country view without auxiliary filters. - custom_ordering: order_by/order_dir whitelist branch. Unauthorized profiles may return only {"items": []} without total_results or sources. """ payload = assert_endpoint( self._url(params), headers=hdrs, items_key=None, ) assert "items" in payload if payload["items"]: assert "total_results" in payload assert "sources" in payload for field in [ "video_id", "asset_id", "channel_id", "track_id", "track_isrc", "views", "claim_type", "claim_status", ]: assert field in payload["items"][0] @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_ugc_video_metrics_emptiness(self, hdrs): """Response is populated iff the caller has access to the ISRC. Scopes the query to a Frenchkiss-only ISRC. The dim_release permission filter matches Frenchkiss label/label-and-subaccount, and full access matches employee. Everyone else (D3, subaccount, artist) has no overlap with the Frenchkiss release row, so ``items`` comes back empty. """ url = self._url(f"?limit=10&track_isrcs={FRENCHKISS_UGC_ISRC}") payload = assert_endpoint(url, headers=hdrs, items_key=None) items = payload.get("items", []) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert items, "non-empty expected" else: assert items == [], "empty expected" class TestTopCountriesVideo: """Integration tests for /videos//top-countries. Each variant exercises a distinct code path (date-range vs HIGHWATERMARK − 28 days fallback, store intersection, distributor IN tightening). Groups: 1. Query variants — 5 variants × 6 headers = 30 tests """ VIDEO_ID = "5bfseWNmlds" QUERY_VARIANTS = [ pytest.param("", id="defaults"), pytest.param("?start_date=2019-11-01&days=28", id="custom_dates"), pytest.param( "?start_date=2019-11-01&days=28&store_ids=453", id="store_filter", ), pytest.param( "?start_date=2019-11-01&days=28&distributors=theorchard", id="distributors_filter", ), pytest.param( "?start_date=2019-11-01&days=28&store_ids=453&distributors=theorchard", id="all_filters", ), ] def _url(self, params=""): return ( config.TOP_COUNTRIES_VIDEOS_URL.replace("", self.VIDEO_ID) + params ) # ── Group 1: Query variants ─────────────────────────────────────── # # 6 headers × 5 variants = 30 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize("params", QUERY_VARIANTS) def test_top_countries(self, hdrs, params): """Top countries for video returns expected payload keys. Default uses HIGHWATERMARK − 28 days fallback. Other variants exercise the date-range, store intersection, and distributor IN tightening SQL branches. """ assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=["video_id", "top_countries_videos", "sources"], ) @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_top_countries_emptiness(self, hdrs): """Response is populated iff the caller has access to the video. Uses a Frenchkiss-owned video and a 2024 date range with stable QA data. Guards against the single-video_id branch of the permissions_filter_video_or_channel macro regressing to always-FALSE (which would silently empty every label user) and against the early-return guard regressing to always-fall-through (which would silently leak data to artists). """ url = ( config.TOP_COUNTRIES_VIDEOS_URL.replace("", FRENCHKISS_VIDEO_ID) + FRENCHKISS_DATE_RANGE ) payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=["video_id", "top_countries_videos", "sources"], ) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert payload["top_countries_videos"], "non-empty expected" else: assert payload["top_countries_videos"] == [], "empty expected" class TestTopCountriesChannels: """Integration tests for /channels//top-countries. Each variant exercises a distinct code path (date-range vs HIGHWATERMARK − 28 days fallback, distributor IN tightening). This endpoint has no store_id filter on the SQL — YouTube is the only store. Groups: 1. Query variants — 4 variants × 6 headers = 24 tests """ CHANNEL_ID = "UCFg7-w47VVA3ozhvnR6P0YQ" QUERY_VARIANTS = [ pytest.param("", id="defaults"), pytest.param("?start_date=2019-11-01&days=28", id="custom_dates"), pytest.param( "?start_date=2019-11-01&days=28&distributors=theorchard", id="distributors_filter", ), pytest.param( "?start_date=2019-11-01&end_date=2019-12-01", id="explicit_end_date", ), ] def _url(self, params=""): return ( config.TOP_COUNTRIES_CHANNELS_URL.replace("", self.CHANNEL_ID) + params ) # ── Group 1: Query variants ─────────────────────────────────────── # # 6 headers × 4 variants = 24 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize("params", QUERY_VARIANTS) def test_top_countries(self, hdrs, params): """Top countries for channel returns expected payload keys. Default uses HIGHWATERMARK − 28 days fallback. Other variants exercise the date-range and distributor IN tightening branches. """ assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=["channel_id", "top_countries_channels", "sources"], ) @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_top_countries_emptiness(self, hdrs): """Response is populated iff the caller has access to the channel. Channel is Frenchkiss-only. Guards the channel_level branch of the permissions_filter_video_or_channel macro and the early return for callers without label_ids (subaccount, artist). """ url = ( config.TOP_COUNTRIES_CHANNELS_URL.replace( "", FRENCHKISS_CHANNEL_ID ) + FRENCHKISS_DATE_RANGE ) payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=["channel_id", "top_countries_channels", "sources"], ) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert payload["top_countries_channels"], "non-empty expected" else: assert payload["top_countries_channels"] == [], "empty expected" class TestTopVideoTrafficSources: """Integration tests for /videos//top-traffic-sources. Verifies traffic sources for a video with default and custom date params. Groups: 1. Default and date-filtered params (12 tests) """ VIDEO_ID = "5bfseWNmlds" def _url(self, params=""): return ( config.TOP_VIDEO_TRAFFIC_SOURCES_URL.replace("", self.VIDEO_ID) + params ) # ── Group 1: Default and date-filtered params ───────────────────── # # 6 headers × 2 date variants = 12 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "params", [ pytest.param("", id="defaults"), pytest.param("?start_date=2019-11-01&days=28", id="custom_dates"), ], ) def test_traffic_sources(self, hdrs, params): """Traffic sources for video returns expected payload keys. Default uses server-side date defaults. Custom dates exercise the date-range code path. """ assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=[ "video_id", "top_video_traffic_sources", "sources", ], ) @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_traffic_sources_emptiness(self, hdrs): """Response is populated iff the caller has access to the video. Uses a Frenchkiss-owned video. Guards against two known regressions: the macro's single-video_id branch always-FALSE bug (which would empty every label user), and the leak path in which the logic forgets to thread video_id into the macro (the IFF then evaluates to TRUE for any label user, leaking data across vendors). """ url = ( config.TOP_VIDEO_TRAFFIC_SOURCES_URL.replace( "", FRENCHKISS_VIDEO_ID ) + FRENCHKISS_DATE_RANGE ) payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=[ "video_id", "top_video_traffic_sources", "sources", ], ) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert payload["top_video_traffic_sources"], "non-empty expected" else: assert payload["top_video_traffic_sources"] == [], "empty expected" class TestTopChannelTrafficSources: """Integration tests for /channels//top-traffic-sources. Each variant hits a distinct SQL branch (DAILY vs ROLLUP view switch driven by date-range presence, country view switch, distributor IN tightening, explicit limit). Groups: 1. Query variants — 6 variants × 6 headers = 36 tests """ CHANNEL_ID = "UCFg7-w47VVA3ozhvnR6P0YQ" QUERY_VARIANTS = [ pytest.param("", id="all_time_defaults"), pytest.param( "?start_date=2019-11-01&days=28", id="custom_dates", ), pytest.param( "?country_code=US&country_code=GB", id="all_time_country", ), pytest.param( "?start_date=2019-11-01&days=28&country_code=US", id="dates_with_country", ), pytest.param( "?start_date=2019-11-01&days=28&distributors=theorchard", id="distributors_filter", ), pytest.param( "?start_date=2019-11-01&days=28&limit=10", id="explicit_limit", ), ] def _url(self, params=""): return ( config.TOP_CHANNEL_TRAFFIC_SOURCES_URL.replace( "", self.CHANNEL_ID ) + params ) # ── Group 1: Query variants ─────────────────────────────────────── # # 6 headers × 6 variants = 36 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize("params", QUERY_VARIANTS) def test_traffic_sources(self, hdrs, params): """Traffic sources for channel returns expected payload keys. Each variant exercises a distinct SQL branch (DAILY vs ROLLUP view switch, country view switch, distributor tightening, explicit limit). """ assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=[ "channel_id", "top_channel_traffic_sources", "sources", ], ) @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_traffic_sources_emptiness(self, hdrs): """Response is populated iff the caller has access to the channel. Channel is Frenchkiss-only. Exercises the channel_level macro branch and the early return for callers without label_ids. """ url = config.TOP_CHANNEL_TRAFFIC_SOURCES_URL.replace( "", FRENCHKISS_CHANNEL_ID ) payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=[ "channel_id", "top_channel_traffic_sources", "sources", ], ) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert payload["top_channel_traffic_sources"], "non-empty expected" else: assert payload["top_channel_traffic_sources"] == [], "empty expected" class TestChannelTopVideos: """Integration tests for /channels//top-videos. Verifies top videos for a channel with country filter and date param variants. Groups: 1. Top videos with filter and date variants (24 tests) """ CHANNEL_ID = "UCpKMJ-rqmy2M5olwH_HwaDQ" def _url(self, params=""): url = config.TOP_CHANNEL_VIDEOS_URL.replace("", self.CHANNEL_ID) return url + params # ── Group 1: Top videos with filter and date variants ───────────── # # 6 headers × 4 param variants = 24 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "params", [ pytest.param("", id="no_filter"), pytest.param( "?country_code=UA&country_code=NO" "&country_code=DE&country_code=US&country_code=GB", id="multi_country", ), pytest.param("?start_date=2019-11-01&days=28", id="custom_dates"), pytest.param( "?days=0&start_date=HIGHWATERMARK", id="all_time_highwatermark" ), ], ) def test_channel_top_videos(self, hdrs, params): """Top channel videos returns list with expected metric fields. Without params returns global top videos. Country filter narrows results. Date params exercise the date-range code path. """ payload = assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=["channel_id", "top_channel_videos", "sources"], ) assert isinstance(payload["top_channel_videos"], list) if payload["top_channel_videos"]: for field in [ "averageViewDurationPercentage", "averageViewDurationSeconds", "premiumViews", ]: assert field in payload["top_channel_videos"][0] @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_channel_top_videos_emptiness(self, hdrs): """Response is populated iff the caller has access to the channel. Channel is Frenchkiss-only. Exercises the channel_level macro branch and the early return for callers without label_ids. """ url = config.TOP_CHANNEL_VIDEOS_URL.replace( "", FRENCHKISS_CHANNEL_ID ) payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=["channel_id", "top_channel_videos", "sources"], ) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert payload["top_channel_videos"], "non-empty expected" else: assert payload["top_channel_videos"] == [], "empty expected" class TestVideoMetricsBulk: """Integration tests for /video-metrics-bulk. Verifies bulk video metrics retrieval with and without country filters. Groups: 1. Bulk metrics with filter variants (12 tests) """ VIDEO_IDS = ["HekrZ0QcI3g", "Cr8K88UcO0s"] # ── Group 1: Bulk metrics with filter variants ──────────────────── # # 6 headers × 2 body variants = 12 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "body", [ pytest.param( { "params": { "start_date": "2024-11-01", "days": 1, "video_ids": ["HekrZ0QcI3g", "Cr8K88UcO0s"], } }, id="no_country", ), pytest.param( { "params": { "start_date": "2024-11-01", "days": 28, "video_ids": ["HekrZ0QcI3g", "Cr8K88UcO0s"], "country_ids": ["US", "MX"], } }, id="with_countries", ), ], ) def test_video_metrics_bulk(self, hdrs, body): """Bulk video metrics returns per-video data with all expected keys. Each video ID in the response must have aggregate_video_metrics, sources, and video_metrics keys. Country filter narrows the aggregation to specified countries. """ payload = assert_endpoint( f"{BASE_URL}/video-metrics-bulk", headers=hdrs, method="POST", json_body=body, items_key=None, ) assert len(payload) == 2 for video_id in self.VIDEO_IDS: assert "aggregate_video_metrics" in payload[video_id] assert "sources" in payload[video_id] assert "video_metrics" in payload[video_id] @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_video_metrics_bulk_emptiness(self, hdrs): """Per-video timeseries is populated iff the caller has access. Bulk takes a different code path from the single-video endpoints: callers without label_ids get a sentinel ``permission_label_ids = []`` injected before the SQL runs, so the macro returns FALSE and the response carries the empty defaults from ``empty_item`` (``video_metrics == []``, aggregate views=0). Callers with label_ids that match the macro see a populated timeseries. """ body = { "params": { "start_date": "2024-01-01", "days": 31, "video_ids": [FRENCHKISS_VIDEO_ID], } } payload = assert_endpoint( f"{BASE_URL}/video-metrics-bulk", headers=hdrs, method="POST", json_body=body, items_key=None, ) metrics = payload[FRENCHKISS_VIDEO_ID] if has_video_access(hdrs, FRENCHKISS["account_id"]): assert metrics["video_metrics"], "non-empty expected" else: assert metrics["video_metrics"] == [], "empty expected" class TestAllTimeVideoMetrics: """Integration tests for /all-time-video-metrics/. Each variant exercises a distinct SQL branch (country view switch on country_code presence, store intersection, distributor IN tightening). Groups: 1. Query variants — 5 variants × 6 headers = 30 tests """ VIDEO_ID = "5bfseWNmlds" QUERY_VARIANTS = [ pytest.param("", id="defaults"), pytest.param( "?country_code=US", id="country_filtered", ), pytest.param( "?country_code=US&country_code=GB", id="multi_country", ), pytest.param( "?store_ids=453", id="store_filter", ), pytest.param( "?country_code=US&store_ids=453&distributors=theorchard", id="all_filters", ), ] def _url(self, params=""): return f"{BASE_URL}/all-time-video-metrics/{self.VIDEO_ID}{params}" # ── Group 1: Query variants ─────────────────────────────────────── # # 6 headers × 5 variants = 30 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize("params", QUERY_VARIANTS) def test_all_time_video_metrics(self, hdrs, params): """All-time video metrics returns metrics with expected fields. Default uses ROLLUP view. Country variants switch to country ROLLUP view and return NULL comments. Store and distributor variants tighten the IN clauses. """ payload = assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=["all_time_video_metrics", "sources"], ) metrics = payload.get("all_time_video_metrics", {}) if metrics: for field in ["views", "cpm", "rpm"]: assert field in metrics, f"Missing '{field}' in all_time_video_metrics" @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_all_time_video_metrics_emptiness(self, hdrs): """Response is populated iff the caller has access to the video. Uses a Frenchkiss-owned video. Guards against the macro's single-video_id branch regressing to always-FALSE. """ url = f"{BASE_URL}/all-time-video-metrics/{FRENCHKISS_VIDEO_ID}" payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=["all_time_video_metrics", "sources"], ) metrics = payload.get("all_time_video_metrics", {}) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert metrics, "non-empty expected" else: assert metrics == {}, "empty expected" class TestChannelMetrics: """Integration tests for /channel-metrics/. Verifies channel metrics with default and date-filtered params. Groups: 1. Default and filtered params (18 tests) """ CHANNEL_ID = "UCFg7-w47VVA3ozhvnR6P0YQ" def _url(self, params=""): return ( config.CHANNEL_METRICS_URL.replace("", self.CHANNEL_ID) + params ) # ── Group 1: Default and filtered params ────────────────────────── # # 6 headers × 3 param variants = 18 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "params", [ pytest.param("", id="defaults"), pytest.param( "?start_date=2019-11-01&end_date=2019-12-01" "&country_code=US&country_code=GB", id="date_and_country", ), pytest.param( "?days=0&start_date=HIGHWATERMARK", id="all_time_highwatermark" ), ], ) def test_channel_metrics(self, hdrs, params): """Channel metrics returns metrics with expected structure.""" payload = assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=[ "channel_metrics", "aggregate_channel_metrics", "sources", ], ) agg = payload.get("aggregate_channel_metrics", {}) if agg: for field in ["views", "cpm", "rpm"]: assert field in agg, f"Missing '{field}' in aggregate_channel_metrics" @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_channel_metrics_emptiness(self, hdrs): """Aggregate and timeseries are populated iff the caller has access. Channel is Frenchkiss-only with stable 2024-01 data. """ url = ( config.CHANNEL_METRICS_URL.replace("", FRENCHKISS_CHANNEL_ID) + FRENCHKISS_DATE_RANGE ) payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=[ "channel_metrics", "aggregate_channel_metrics", "sources", ], ) if has_video_access(hdrs, FRENCHKISS["account_id"]): assert payload["aggregate_channel_metrics"], "non-empty expected" assert payload["channel_metrics"], "non-empty expected" else: assert payload["aggregate_channel_metrics"] == {}, "empty expected" assert payload["channel_metrics"] == [], "empty expected" class TestAllTimeChannelMetrics: """Integration tests for /all-time-channel-metrics/. Verifies all-time channel metrics with default and country-filtered params. Groups: 1. Default and filtered params (12 tests) """ CHANNEL_ID = "UCFg7-w47VVA3ozhvnR6P0YQ" def _url(self, params=""): return ( config.ALL_TIME_CHANNEL_METRICS_URL.replace("", self.CHANNEL_ID) + params ) # ── Group 1: Default and filtered params ────────────────────────── # # 6 headers × 2 param variants = 12 tests. @pytest.mark.parametrize("hdrs", ALL_HEADERS) @pytest.mark.parametrize( "params", [ pytest.param("", id="defaults"), pytest.param( "?country_code=US&country_code=GB", id="country_filtered", ), ], ) def test_all_time_channel_metrics(self, hdrs, params): """All-time channel metrics returns metrics with expected fields. Authorized profiles get AllTimeChannelMetricsSchema with all_time_channel_metrics key. Unauthorized profiles get an early-return ChannelMetricsSchema with channel_metrics and aggregate_channel_metrics keys instead. """ payload = assert_endpoint( self._url(params), headers=hdrs, items_key=None, expect_payload_keys=["sources"], ) if "all_time_channel_metrics" in payload: metrics = payload["all_time_channel_metrics"] if metrics: for field in ["views", "cpm", "rpm", "comments"]: assert ( field in metrics ), f"Missing '{field}' in all_time_channel_metrics" else: assert "channel_metrics" in payload assert "aggregate_channel_metrics" in payload @pytest.mark.parametrize("hdrs", ALL_HEADERS) def test_all_time_channel_metrics_emptiness(self, hdrs): """all_time_channel_metrics is populated iff the caller has access. Channel is Frenchkiss-only. Callers without label_ids early-return through ChannelMetricsSchema (no all_time_channel_metrics key); callers with label_ids that miss the macro check get the AllTimeChannelMetricsSchema with an empty dict. """ url = config.ALL_TIME_CHANNEL_METRICS_URL.replace( "", FRENCHKISS_CHANNEL_ID ) payload = assert_endpoint( url, headers=hdrs, items_key=None, expect_payload_keys=["sources"], ) metrics = payload.get("all_time_channel_metrics") if has_video_access(hdrs, FRENCHKISS["account_id"]): assert metrics, "non-empty expected" else: assert not metrics, "empty expected"