"""Unit tests for sound recording streams_by_store logic layer.""" import datetime from unittest.mock import patch import pytest from analytics.api import app from analytics.logic.streams_by_store import get_streams_by_store MOCK_STORE_IDS = [1, 286] def _normalize(payload): """Sort the stores list by id — it comes from a `set()` traversal.""" return {**payload, "stores": sorted(payload["stores"], key=lambda s: s["id"])} @pytest.fixture(autouse=True) def mock_context(): """Mock successful context.""" with app.test_request_context(): yield @pytest.fixture(autouse=True) def no_cache(): """Mock out caching of response.""" with patch("analytics.connectors.redis.client.get") as get: get.return_value = None yield get @pytest.fixture(autouse=True) def mock_store_availability(mocker): """Mock store_availability.""" mocker.patch( "analytics.logic.streams_by_store.store_availability.get_store_ids", return_value=MOCK_STORE_IDS, ) mocker.patch( "analytics.utils.streams.store_availability.get_store_names", return_value={1: "Apple Music", 286: "Spotify"}, ) @pytest.fixture def permissions(): """Return permissions with label access.""" 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 subaccount_permissions(): """Return permissions with subaccount access.""" return { "permission_label_ids": None, "permission_artist_ids": None, "permission_subaccount_ids": [345], "permission_label_participant_ids": None, "permission_feed_ids": [1, 2], } @pytest.fixture def mock_streams_by_store_query_result(): """Mock query result for streams by store.""" return [ { "store_id": 1, "date": datetime.date(2018, 6, 28), "streams": 500, "streams_with_skips": 0, "skips": None, "saves": None, }, { "store_id": 1, "date": datetime.date(2018, 6, 29), "streams": 3000, "streams_with_skips": 2000, "skips": 300, "saves": 600, }, { "store_id": 286, "date": datetime.date(2018, 6, 28), "streams": 3000, "streams_with_skips": 2000, "skips": 300, "saves": 600, }, { "store_id": 286, "date": datetime.date(2018, 6, 29), "streams": 2000, "streams_with_skips": 1000, "skips": 200, "saves": 400, }, { "store_id": 1, "date": datetime.date(2018, 6, 30), "streams": 1000, "streams_with_skips": 0, "skips": None, "saves": None, }, ] @pytest.fixture def expected_payload_streams_by_store(): """Return expected payload from get_streams_by_store logic.""" return { "isrc": "isrc", "stores": [ { "id": 1, "name": "Apple Music", "items": [ { "streams": 500, "saves": None, "skip_rate": None, "date": "2018-06-28T00:00:00Z", }, { "streams": 3000, "saves": 600, "skip_rate": 0.13043478260869565, "date": "2018-06-29T00:00:00Z", }, ], }, { "id": 286, "name": "Spotify", "items": [ { "streams": 3000, "saves": 600, "skip_rate": 0.13043478260869565, "date": "2018-06-28T00:00:00Z", }, { "streams": 2000, "saves": 400, "skip_rate": 0.16666666666666666, "date": "2018-06-29T00:00:00Z", }, ], }, ], } class TestGetStreamsByStoreWithSubaccount: """Test get_streams_by_store with Subaccount.""" isrc = "isrc" start_date = datetime.date(2018, 6, 28) end_date = datetime.date(2018, 6, 29) def _query_params(self, countries=None): return { "isrc": self.isrc, "distributors": ["theorchard", "sme", "awal"], "country_ids": countries or [], "store_ids": [], "start_date": self.start_date, "end_date": self.end_date, } def test_get_streams_by_store_success( self, mocker, subaccount_permissions, mock_streams_by_store_query_result, expected_payload_streams_by_store, ): """Test successful response.""" mocker.patch( "analytics.logic.streams_by_store.StreamsByStore.execute", return_value=mock_streams_by_store_query_result, ) response = get_streams_by_store( self._query_params(countries=["GB", "US"]), subaccount_permissions, ) assert response.status == 200 assert _normalize(response.message) == _normalize( expected_payload_streams_by_store ) def test_get_streams_by_store_failure(self, mocker, subaccount_permissions): """Test failure response when query returns empty.""" mocker.patch( "analytics.logic.streams_by_store.StreamsByStore.execute", return_value=[], ) response = get_streams_by_store( self._query_params(countries=["GB", "US"]), subaccount_permissions, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "stores": []} class TestGetStreamsByStoreWithLabel: """Test get_streams_by_store with Label.""" isrc = "isrc" start_date = datetime.date(2018, 6, 28) end_date = datetime.date(2018, 6, 29) def _query_params(self): return { "isrc": self.isrc, "distributors": ["theorchard", "sme", "awal"], "country_ids": [], "store_ids": [], "start_date": self.start_date, "end_date": self.end_date, } def test_get_streams_by_store_success( self, mocker, permissions, mock_streams_by_store_query_result, expected_payload_streams_by_store, ): """Test successful response.""" mocker.patch( "analytics.logic.streams_by_store.StreamsByStore.execute", return_value=mock_streams_by_store_query_result, ) response = get_streams_by_store( self._query_params(), permissions, ) assert response.status == 200 assert _normalize(response.message) == _normalize( expected_payload_streams_by_store ) def test_get_streams_by_store_failure(self, mocker, permissions): """Test failure response when query returns empty.""" mocker.patch( "analytics.logic.streams_by_store.StreamsByStore.execute", return_value=[], ) response = get_streams_by_store( self._query_params(), permissions, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "stores": []}