"""Unit tests for sound recording top-countries logic layer.""" import datetime from unittest.mock import patch import pytest from oto import response as oto_response from sound_recordings.logic import top_countries as top_countries @pytest.fixture def mock_get_top_countries_aggregate_streams_model_payload(): """Mock aggregate streams payload for top-countries model.""" return [ {"country_code": "US", "streams": 43126}, {"country_code": "FR", "streams": 3126}, {"country_code": "CA", "streams": 126}, {"country_code": "NO", "streams": 26}, {"country_code": "SE", "streams": 6}, ] @pytest.fixture def mock_get_top_countries_downloads_model_payload(): """Mock downloads payload for sound recording top-countries model.""" return [ {"country_code": "US", "downloads": 3126}, {"country_code": "FR", "downloads": 126}, {"country_code": "CA", "downloads": 26}, {"country_code": "NO", "downloads": 6}, ] @pytest.fixture def expected_streams_payload(): """Return expected streams without items payload from logic.""" return { "isrc": "isrc", "sources": [ {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, {"id": 187, "name": "Amazon Music"}, {"id": 286, "name": "Spotify"}, ], "top_countries": [ {"country_code": "US", "streams": 43126}, {"country_code": "FR", "streams": 3126}, {"country_code": "CA", "streams": 126}, {"country_code": "NO", "streams": 26}, {"country_code": "SE", "streams": 6}, ], } @pytest.fixture def expected_downloads_payload(): """Return expected dowmloads payload from logic.""" return { "isrc": "isrc", "sources": [ {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, {"id": 187, "name": "Amazon Music"}, {"id": 286, "name": "Spotify"}, ], "top_countries": [ {"country_code": "US", "downloads": 3126}, {"country_code": "FR", "downloads": 126}, {"country_code": "CA", "downloads": 26}, {"country_code": "NO", "downloads": 6}, ], } @pytest.fixture def mock_add_outage_error_to_stores(): """Mock add_outage_error_to_stores.""" with patch( "sound_recordings.logic.top_countries.add_outage_error_to_stores" ) as add_outage_error_to_stores: add_outage_error_to_stores.return_value = [ {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, {"id": 187, "name": "Amazon Music"}, {"id": 286, "name": "Spotify"}, ] yield add_outage_error_to_stores @pytest.fixture def mock_get_top_countries_aggregate_streams_model_success( mock_get_top_countries_aggregate_streams_model_payload, ): """Mock successful get_top_countries_aggregate_streams model response.""" with patch( "sound_recordings.models.top_countries." "get_top_countries_aggregate_streams" ) as get_top_countries_aggregate_streams: get_top_countries_aggregate_streams.return_value = ( mock_get_top_countries_aggregate_streams_model_payload ) yield get_top_countries_aggregate_streams @pytest.fixture def mock_get_top_countries_downloads_model_success( mock_get_top_countries_downloads_model_payload, ): """Mock successful get_top_countries_downloads model response.""" with patch( "sound_recordings.models.top_countries.get_top_countries_downloads" ) as get_top_countries_downloads: get_top_countries_downloads.return_value = ( mock_get_top_countries_downloads_model_payload ) yield get_top_countries_downloads @pytest.fixture def mock_get_top_countries_downloads_model_failure(): """Mock failure get_top_countries_downloads model response.""" with patch( "sound_recordings.models.top_countries.get_top_countries_downloads" ) as get_top_countries_downloads: get_top_countries_downloads.return_value = oto_response.Response([]) yield get_top_countries_downloads @pytest.fixture def mock_get_max_available_date(): """Mock successful get_max_available_date model response.""" with patch( "sound_recordings.models.data_availability.get_max_available_date" ) as get_max_available_date: get_max_available_date.return_value = "2018-07-06" yield get_max_available_date @pytest.fixture def mock_get_download_max_available_date(): """Mock successful get_download_max_available_date model response.""" with patch( "sound_recordings.models.data_availability" ".get_downloads_max_available_date" ) as get_download_max_available_date: get_download_max_available_date.return_value = "2018-07-06" yield get_download_max_available_date @pytest.fixture def mock_store_availability(): """Mock store_availability.""" with patch( "sound_recordings.logic.top_countries.store_availability" ) as store_availability: store_availability.get_sources.return_value = [ {"id": 1, "name": "Apple Music"}, {"id": 187, "name": "Amazon Music"}, {"id": 286, "name": "Spotify"}, ] store_availability.get_download_sources.return_value = [ {"id": 1, "name": "Apple Music"}, {"id": 187, "name": "Amazon Music"}, ] yield store_availability class TestGetTopCountriesAggregateStreamsWithSubaccount: """Test get_top_countries_streams aggregate with subaccount.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_top_countries_aggregate_streams_model_success, mock_add_outage_error_to_stores, mock_get_max_available_date, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_top_countries.""" return top_countries.get_top_countries_streams( request_context_for_subaccount, self.isrc, ["theorchard"], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_streams_payload): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_streams_payload["sources"] del response_message["sources"] del expected_streams_payload["sources"] assert response.message == expected_streams_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_top_countries_model_is_called( self, response, mock_get_top_countries_aggregate_streams_model_success, mock_add_outage_error_to_stores, permissions_for_subaccount, ): """Test get_top_countries_model is called.""" mock_get_top_countries_aggregate_streams_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], datetime.date(2018, 6, 30), datetime.date(2018, 7, 6), ) class TestGetTopCountriesAggregateStreamsWithLabel: """Test get_top_countries_streams with label.""" isrc = "isrc" start_date = datetime.date(2018, 7, 4) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_top_countries_aggregate_streams_model_success, mock_add_outage_error_to_stores, mock_get_max_available_date, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_top_countries_streams.""" return top_countries.get_top_countries_streams( request_context_for_label, self.isrc, ["theorchard"], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_streams_payload): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_streams_payload["sources"] del response_message["sources"] del expected_streams_payload["sources"] assert response.message == expected_streams_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_countries_streams_model_is_called( self, response, mock_get_top_countries_aggregate_streams_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_countries_streams model is called.""" mock_get_top_countries_aggregate_streams_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], self.start_date, self.end_date, ) class TestGetTopCountriesDownloadsWithLabel: """Test get_top_countries_downloads with label.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_top_countries_downloads_model_success, mock_add_outage_error_to_stores, mock_get_download_max_available_date, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_top_countries.""" return top_countries.get_top_countries_downloads( request_context_for_label, self.isrc, ["theorchard"] ) def test_succeeds(self, response, expected_downloads_payload): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_downloads_payload["sources"] del response_message["sources"] del expected_downloads_payload["sources"] assert response.message == expected_downloads_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_top_countries_model_is_called( self, response, mock_get_top_countries_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_top_countries_model is called.""" mock_get_top_countries_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) class TestGetTopCountriesAggregateStreamsWithSubaccount7Days: """Test get_top_countries_streams aggregate with subaccount.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_top_countries_aggregate_streams_model_success, mock_add_outage_error_to_stores, mock_get_max_available_date, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_top_countries.""" return top_countries.get_top_countries_streams( request_context_for_subaccount, self.isrc, ["theorchard"], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_streams_payload): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_streams_payload["sources"] del response_message["sources"] del expected_streams_payload["sources"] assert response.message == expected_streams_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_top_countries_model_is_called( self, response, mock_get_top_countries_aggregate_streams_model_success, mock_add_outage_error_to_stores, permissions_for_subaccount, ): """Test get_top_countries_model is called.""" mock_get_top_countries_aggregate_streams_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], datetime.date(2018, 6, 30), datetime.date(2018, 7, 6), ) class TestGetTopCountriesDownloadsWithSubaccount7Days: """Test get_top_countries with subaccount.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_top_countries_downloads_model_success, mock_add_outage_error_to_stores, mock_get_download_max_available_date, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_top_countries.""" return top_countries.get_top_countries_downloads( request_context_for_subaccount, self.isrc, ["theorchard"], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_downloads_payload): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_downloads_payload["sources"] del response_message["sources"] del expected_downloads_payload["sources"] assert response.message == expected_downloads_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_top_countries_model_is_called( self, response, mock_get_top_countries_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_subaccount, ): """Test get_top_countries_model is called.""" mock_get_top_countries_downloads_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], datetime.date(2018, 6, 30), datetime.date(2018, 7, 6), )