"""Unit tests for the ugc video metrics logic layer.""" from unittest.mock import patch import pytest from analytics.api import app from analytics.logic import ugc_video_metrics VIDEO_SOURCES = [{"id": 453, "name": "YouTube"}] @pytest.fixture(autouse=True) def mock_request_context(): with app.test_request_context(): yield @pytest.fixture(autouse=True) def no_cache(): with patch("analytics.connectors.redis.client.get") as get: get.return_value = None yield get @pytest.fixture(autouse=True) def mock_environment(mocker): mocker.patch( "analytics.logic.ugc_video_metrics.store_availability.get_query_store_ids", return_value=[453], ) mocker.patch( "analytics.logic.ugc_video_metrics.store_availability.get_video_sources", return_value=VIDEO_SOURCES, ) mocker.patch( "analytics.logic.ugc_video_metrics.add_outage_error_to_stores", return_value=VIDEO_SOURCES, ) @pytest.fixture def permissions(): return { "permission_label_ids": [7123], "permission_artist_ids": None, "permission_subaccount_ids": None, "permission_label_participant_ids": None, "permission_feed_ids": [1, 2], } @pytest.fixture def query_params(): return { "distributors": ["theorchard", "sme", "awal"], "store_ids": [], "video_ids": [], "track_ids": [], "asset_ids": [], "track_isrcs": [], "countries": [], "claim_types": [], "claim_statuses": [], "order_by": "views", "order_dir": "DESC", "limit": 10, "offset": 0, } @pytest.fixture def metrics_rows(): return [ { "video_id": "V1", "asset_id": "A1", "channel_id": "C1", "track_id": 123, "track_isrc": "USXDR1700554", "views": 100, "premium_views": 5, "percentage": 0.5, "claim_type": "AUDIO", "claim_created_date": "2021-01-01", "claim_policy_monetize": None, "claim_policy_track": None, "claim_policy_block": None, "claim_status": "ACTIVE", "content_type": "UGC", "video_name": "Video 1", "channel_name": "Channel 1", "release_date": "2021-01-01", } ] @pytest.fixture def count_rows(): return [{"total_results": 42}] class TestGetUgcVideoMetrics: def test_succeeds( self, mocker, permissions, query_params, metrics_rows, count_rows ): mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetrics.execute", return_value=metrics_rows, ) mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount.execute", return_value=count_rows, ) response = ugc_video_metrics.get_ugc_video_metrics(query_params, permissions) assert response.status == 200 assert response.message["total_results"] == 42 assert response.message["sources"] == VIDEO_SOURCES assert response.message["items"][0]["video_id"] == "V1" assert response.message["items"][0]["claim_policy"] is None def test_no_items_returns_empty_payload( self, mocker, permissions, query_params, count_rows ): mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetrics.execute", return_value=[], ) mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount.execute", return_value=count_rows, ) response = ugc_video_metrics.get_ugc_video_metrics(query_params, permissions) assert response.status == 200 assert response.message == {"items": []} def test_invalid_order_by_raises(self, permissions, query_params): params = {**query_params, "order_by": "bogus"} with pytest.raises(Exception): ugc_video_metrics.get_ugc_video_metrics(params, permissions) def test_invalid_order_dir_raises(self, permissions, query_params): params = {**query_params, "order_dir": "INVALID"} with pytest.raises(Exception): ugc_video_metrics.get_ugc_video_metrics(params, permissions) def test_no_video_stores_short_circuits(self, mocker, permissions, query_params): mocker.patch( "analytics.logic.ugc_video_metrics.store_availability.get_query_store_ids", return_value=[], ) metrics_execute = mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetrics.execute" ) count_execute = mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount.execute" ) response = ugc_video_metrics.get_ugc_video_metrics(query_params, permissions) assert response.status == 200 assert response.message == [] metrics_execute.assert_not_called() count_execute.assert_not_called() def test_blocked_claim_status_sets_blocked_flag( self, mocker, permissions, query_params, metrics_rows, count_rows ): MockQuery = mocker.patch("analytics.logic.ugc_video_metrics.UgcVideoMetrics") MockQuery.return_value.execute.return_value = metrics_rows mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount.execute", return_value=count_rows, ) params = {**query_params, "claim_statuses": ["blocked"]} ugc_video_metrics.get_ugc_video_metrics(params, permissions) query_input = MockQuery.call_args[0][0] assert query_input["claim_statuses_blocked"] is True assert query_input["claim_statuses"] == ["blocked"] def test_active_claim_status_does_not_set_blocked_flag( self, mocker, permissions, query_params, metrics_rows, count_rows ): MockQuery = mocker.patch("analytics.logic.ugc_video_metrics.UgcVideoMetrics") MockQuery.return_value.execute.return_value = metrics_rows mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount.execute", return_value=count_rows, ) params = {**query_params, "claim_statuses": ["ACTIVE"]} ugc_video_metrics.get_ugc_video_metrics(params, permissions) query_input = MockQuery.call_args[0][0] assert query_input["claim_statuses_blocked"] is False def test_count_query_omits_claim_statuses( self, mocker, permissions, query_params, metrics_rows, count_rows ): """Preserves the legacy quirk where count omits claim_statuses filter.""" mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetrics.execute", return_value=metrics_rows, ) MockCount = mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount" ) MockCount.return_value.execute.return_value = count_rows params = {**query_params, "claim_statuses": ["ACTIVE"]} ugc_video_metrics.get_ugc_video_metrics(params, permissions) count_input = MockCount.call_args[0][0] assert "claim_statuses" not in count_input assert "claim_statuses_blocked" not in count_input def test_rollup_grain_threaded_to_both_queries( self, mocker, permissions, query_params, metrics_rows, count_rows ): MockMetrics = mocker.patch("analytics.logic.ugc_video_metrics.UgcVideoMetrics") MockMetrics.return_value.execute.return_value = metrics_rows MockCount = mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount" ) MockCount.return_value.execute.return_value = count_rows ugc_video_metrics.get_ugc_video_metrics(query_params, permissions) assert MockMetrics.call_args[0][0]["rollup_grain"] is True assert MockCount.call_args[0][0]["rollup_grain"] is True def test_claim_policy_parsing(self, mocker, permissions, query_params, count_rows): rows = [ { "video_id": "V1", "asset_id": "A1", "channel_id": "C1", "track_id": 1, "track_isrc": "I1", "views": 1, "premium_views": 0, "percentage": 0.0, "claim_type": "AUDIO", "claim_created_date": "2021-01-01", "claim_policy_monetize": "INCLUDE US JP", "claim_policy_track": None, "claim_policy_block": None, "claim_status": "ACTIVE", "content_type": "UGC", "video_name": "v", "channel_name": "c", "release_date": "2021-01-01", } ] mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetrics.execute", return_value=rows, ) mocker.patch( "analytics.logic.ugc_video_metrics.UgcVideoMetricsCount.execute", return_value=count_rows, ) response = ugc_video_metrics.get_ugc_video_metrics(query_params, permissions) assert response.message["items"][0]["claim_policy"] == "US,JP||"