"""Unit tests for the top accounts metrics logic layer.""" from unittest.mock import patch import pytest from analytics.api import app from analytics.logic import top_accounts_metrics @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_store_ids(mocker): mocker.patch( "analytics.logic.top_accounts_metrics.store_availability.get_store_ids", return_value=[1, 286], ) @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"], "countries": [], "store_ids": [], "label_ids": [], "subaccount_ids": [], "parent_company": None, "company_brand": None, "service_tier": None, "label_manager": None, "include_subaccounts": False, "order_by": "streams_28_days", "order_dir": "DESC", "limit": 25, "offset": 0, } @pytest.fixture def query_rows(): return [ { "label_id": 7123, "label_manager_name": "Manager A", "streams_7_days": 100, "streams_growth_percentage_7_day": 0.1, "streams_28_days": 500, "streams_growth_percentage_28_day": 0.05, "streams_all_time": 10000, "track_downloads_28_days": 10, "track_downloads_growth_percentage_28_day": 0.0, "album_downloads_28_days": 5, "album_downloads_growth_percentage_28_day": 0.0, "aggregated_downloads_7_days": 3, "aggregated_downloads_growth_percentage_7_day": 0.0, "aggregated_downloads_all_time": 200, "total_results": 1, "labels_count": 1, "subaccounts_count": 0, }, ] class TestGetTopAccountsMetrics: def test_succeeds(self, mocker, permissions, query_params, query_rows): mocker.patch( "analytics.logic.top_accounts_metrics.TopAccountsMetrics.execute", return_value=query_rows, ) response = top_accounts_metrics.get_top_accounts_metrics( query_params, permissions ) assert response.status == 200 assert response.message["total_count"] == 1 assert response.message["labels_count"] == 1 assert response.message["subaccounts_count"] == 0 assert response.message["items"][0]["label_id"] == 7123 assert "subaccount_id" not in response.message["items"][0] def test_include_subaccounts(self, mocker, permissions, query_params, query_rows): params = {**query_params, "include_subaccounts": True} rows = [{**query_rows[0], "subaccount_id": 46189}] mocker.patch( "analytics.logic.top_accounts_metrics.TopAccountsMetrics.execute", return_value=rows, ) response = top_accounts_metrics.get_top_accounts_metrics(params, permissions) assert response.status == 200 assert response.message["items"][0]["subaccount_id"] == 46189 def test_invalid_order_by_raises(self, permissions, query_params): params = {**query_params, "order_by": "bogus"} with pytest.raises(Exception): top_accounts_metrics.get_top_accounts_metrics(params, permissions) def test_invalid_order_dir_raises(self, permissions, query_params): params = {**query_params, "order_dir": "INVALID"} with pytest.raises(Exception): top_accounts_metrics.get_top_accounts_metrics(params, permissions) def test_unavailable_store_ids_returns_empty( self, mocker, permissions, query_params ): execute = mocker.patch( "analytics.logic.top_accounts_metrics.TopAccountsMetrics.execute" ) params = {**query_params, "store_ids": [99999]} response = top_accounts_metrics.get_top_accounts_metrics(params, permissions) assert response.status == 200 assert response.message["items"] == [] assert response.message["total_count"] == 0 execute.assert_not_called() def test_order_by_numeric_field_wrapped_in_coalesce( self, mocker, permissions, query_params, query_rows ): MockQuery = mocker.patch( "analytics.logic.top_accounts_metrics.TopAccountsMetrics" ) MockQuery.return_value.execute.return_value = query_rows top_accounts_metrics.get_top_accounts_metrics(query_params, permissions) query_input = MockQuery.call_args[0][0] assert query_input["order_by"] == "COALESCE(streams_28_days, 0)" def test_order_by_label_manager_name_not_wrapped( self, mocker, permissions, query_params, query_rows ): MockQuery = mocker.patch( "analytics.logic.top_accounts_metrics.TopAccountsMetrics" ) MockQuery.return_value.execute.return_value = query_rows params = {**query_params, "order_by": "label_manager_name"} top_accounts_metrics.get_top_accounts_metrics(params, permissions) query_input = MockQuery.call_args[0][0] assert query_input["order_by"] == "label_manager_name"