"""Tests for handlers.""" import datetime import json from unittest.mock import MagicMock, patch from urllib.parse import urlencode import pytest from oto import response as oto_response from sound_recordings import config, handlers from sound_recordings.constants.owner_category import CURATED, EDITORIAL from sound_recordings.constants.placements import DEFAULT_MIN_FOLLOWERS @patch("sound_recordings.handlers.g") def test_exception_handler(mock_g): """Verify exception_Handler returns 500 status code and json payload.""" message = ( "The server encountered an internal error " "and was unable to complete your request." ) mock_error = MagicMock() server_response = handlers.exception_handler(mock_error) mock_g.log.exception.assert_called_with(mock_error) assert server_response.status_code == 500 response_message = json.loads(server_response.data.decode()) assert response_message["message"] == message assert response_message["code"] == oto_response.error.ERROR_CODE_INTERNAL_ERROR class TestTopSoundRecordings(object): """Test top tracks endpoint.""" countries = ["US"] @pytest.fixture def top_sound_recordings(self): """Mock top sound recordings.""" with patch( "sound_recordings.handlers." "top_sound_recordings.get_top_sound_recordings" ) as get_top_sound_recordings: get_top_sound_recordings.return_value = oto_response.Response({}) yield get_top_sound_recordings @pytest.fixture def response( self, client, top_sound_recordings, artist_profiles_request_headers, request_context_profile, owsrequest_verify_grass_headers, owsrequest_get_empty_grass_headers, owsrequest_verify_profile_headers, owsrequest_get_profile_headers, ): """Return response from requesting endpoint.""" return client.get( config.TOP_SOUND_RECORDINGS_PATH, headers=artist_profiles_request_headers ) @pytest.fixture def response_with_countries( self, client, top_sound_recordings, artist_profiles_request_headers, request_context_profile, owsrequest_verify_grass_headers, owsrequest_get_empty_grass_headers, owsrequest_verify_profile_headers, owsrequest_get_profile_headers, ): """Return response from requesting endpoint.""" country_param = "?country_code=US" return client.get( config.TOP_SOUND_RECORDINGS_PATH + country_param, headers=artist_profiles_request_headers, ) @pytest.fixture def response_with_order_by( self, client, top_sound_recordings, artist_profiles_request_headers, request_context_profile, owsrequest_verify_grass_headers, owsrequest_get_empty_grass_headers, owsrequest_verify_profile_headers, owsrequest_get_profile_headers, ): """Return response from requesting endpoint.""" params = "?order_by=streams_28_days" return client.get( config.TOP_SOUND_RECORDINGS_PATH + params, headers=artist_profiles_request_headers, ) @pytest.fixture def response_all_time( self, client, top_sound_recordings, artist_profiles_request_headers, request_context_profile, owsrequest_verify_grass_headers, owsrequest_get_empty_grass_headers, owsrequest_verify_profile_headers, owsrequest_get_profile_headers, ): """Return response from requesting endpoint.""" params = "?order_by=streams_all_time" return client.get( config.TOP_SOUND_RECORDINGS_PATH + params, headers=artist_profiles_request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == {} def test_calls_logic_layer( self, response, request_context_profile, top_sound_recordings ): """Test that get_top_sound_recordings is called from handler.""" top_sound_recordings.assert_called_once_with( request_context_profile, ["theorchard"], 25, 0, [], "streams_7_days" ) def test_calls_logic_layer_with_countries( self, response_with_countries, request_context_profile, top_sound_recordings ): """Test that get_top_sound_recordings is called from handler.""" top_sound_recordings.assert_called_once_with( request_context_profile, ["theorchard"], 25, 0, self.countries, "streams_7_days", ) def test_calls_logic_layer_with_order_by( self, response_with_order_by, request_context_profile, top_sound_recordings ): """Test that get_top_sound_recordings is called from handler.""" top_sound_recordings.assert_called_once_with( request_context_profile, ["theorchard"], 25, 0, [], "streams_28_days" ) def test_calls_logic_layer_with_all_time( self, response_all_time, request_context_profile, top_sound_recordings ): """Test that get_top_sound_recordings is called from handler.""" top_sound_recordings.assert_called_once_with( request_context_profile, ["theorchard"], 25, 0, [], "streams_all_time" ) def test_verify_profile_headers(self, response, owsrequest_verify_profile_headers): """Test that flask_request.verify_profile_headers is called.""" owsrequest_verify_profile_headers.assert_called_once() def test_get_profile_headers(self, response, owsrequest_get_profile_headers): """Test that flask_request.get_profile_headers is called.""" assert owsrequest_get_profile_headers.call_count == 1 class TestPlacements: """Test /sound-recording//placements endpoint.""" isrc = "GBUM71105426" store_ids = [1, 286] owner_categories = [CURATED, EDITORIAL] min_followers = DEFAULT_MIN_FOLLOWERS limit = 25 offset = 0 order_dir = "ASC" order_by = "added" @pytest.fixture def placements(self): """Mock get_placements.""" with patch( "sound_recordings.logic.placements.get_placements" ) as get_placements: get_placements.return_value = oto_response.Response([{"mock": "payload"}]) yield get_placements @pytest.fixture def response(self, client, placements, request_headers, request_context): """Return response from requesting endpoint.""" query_string = urlencode( list(map(lambda id: ("store_id", id), self.store_ids)) + list(map(lambda c: ("owner_category", c), self.owner_categories)) + list([("order_by", self.order_by), ("order_dir", self.order_dir)]) ) return client.get( config.PLACEMENTS_PATH.replace("", self.isrc) + "?" + query_string, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, placements, request_headers, request_context ): """Test that get_placements is called from handler.""" placements.assert_called_once_with( request_context, None, None, self.order_dir, self.order_by, self.isrc, self.store_ids, self.owner_categories, self.min_followers, ) @pytest.fixture def response_paginated(self, client, placements, request_headers, request_context): """Return response from requesting endpoint.""" query_string = urlencode( list(map(lambda id: ("store_id", id), self.store_ids)) + list(map(lambda c: ("owner_category", c), self.owner_categories)) + [ ("limit", 25), ("offset", 0), ("order_dir", self.order_dir), ("order_by", self.order_by), ] ) return client.get( config.PLACEMENTS_PATH.replace("", self.isrc) + "?" + query_string, headers=request_headers, ) def test_calls_logic_layer_paginated( self, response_paginated, placements, request_headers, request_context ): """Test that get_placements is called from handler.""" placements.assert_called_once_with( request_context, self.limit, self.offset, self.order_dir, self.order_by, self.isrc, self.store_ids, self.owner_categories, self.min_followers, ) class TestSourceOfStreams: """Test /sound-recording//source-of-streams endpoint.""" isrc = "GBUM71105426" countries = ["US"] distributors = ["theorchard"] store_ids = [] start_date = datetime.date(2019, 11, 1) end_date = datetime.date(2019, 12, 1) @pytest.fixture def source_of_streams(self): """Mock get_source_breakdown.""" with patch( "sound_recordings.logic.source_of_streams.get_source_breakdown" ) as get_source_breakdown: get_source_breakdown.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_source_breakdown @pytest.fixture def response(self, client, source_of_streams, request_headers, request_context): """Return response from requesting endpoint.""" country_param = "?country_code=US" date_param = "&start_date=2019-11-01&end_date=2019-12-01" return client.get( config.SOURCE_OF_STREAMS_PATH.replace("", self.isrc) + country_param + date_param, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, source_of_streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" source_of_streams.assert_called_once_with( request_context, self.isrc, self.countries, self.store_ids, self.start_date, self.end_date, self.distributors, ) class TestStreams: """Test /sound-recording//streams endpoint.""" isrc = "GBUM71105426" @pytest.fixture def streams(self): """Mock get_streams.""" with patch("sound_recordings.logic.streams.get_streams_bulk") as get_streams: get_streams.return_value = oto_response.Response( {"GBUM71105426": [{"mock": "payload"}]} ) yield get_streams @pytest.fixture def response( self, client, streams, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" return client.get( config.STREAMS_PATH.replace("", self.isrc), headers=request_headers ) @pytest.fixture def response_start_end_date( self, client, streams, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=2019-11-01&end_date=2019-12-01" return client.get( config.STREAMS_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def response_start_date_days( self, client, streams, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=2019-11-01&days=30" return client.get( config.STREAMS_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def response_start_date_days_back( self, client, streams, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=2019-11-01&days=-30" return client.get( config.STREAMS_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def response_highwatermark_days( self, client, streams, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=HIGHWATERMARK&days=30" return client.get( config.STREAMS_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def response_highwatermark_days_back( self, client, streams, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=HIGHWATERMARK&days=-30" return client.get( config.STREAMS_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) @pytest.fixture def payload_start_end_date(self, response_start_end_date): """Return payload.""" return json.loads(response_start_end_date.data.decode("utf-8")) @pytest.fixture def payload_start_date_days(self, response_start_date_days): """Return payload.""" return json.loads(response_start_date_days.data.decode("utf-8")) @pytest.fixture def payload_start_date_days_back(self, response_start_date_days_back): """Return payload.""" return json.loads(response_start_date_days_back.data.decode("utf-8")) @pytest.fixture def payload_highwatermark_days(self, response_highwatermark_days): """Return payload.""" return json.loads(response_highwatermark_days.data.decode("utf-8")) @pytest.fixture def payload_highwatermark_days_back(self, response_highwatermark_days_back): """Return payload.""" return json.loads(response_highwatermark_days_back.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], [], [], None, None ) def test_calls_logic_layer_start_end_date( self, response_start_end_date, streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], [], [], datetime.date(2019, 11, 1), datetime.date(2019, 12, 1), ) def test_calls_logic_layer_start_date_days( self, response_start_date_days, streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], [], [], datetime.date(2019, 11, 1), datetime.date(2019, 11, 30), ) def test_calls_logic_layer_start_date_days_back( self, response_start_date_days_back, streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], [], [], datetime.date(2019, 10, 3), datetime.date(2019, 11, 1), ) def test_calls_logic_layer_highwatermark_days( self, response_highwatermark_days, streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], [], [], datetime.date(2019, 12, 2), datetime.date(2019, 12, 31), ) def test_calls_logic_layer_highwatermark_days_back( self, response_highwatermark_days_back, streams, request_headers, request_context, ): """Test that get_source_breakdown is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], [], [], datetime.date(2019, 12, 2), datetime.date(2019, 12, 31), ) class TestDownloads: """Test /sound-recording//downloads endpoint.""" isrc = "GBUM71105426" @pytest.fixture def downloads(self): """Mock get_downloads.""" with patch("sound_recordings.logic.downloads.get_downloads") as get_downloads: get_downloads.return_value = oto_response.Response([{"mock": "payload"}]) yield get_downloads @pytest.fixture def response( self, client, downloads, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=2019-11-01&days=30" return client.get( config.DOWNLOADS_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, downloads, request_headers, request_context ): """Test that get_downloads is called from handler.""" downloads.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], datetime.date(2019, 11, 1), datetime.date(2019, 11, 30), ) class TestDownloadsAll: """Test /sound-recording//downloads-all endpoint.""" isrc = "GBUM71105426" @pytest.fixture def downloads(self): """Mock get_downloads_all.""" with patch( "sound_recordings.logic.downloads.get_downloads_all" ) as get_downloads_all: get_downloads_all.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_downloads_all @pytest.fixture def response( self, client, downloads, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=2019-11-01&days=30" return client.get( config.DOWNLOADS_ALL_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, downloads, request_headers, request_context ): """Test that get_downloads_all is called from handler.""" downloads.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], datetime.date(2019, 11, 1), datetime.date(2019, 11, 30), ) class TestDownloadsByStore: """Test /sound-recording//downloads-by-store endpoint.""" isrc = "GBUM71105426" @pytest.fixture def downloads(self): """Mock get_downloads_by_store.""" with patch( "sound_recordings.logic.downloads.get_downloads_by_store" ) as get_downloads_by_store: get_downloads_by_store.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_downloads_by_store @pytest.fixture def response( self, client, downloads, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=2019-11-01&days=30" return client.get( config.DOWNLOADS_BY_STORE_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, downloads, request_headers, request_context ): """Test that get_downloads_by_store is called from handler.""" downloads.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], datetime.date(2019, 11, 1), datetime.date(2019, 11, 30), ) class TestDownloadsByProduct: """Test /sound-recording//downloads-by-product endpoint.""" isrc = "GBUM71105426" @pytest.fixture def downloads(self): """Mock get_downloads_by_product.""" with patch( "sound_recordings.logic.downloads.get_downloads_by_product" ) as get_downloads_by_product: get_downloads_by_product.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_downloads_by_product @pytest.fixture def response(self, client, downloads, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.DOWNLOADS_BY_PRODUCT_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, downloads, request_context, request_headers ): """Test get_downloads_by_product is called from handler.""" downloads.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], None, None ) class TestStreamsWithCountries: """Test /sound-recording//streams endpoint filtered by country.""" isrc = "GBUM71105426" countries = ["US", "NO", "SE"] store_ids = [] @pytest.fixture def streams(self): """Mock get_streams.""" with patch("sound_recordings.logic.streams.get_streams_bulk") as get_streams: get_streams.return_value = oto_response.Response([{"mock": "payload"}]) yield get_streams @pytest.fixture def response(self, client, streams, request_headers, request_context): """Return response from requesting endpoint.""" query_string = urlencode( list(map(lambda id: ("country_code", id), self.countries)) ) return client.get( config.STREAMS_PATH.replace("", self.isrc) + "?" + query_string, headers=request_headers, ) def test_calls_logic_layer( self, response, streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], self.countries, [], None, None ) class TestDownloadsByCountry: """Test /sound-recording//downloads-by-country endpoint.""" isrc = "GBUM71105426" @pytest.fixture def downloads(self): """Mock get_downloads_by_country.""" with patch( "sound_recordings.logic.downloads.get_downloads_by_country" ) as get_downloads_by_country: get_downloads_by_country.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_downloads_by_country @pytest.fixture def response( self, client, downloads, request_headers, request_context, max_available_date ): """Return response from requesting endpoint.""" date_param = "?start_date=2019-11-01&days=30" return client.get( config.DOWNLOADS_BY_COUNTRY_PATH.replace("", self.isrc) + date_param, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, downloads, request_headers, request_context ): """Test that get_downloads_by_store is called from handler.""" downloads.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], datetime.date(2019, 11, 1), datetime.date(2019, 11, 30), ) class TestTopMarkets: """Test /sound-recording//top-markets endpoint.""" isrc = "GBUM71105426" store_ids = [1, 286] countries = ["US", "GB"] @pytest.fixture def top_markets(self): """Mock get_top_markets.""" with patch( "sound_recordings.logic.top_markets.get_top_markets" ) as get_top_markets: get_top_markets.return_value = oto_response.Response([{"mock": "payload"}]) yield get_top_markets @pytest.fixture def response(self, client, top_markets, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.TOP_MARKETS_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def response_with_query_string( self, client, top_markets, request_headers, request_context ): """Return response from requesting endpoint.""" data = {"store_ids": self.store_ids, "country_code": self.countries} return client.get( config.TOP_MARKETS_PATH.replace("", self.isrc), query_string=data, headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, top_markets, request_headers, request_context ): """Test that get_top_markets called from handler.""" top_markets.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [] ) def test_calls_logic_layer_with_query_params( self, response_with_query_string, top_markets, request_headers, request_context ): """Test that get_top_markets called from handler.""" top_markets.assert_called_once_with( request_context, self.isrc, ["theorchard"], self.store_ids, self.countries ) class TestTopCountriesStreams: """Test /sound-recording//top-countries-streams endpoint.""" isrc = "GBUM71105426" @pytest.fixture def top_countries_streams(self): """Mock get_top_countries_streams.""" with patch( "sound_recordings.logic.top_countries." "get_top_countries_streams" ) as get_top_countries_streams: get_top_countries_streams.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_top_countries_streams @pytest.fixture def response(self, client, top_countries_streams, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.TOP_COUNTRIES_STREAMS_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, top_countries_streams, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" top_countries_streams.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], None, None ) class TestTopCountriesDownloads: """Test /sound-recording//top-countries-downloads endpoint.""" isrc = "GBUM71105426" @pytest.fixture def top_countries_downloads(self): """Mock get_top_countries_downloads.""" with patch( "sound_recordings.logic.top_countries." "get_top_countries_downloads" ) as get_top_countries_downloads: get_top_countries_downloads.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_top_countries_downloads @pytest.fixture def response( self, client, top_countries_downloads, request_headers, request_context ): """Return response from requesting endpoint.""" return client.get( config.TOP_COUNTRIES_DOWNLOADS_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, top_countries_downloads, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" top_countries_downloads.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], None, None ) class TestDemographics(object): """Test /sound-recording//demographics endpoint.""" isrc = "GBUM71105426" @pytest.fixture def demographics(self): """Test demographic endpoint.""" with patch( "sound_recordings.logic.demographics.get_demographics" ) as get_demographics: get_demographics.return_value = { "isrc": self.isrc, "stores": [], "demographics": [], } yield get_demographics @pytest.fixture def demographics_exception(self): """Demographic logic layer should raise Exception.""" with patch( "sound_recordings.logic.demographics.get_demographics", side_effect=Exception("boom"), ) as get_demographics: yield get_demographics @pytest.fixture def response(self, client, demographics, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.DEMOGRAPHICS_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_calls_logic_layer( self, response, demographics, request_headers, request_context ): """Test that get_source_breakdown is called from handler.""" demographics.assert_called_once_with( request_context, self.isrc, [], [], None, None, ["theorchard"] ) def handles_exceptions(self, client, demographics_exception, request_headers): """Test the exceptions route.""" error_response = client.get( config.DEMOGRAPHICS_PATH.replace("", self.isrc), headers=request_headers, ) assert error_response.code == 500 class TestStreamsBySourceOfStreams: """Test /sound-recording//streams-by-sos endpoint.""" isrc = "GBUM71105426" @pytest.fixture def streams_by_sos(self): """Mock streams_by_source_of_streams logic.""" with patch( "sound_recordings.logic.streams_by_sos." "get_streams_by_source_of_streams" ) as streams_by_sos: streams_by_sos.return_value = oto_response.Response([{"mock": "payload"}]) yield streams_by_sos @pytest.fixture def response(self, client, streams_by_sos, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.STREAMS_BY_SOS_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, streams_by_sos, request_headers, request_context ): """Test that streams_by_sos is called from handler.""" streams_by_sos.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], None, None ) class TestStreamsByStore: """Test /sound-recording//streams-by-store endpoint.""" isrc = "GBUM71105426" @pytest.fixture def streams_by_store(self): """Mock streams_by_store logic.""" with patch( "sound_recordings.logic.streams_by_store.get_streams_by_store" ) as streams_by_store: streams_by_store.return_value = oto_response.Response([{"mock": "payload"}]) yield streams_by_store @pytest.fixture def response(self, client, streams_by_store, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.STREAMS_BY_STORE_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, streams_by_store, request_headers, request_context ): """Test that streams_by_store is called from handler.""" streams_by_store.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], None, None ) class TestStreamsByProduct: """Test /sound-recording//streams-by-product endpoint.""" isrc = "GBUM71105426" @pytest.fixture def streams_by_product(self): """Mock streams_by_product logic.""" with patch( "sound_recordings.logic.streams_by_product.get_streams_by_product" ) as streams_by_product: streams_by_product.return_value = oto_response.Response( [{"mock": "payload"}] ) yield streams_by_product @pytest.fixture def response(self, client, streams_by_product, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.STREAMS_BY_PRODUCT_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, streams_by_product, request_headers, request_context ): """Test that streams_by_product is called from handler.""" streams_by_product.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], None, None ) class TestStreamsAll: """Test /sound-recording//streams-all endpoint.""" isrc = "GBUM71105426" @pytest.fixture def streams_all(self): """Mock streams_all logic.""" with patch("sound_recordings.logic.streams.get_streams_all") as streams_all: streams_all.return_value = oto_response.Response([{"mock": "payload"}]) yield streams_all @pytest.fixture def response(self, client, streams_all, request_headers, request_context): """Return response from requesting endpoint.""" return client.get( config.STREAMS_ALL_PATH.replace("", self.isrc), headers=request_headers, ) @pytest.fixture def payload(self, response): """Return payload.""" return json.loads(response.data.decode("utf-8")) def test_succeeds(self, response): """Test successful response.""" assert response.status_code == 200 def test_returns_payload(self, payload): """Test returns payload.""" assert payload == [{"mock": "payload"}] def test_calls_logic_layer( self, response, streams_all, request_headers, request_context ): """Test that streams_all is called from handler.""" streams_all.assert_called_once_with( request_context, self.isrc, ["theorchard"], [], [], None, None ) class TestStreamsBulk: """Test /sound-recording/streams endpoint filtered by country.""" isrc = "GBUM71105426" countries = ["US", "NO", "SE"] store_ids = [] @pytest.fixture def streams(self): """Mock get_streams.""" with patch("sound_recordings.logic.streams.get_streams_bulk") as get_streams: get_streams.return_value = oto_response.Response([{"mock": "payload"}]) yield get_streams @pytest.fixture def response(self, client, streams, request_headers, request_context): """Return response from requesting endpoint.""" query_string = urlencode( list(map(lambda id: ("country_code", id), self.countries)) ) return client.post( config.STREAMS_BULK_PATH + "?" + query_string, json={"isrcs": [self.isrc]}, headers=request_headers, ) def test_calls_logic_layer( self, response, streams, request_headers, request_context ): """Test that get_streams_bulk is called from handler.""" streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], self.countries, [], None, None ) def test_returns_nothing_with_no_isrcs( self, client, streams, request_headers, request_context ): """Test that get_source_bulk will return nothing with no isrcs.""" response = client.post( config.STREAMS_BULK_PATH, json={"isrcs": []}, headers=request_headers ) assert json.loads(response.data.decode("utf-8")) == {} class TestAggregateStreams: """Test /sound-recording/aggregate-streams endpoint.""" isrc = "GBUM71105426" store_ids = [] @pytest.fixture def aggregate_streams(self): """Mock get_aggregate_streams.""" with patch( "sound_recordings.logic.streams.get_aggregate_streams" ) as get_aggregate_streams: get_aggregate_streams.return_value = oto_response.Response( [{"mock": "payload"}] ) yield get_aggregate_streams @pytest.fixture def response(self, client, aggregate_streams, request_headers, request_context): """Return response from requesting endpoint.""" return client.post( config.AGGREGATE_STREAMS_PATH, json={"isrcs": [self.isrc]}, headers=request_headers, ) def test_calls_logic_layer( self, response, aggregate_streams, request_headers, request_context ): """Test that get_aggregate_streams is called from handler.""" aggregate_streams.assert_called_once_with( request_context, [self.isrc], ["theorchard"], [], [] ) def test_returns_nothing_with_no_isrcs( self, client, aggregate_streams, request_headers, request_context ): """Test get_aggregate_streams returns nothing with no isrcs.""" response = client.post( config.AGGREGATE_STREAMS_PATH, json={"isrcs": []}, headers=request_headers ) assert json.loads(response.data.decode("utf-8")) == {}