"""Unit tests for sound recording downloads logic layer.""" import datetime from unittest.mock import patch import pytest from sound_recordings.api import app from sound_recordings.logic import downloads as downloads ITEMS_28_DAYS = [ [ {"date": "2018-06-09T00:00:00Z", "downloads": 0}, {"date": "2018-06-10T00:00:00Z", "downloads": 0}, {"date": "2018-06-11T00:00:00Z", "downloads": 0}, {"date": "2018-06-12T00:00:00Z", "downloads": 0}, {"date": "2018-06-13T00:00:00Z", "downloads": 0}, {"date": "2018-06-14T00:00:00Z", "downloads": 0}, {"date": "2018-06-15T00:00:00Z", "downloads": 0}, {"date": "2018-06-16T00:00:00Z", "downloads": 0}, {"date": "2018-06-17T00:00:00Z", "downloads": 0}, {"date": "2018-06-18T00:00:00Z", "downloads": 0}, {"date": "2018-06-19T00:00:00Z", "downloads": 0}, {"date": "2018-06-20T00:00:00Z", "downloads": 0}, {"date": "2018-06-21T00:00:00Z", "downloads": 0}, {"date": "2018-06-22T00:00:00Z", "downloads": 0}, {"date": "2018-06-23T00:00:00Z", "downloads": 0}, {"date": "2018-06-24T00:00:00Z", "downloads": 0}, {"date": "2018-06-25T00:00:00Z", "downloads": 0}, {"date": "2018-06-26T00:00:00Z", "downloads": 0}, {"date": "2018-06-27T00:00:00Z", "downloads": 0}, {"date": "2018-06-28T00:00:00Z", "downloads": 5}, {"date": "2018-06-29T00:00:00Z", "downloads": 10}, {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 10}, {"date": "2018-07-06T00:00:00Z", "downloads": 20}, ], [ {"date": "2018-06-09T00:00:00Z", "downloads": 0}, {"date": "2018-06-10T00:00:00Z", "downloads": 0}, {"date": "2018-06-11T00:00:00Z", "downloads": 0}, {"date": "2018-06-12T00:00:00Z", "downloads": 0}, {"date": "2018-06-13T00:00:00Z", "downloads": 0}, {"date": "2018-06-14T00:00:00Z", "downloads": 0}, {"date": "2018-06-15T00:00:00Z", "downloads": 0}, {"date": "2018-06-16T00:00:00Z", "downloads": 0}, {"date": "2018-06-17T00:00:00Z", "downloads": 0}, {"date": "2018-06-18T00:00:00Z", "downloads": 0}, {"date": "2018-06-19T00:00:00Z", "downloads": 0}, {"date": "2018-06-20T00:00:00Z", "downloads": 0}, {"date": "2018-06-21T00:00:00Z", "downloads": 0}, {"date": "2018-06-22T00:00:00Z", "downloads": 0}, {"date": "2018-06-23T00:00:00Z", "downloads": 0}, {"date": "2018-06-24T00:00:00Z", "downloads": 0}, {"date": "2018-06-25T00:00:00Z", "downloads": 0}, {"date": "2018-06-26T00:00:00Z", "downloads": 0}, {"date": "2018-06-27T00:00:00Z", "downloads": 0}, {"date": "2018-06-28T00:00:00Z", "downloads": 30}, {"date": "2018-06-29T00:00:00Z", "downloads": 20}, {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 60}, {"date": "2018-07-06T00:00:00Z", "downloads": 40}, ], ] ITEMS_7_DAYS = [ [ {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 10}, {"date": "2018-07-06T00:00:00Z", "downloads": 20}, ], [ {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 60}, {"date": "2018-07-06T00:00:00Z", "downloads": 40}, ], ] STORES_28_DAYS = [ { "id": 1, "name": "Apple Music", "items": ITEMS_28_DAYS[0], }, { "id": 496, "name": "Google Play", "items": ITEMS_28_DAYS[1], }, ] STORES_7_DAYS = [ { "id": 1, "name": "Apple Music", "items": ITEMS_7_DAYS[0], }, { "id": 496, "name": "Google Play", "items": ITEMS_7_DAYS[1], }, ] COUNTRIES_28_DAYS = [ { "code": "GB", "items": ITEMS_28_DAYS[0], }, { "code": "US", "items": ITEMS_28_DAYS[1], }, ] COUNTRIES_7_DAYS = [ { "code": "GB", "items": ITEMS_7_DAYS[0], }, { "code": "US", "items": ITEMS_7_DAYS[1], }, ] SOURCES = [ {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, {"id": 496, "name": "Google Play"}, ] @pytest.fixture def mock_get_downloads_model_payload(): """Mock payload for sound recording downloads model.""" return [ {"store_id": 1, "date": datetime.date(2018, 6, 28), "downloads": 5}, {"store_id": 1, "date": datetime.date(2018, 6, 29), "downloads": 10}, {"store_id": 496, "date": datetime.date(2018, 6, 28), "downloads": 30}, {"store_id": 496, "date": datetime.date(2018, 6, 29), "downloads": 20}, {"store_id": 1, "date": datetime.date(2018, 7, 5), "downloads": 10}, {"store_id": 1, "date": datetime.date(2018, 7, 6), "downloads": 20}, {"store_id": 496, "date": datetime.date(2018, 7, 5), "downloads": 60}, {"store_id": 496, "date": datetime.date(2018, 7, 6), "downloads": 40}, ] @pytest.fixture def mock_get_downloads_by_country_model_payload(): """Mock payload for sound recording downloads by country model.""" return [ {"country_code": "GB", "date": datetime.date(2018, 6, 28), "downloads": 5}, {"country_code": "GB", "date": datetime.date(2018, 6, 29), "downloads": 10}, {"country_code": "US", "date": datetime.date(2018, 6, 28), "downloads": 30}, {"country_code": "US", "date": datetime.date(2018, 6, 29), "downloads": 20}, {"country_code": "GB", "date": datetime.date(2018, 7, 5), "downloads": 10}, {"country_code": "GB", "date": datetime.date(2018, 7, 6), "downloads": 20}, {"country_code": "US", "date": datetime.date(2018, 7, 5), "downloads": 60}, {"country_code": "US", "date": datetime.date(2018, 7, 6), "downloads": 40}, ] @pytest.fixture def expected_payload(): """Return expected payload from logic.""" return { "isrc": "isrc", "aggregate": { "items": [ {"date": "2018-06-09T00:00:00Z", "downloads": 0}, {"date": "2018-06-10T00:00:00Z", "downloads": 0}, {"date": "2018-06-11T00:00:00Z", "downloads": 0}, {"date": "2018-06-12T00:00:00Z", "downloads": 0}, {"date": "2018-06-13T00:00:00Z", "downloads": 0}, {"date": "2018-06-14T00:00:00Z", "downloads": 0}, {"date": "2018-06-15T00:00:00Z", "downloads": 0}, {"date": "2018-06-16T00:00:00Z", "downloads": 0}, {"date": "2018-06-17T00:00:00Z", "downloads": 0}, {"date": "2018-06-18T00:00:00Z", "downloads": 0}, {"date": "2018-06-19T00:00:00Z", "downloads": 0}, {"date": "2018-06-20T00:00:00Z", "downloads": 0}, {"date": "2018-06-21T00:00:00Z", "downloads": 0}, {"date": "2018-06-22T00:00:00Z", "downloads": 0}, {"date": "2018-06-23T00:00:00Z", "downloads": 0}, {"date": "2018-06-24T00:00:00Z", "downloads": 0}, {"date": "2018-06-25T00:00:00Z", "downloads": 0}, {"date": "2018-06-26T00:00:00Z", "downloads": 0}, {"date": "2018-06-27T00:00:00Z", "downloads": 0}, {"date": "2018-06-28T00:00:00Z", "downloads": 35}, {"date": "2018-06-29T00:00:00Z", "downloads": 30}, {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 70}, {"date": "2018-07-06T00:00:00Z", "downloads": 60}, ], }, "stores": STORES_28_DAYS, "sources": SOURCES, } @pytest.fixture def expected_payload_seven_days(): """Return expected payload from logic.""" return { "isrc": "isrc", "aggregate": { "items": [ {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 70}, {"date": "2018-07-06T00:00:00Z", "downloads": 60}, ], }, "stores": STORES_7_DAYS, "sources": SOURCES, } @pytest.fixture def expected_payload_all(): """Return expected payload from logic.""" return { "isrc": "isrc", "items": [ {"date": "2018-06-09T00:00:00Z", "downloads": 0}, {"date": "2018-06-10T00:00:00Z", "downloads": 0}, {"date": "2018-06-11T00:00:00Z", "downloads": 0}, {"date": "2018-06-12T00:00:00Z", "downloads": 0}, {"date": "2018-06-13T00:00:00Z", "downloads": 0}, {"date": "2018-06-14T00:00:00Z", "downloads": 0}, {"date": "2018-06-15T00:00:00Z", "downloads": 0}, {"date": "2018-06-16T00:00:00Z", "downloads": 0}, {"date": "2018-06-17T00:00:00Z", "downloads": 0}, {"date": "2018-06-18T00:00:00Z", "downloads": 0}, {"date": "2018-06-19T00:00:00Z", "downloads": 0}, {"date": "2018-06-20T00:00:00Z", "downloads": 0}, {"date": "2018-06-21T00:00:00Z", "downloads": 0}, {"date": "2018-06-22T00:00:00Z", "downloads": 0}, {"date": "2018-06-23T00:00:00Z", "downloads": 0}, {"date": "2018-06-24T00:00:00Z", "downloads": 0}, {"date": "2018-06-25T00:00:00Z", "downloads": 0}, {"date": "2018-06-26T00:00:00Z", "downloads": 0}, {"date": "2018-06-27T00:00:00Z", "downloads": 0}, {"date": "2018-06-28T00:00:00Z", "downloads": 35}, {"date": "2018-06-29T00:00:00Z", "downloads": 30}, {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 70}, {"date": "2018-07-06T00:00:00Z", "downloads": 60}, ], } @pytest.fixture def expected_payload_all_seven_days(): """Return expected payload from logic.""" return { "isrc": "isrc", "items": [ {"date": "2018-06-30T00:00:00Z", "downloads": 0}, {"date": "2018-07-01T00:00:00Z", "downloads": 0}, {"date": "2018-07-02T00:00:00Z", "downloads": 0}, {"date": "2018-07-03T00:00:00Z", "downloads": 0}, {"date": "2018-07-04T00:00:00Z", "downloads": 0}, {"date": "2018-07-05T00:00:00Z", "downloads": 70}, {"date": "2018-07-06T00:00:00Z", "downloads": 60}, ], } @pytest.fixture def expected_payload_by_store(): """Return expected payload by store.""" return {"isrc": "isrc", "stores": STORES_28_DAYS} @pytest.fixture def expected_payload_by_store_seven_days(): """Return expected payload from logic.""" return {"isrc": "isrc", "stores": STORES_7_DAYS} @pytest.fixture def expected_payload_by_country(): """Return expected payload by country.""" return {"isrc": "isrc", "countries": COUNTRIES_28_DAYS} @pytest.fixture def expected_payload_by_country_seven_days(): """Return expected payload from logic.""" return {"isrc": "isrc", "countries": COUNTRIES_7_DAYS} @pytest.fixture def mock_add_outage_error_to_stores(): """Mock add_outage_error_to_stores.""" with patch( "sound_recordings.logic.downloads.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": 496, "name": "Google Play"}, ] yield add_outage_error_to_stores @pytest.fixture def mock_get_downloads_model_success(mock_get_downloads_model_payload): """Mock successful get_downloads model response.""" with patch("sound_recordings.models.downloads.get_downloads") as get_downloads: get_downloads.return_value = mock_get_downloads_model_payload yield get_downloads @pytest.fixture def mock_get_download_max_available_date_success(): """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_get_downloads_model_failure(): """Mock failure get_downloads model response.""" with patch("sound_recordings.models.downloads.get_downloads") as get_downloads: get_downloads.return_value = [] with app.test_request_context(): yield get_downloads @pytest.fixture def mock_get_download_max_available_date_failure(): """Mock failure get_download_max_available_date model response.""" with patch( "sound_recordings.logic.downloads.data_availability." "get_downloads_max_available_date" ) as get_downloads: get_downloads.return_value = None yield get_downloads @pytest.fixture def mock_get_downloads_by_country_model_success( mock_get_downloads_by_country_model_payload, ): """Mock successful get_downloads_by_country model response.""" with patch( "sound_recordings.models.downloads.get_downloads_by_country" ) as get_downloads_by_country: get_downloads_by_country.return_value = ( mock_get_downloads_by_country_model_payload ) yield get_downloads_by_country @pytest.fixture def mock_get_downloads_by_country_model_failure(): """Mock failure get_downloads_by_country model response.""" with patch( "sound_recordings.models.downloads.get_downloads_by_country" ) as get_downloads_by_country: get_downloads_by_country.return_value = [] with app.test_request_context(): yield get_downloads_by_country @pytest.fixture def mock_store_availability(): """Mock store_availability.""" with patch( "sound_recordings.logic.downloads.store_availability" ) as store_availability: store_availability.get_download_sources.return_value = [ {"id": 1, "name": "Apple Music"}, {"id": 496, "name": "Google Play"}, ] store_availability.get_download_store_names.return_value = { 1: "Apple Music", 496: "Google Play", } yield store_availability class TestGetDownloadsWithLabel: """Test get_downloads with label.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads.""" return downloads.get_downloads( request_context_for_label, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_payload["sources"] del response_message["sources"] del expected_payload["sources"] assert response.message == expected_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_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 TestGetDownloadsWithLabelSevenDaysBack: """Test get_downloads with label.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads.""" with app.test_request_context(): return downloads.get_downloads( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload_seven_days): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_payload_seven_days["sources"] del response_message["sources"] del expected_payload_seven_days["sources"] assert response.message == expected_payload_seven_days assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], datetime.date(2018, 6, 30), datetime.date(2018, 7, 6), ) class TestGetDownloadsWithSubaccount: """Test get_downloads with subaccount.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_downloads.""" with app.test_request_context(): return downloads.get_downloads( request_context_for_subaccount, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, permissions_for_subaccount ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], [], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) class TestGetDownloadsWithSuperNewRelease: """Test get_downloads with super new release.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_store_availability, ): """Run get_downloads.""" return downloads.get_downloads( request_context_for_label, self.isrc, ["theorchard"] ) def test_succeeds(self, response, expected_payload): """Test successful response.""" payload = {**expected_payload} assert response.status == 200 assert response.message == payload class TestGetDownloadsFilteredByCountries: """Test get_downloads filtered by countries.""" isrc = "isrc" countries = ["US", "NO", "SE"] store_ids = [1, 496] @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads.""" return downloads.get_downloads( request_context_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, ) def test_succeeds(self, response, expected_payload): """Test successful response.""" assert response.status == 200 response_message = response.message response_sources = response_message["sources"] expected_sources = expected_payload["sources"] del response_message["sources"] del expected_payload["sources"] expected_payload["stores"] = [] assert response.message == expected_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], self.countries, [1, 496], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) class TestGetDownloadsAllWithLabel: """Test get_downloads_all with label.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_all.""" return downloads.get_downloads_all( request_context_for_label, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload_all): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_all def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_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 TestGetDownloadsAllWithLabelSevenDaysBack: """Test get_downloads_all with label seven days back.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_all.""" with app.test_request_context(): return downloads.get_downloads_all( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload_all_seven_days): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_all_seven_days def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], datetime.date(2018, 6, 30), datetime.date(2018, 7, 6), ) class TestGetDownloadsAllWithSubaccount: """Test get_downloads_all with subaccount.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_downloads_all.""" with app.test_request_context(): return downloads.get_downloads_all( request_context_for_subaccount, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload_all): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_all def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, permissions_for_subaccount ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], [], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) class TestGetDownloadsAllFilteredByCountries: """Test get_downloads_all filtered by countries.""" isrc = "isrc" countries = ["US", "NO", "SE"] store_ids = [1, 496] @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_all.""" return downloads.get_downloads_all( request_context_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, ) def test_succeeds(self, response, expected_payload_all): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_all def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], self.countries, [1, 496], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) class TestGetDownloadsByStoreWithLabel: """Test get_downloads_by_store with label.""" isrc = "isrc" start_date = datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_by_store.""" return downloads.get_downloads_by_store( request_context_for_label, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload_by_store): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_store def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_downloads_model_fails( self, mock_get_downloads_model_failure, request_context_for_label, mock_permissions_for_label, mock_add_outage_error_to_stores, ): """Test failure response when downloads model fails.""" response = downloads.get_downloads_by_store( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "stores": []} class TestGetDownloadsByStoreWithLabelSevenDaysBack: """Test get_downloads_by_store with label for past 7 days.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_by_store.""" with app.test_request_context(): return downloads.get_downloads_by_store( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload_by_store_seven_days): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_store_seven_days def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_downloads_model_fails( self, mock_get_downloads_model_failure, request_context_for_label, mock_permissions_for_label, mock_add_outage_error_to_stores, ): """Test failure response when downloads model fails.""" response = downloads.get_downloads_by_store( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "stores": []} class TestGetDownloadsByStoreWithSubaccount: """Test get_downloads_by_store with subaccount.""" isrc = "isrc" start_date = datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_downloads.""" with app.test_request_context(): return downloads.get_downloads_by_store( request_context_for_subaccount, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload_by_store): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_store def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, permissions_for_subaccount ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_downloads_model_fails( self, mock_get_downloads_model_failure, request_context_for_subaccount, permissions_for_subaccount, mock_add_outage_error_to_stores, ): """Test failure response when downloads model fails.""" response = downloads.get_downloads_by_store( request_context_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "stores": []} class TestGetDownloadsByStoreFilteredByCountries: """Test get_downloads_by_store filtered by countries.""" isrc = "isrc" countries = ["US", "NO", "SE"] store_ids = [1, 496] start_date = datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_by_store.""" return downloads.get_downloads_by_store( request_context_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, ) def test_succeeds(self, response, expected_payload_by_store): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_store def test_get_downloads_model_is_called( self, response, mock_get_downloads_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads model is called.""" mock_get_downloads_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, self.start_date, self.end_date, ) def test_fails_when_downloads_model_fails( self, mock_get_downloads_model_failure, request_context_for_label, permissions_for_label, mock_add_outage_error_to_stores, ): """Test failure response when downloads model fails.""" response = downloads.get_downloads_by_store( request_context_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "stores": []} class TestGetDownloadsByCountryWithLabel: """Test get_downloads_by_country with label.""" isrc = "isrc" start_date = datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_by_country_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_by_country.""" return downloads.get_downloads_by_country( request_context_for_label, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload_by_country): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_country def test_get_downloads_by_country_model_is_called( self, response, mock_get_downloads_by_country_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads_by_country model is called.""" mock_get_downloads_by_country_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_downloads_by_country_model_fails( self, mock_get_downloads_by_country_model_failure, request_context_for_label, mock_permissions_for_label, mock_add_outage_error_to_stores, ): """Test failure response when downloads by country model fails.""" response = downloads.get_downloads_by_country( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "countries": []} class TestGetDownloadsByCountryWithLabelSevenDaysBack: """Test get_downloads_by_country with label for past 7 days.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_by_country_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_by_country.""" with app.test_request_context(): return downloads.get_downloads_by_country( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload_by_country_seven_days): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_country_seven_days def test_get_downloads_model_by_country_is_called( self, response, mock_get_downloads_by_country_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads_by_country model is called.""" mock_get_downloads_by_country_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_downloads_model_fails( self, mock_get_downloads_by_country_model_failure, request_context_for_label, mock_permissions_for_label, mock_add_outage_error_to_stores, ): """Test failure response when downloads by country model fails.""" response = downloads.get_downloads_by_country( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "countries": []} class TestGetDownloadsByCountryWithSubaccount: """Test get_downloads_by_country with subaccount.""" isrc = "isrc" start_date = datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_by_country_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_downloads_by_country.""" with app.test_request_context(): return downloads.get_downloads_by_country( request_context_for_subaccount, self.isrc, ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload_by_country): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_country def test_get_downloads_by_country_model_is_called( self, response, mock_get_downloads_by_country_model_success, permissions_for_subaccount, ): """Test get_downloads_by_country model is called.""" mock_get_downloads_by_country_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_downloads_model_fails( self, mock_get_downloads_by_country_model_failure, request_context_for_subaccount, permissions_for_subaccount, mock_add_outage_error_to_stores, ): """Test failure response when downloads by country model fails.""" response = downloads.get_downloads_by_country( request_context_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "countries": []} class TestGetDownloadsByCountryFilteredByCountries: """Test get_downloads_by_country filtered by countries.""" isrc = "isrc" countries = ["US", "NO", "SE"] store_ids = [1, 496] start_date = datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_downloads_by_country_model_success, mock_get_download_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_downloads_by_country.""" return downloads.get_downloads_by_country( request_context_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, ) def test_succeeds(self, response, expected_payload_by_country): """Test successful response.""" assert response.status == 200 assert response.message == expected_payload_by_country def test_get_downloads_model_is_called( self, response, mock_get_downloads_by_country_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_downloads_by_country model is called.""" mock_get_downloads_by_country_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, self.start_date, self.end_date, ) def test_fails_when_downloads_model_fails( self, mock_get_downloads_by_country_model_failure, request_context_for_label, permissions_for_label, mock_add_outage_error_to_stores, ): """Test failure response when downloads_by_country model fails.""" response = downloads.get_downloads_by_country( request_context_for_label, self.isrc, ["theorchard"], self.countries, self.store_ids, self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "countries": []} @pytest.fixture def mock_get_downloads_by_product_model_payload(): """Mock payload for sound recording downloads by product model.""" return [ {"product_id": 111, "date": datetime.date(2018, 6, 28), "downloads": 5}, {"product_id": 111, "date": datetime.date(2018, 6, 29), "downloads": 10}, {"product_id": 222, "date": datetime.date(2018, 6, 28), "downloads": 30}, {"product_id": 222, "date": datetime.date(2018, 6, 29), "downloads": 20}, ] @pytest.fixture def expected_payload_by_product(): """Return expected payload from logic.""" return { "isrc": "isrc", "products": [ { "product_id": "111", "items": [ {"date": "2018-06-28T00:00:00Z", "downloads": 5}, {"date": "2018-06-29T00:00:00Z", "downloads": 10}, ], }, { "product_id": "222", "items": [ {"date": "2018-06-28T00:00:00Z", "downloads": 30}, {"date": "2018-06-29T00:00:00Z", "downloads": 20}, ], }, ], } @pytest.fixture def mock_get_downloads_by_product_model_success( mock_get_downloads_by_product_model_payload, ): """Mock successful get_downloads_by_product model response.""" with patch( "sound_recordings.models.downloads.get_downloads_by_product" ) as get_downloads_by_product: get_downloads_by_product.return_value = ( mock_get_downloads_by_product_model_payload ) yield get_downloads_by_product @pytest.fixture def mock_get_downloads_by_product_model_failure(): """Mock failed get_downloads_by_product response.""" with patch( "sound_recordings.models.downloads.get_downloads_by_product" ) as get_downloads_by_product: get_downloads_by_product.return_value = [] yield get_downloads_by_product class TestGetDownloadsByProductWithLabel: """Test get_downloads_by_product with Label.""" isrc = "isrc" start_date = datetime.date(2018, 6, 28) end_date = datetime.date(2018, 6, 29) @pytest.fixture def response( self, mock_get_downloads_by_product_model_success, mock_permissions_for_label, request_context_for_label, mock_get_download_max_available_date_success, mock_store_availability, ): """Run get_downloads_by_product.""" return downloads.get_downloads_by_product( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload_by_product): """Test successful response.""" assert response.status == 200 # Sorted the response and expected_payload as set() changes the order # of the `all_product_ids` list every time assert sorted(response.message) == sorted(expected_payload_by_product) def test_get_downloads_by_product_model_is_called( self, response, mock_get_downloads_by_product_model_success, permissions_for_label, mock_store_availability, ): """Test get_downloads_by_product model is called.""" mock_get_downloads_by_product_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_model_fails( self, mock_get_downloads_by_product_model_failure, mock_permissions_for_label, request_context_for_label, mock_store_availability, mock_get_download_max_available_date_success, ): """Test failure response when get_downloads_by_product model fails.""" response = downloads.get_downloads_by_product( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "products": []} class TestGetDownloadsByProductWithSubaccount: """Test get_downloads_by_product with Subaccount.""" isrc = "isrc" start_date = datetime.date(2018, 6, 28) end_date = datetime.date(2018, 6, 29) @pytest.fixture def response( self, mock_get_downloads_by_product_model_success, mock_permissions_for_subaccount, request_context_for_subaccount, mock_get_download_max_available_date_success, mock_store_availability, ): """Run get_downloads_by_product.""" return downloads.get_downloads_by_product( request_context_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload_by_product): """Test successful response.""" assert response.status == 200 assert sorted(response.message) == sorted(expected_payload_by_product) def test_get_downloads_by_product_model_is_called( self, response, mock_get_downloads_by_product_model_success, permissions_for_subaccount, mock_store_availability, ): """Test get_downloads_by_product model is called.""" mock_get_downloads_by_product_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_model_fails( self, mock_get_downloads_by_product_model_failure, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, mock_get_download_max_available_date_success, ): """Test failure response when get_downloads_by_product model fails.""" response = downloads.get_downloads_by_product( request_context_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 200 assert response.message == {"isrc": self.isrc, "products": []}