"""Tests for Spotify status polling.""" import json import os import pytest from availability import datastructures as ds from availability import exceptions from availability.constants import models from availability.logic.polling.stores import spotify UPC = '819224018247' # This should match test json data. SPOTIFY_INTERNAL_RELEASE_ID = '5jIArwISz7uEAip1gFK1Z3' COUNTRIES = ['USA', 'GB'] def test_get_status_from_store_empty_parser_response(mocker): """Test Spotify status polling.""" store_response = 'does not matter' mock_query_store = mocker.patch( 'availability.logic.polling.stores.spotify.spotify.query_store', return_value=store_response) expected_store_calls = [mocker.call(UPC, country) for country in COUNTRIES] mocker.patch( 'availability.logic.polling.stores.spotify.release_status_from_dict', return_value=None) expected_status = ds.ReleaseStatus( db_release_status=models.RELEASE_STATUS_DELIVERED) actual_status = spotify.get_status_from_store(upc=UPC, countries=COUNTRIES) mock_query_store.assert_has_calls(expected_store_calls) assert actual_status == expected_status def test_get_status_from_store_non_empty_parser_response(mocker): """Test Spotify status polling.""" store_response = 'does not matter' mock_query_store = mocker.patch( 'availability.logic.polling.stores.spotify.spotify.query_store', return_value=store_response) expected_store_calls = [mocker.call(UPC, 'USA')] mocker.patch( 'availability.logic.polling.stores.spotify.release_status_from_dict', return_value=ds.ReleaseStatus()) expected_status = ds.ReleaseStatus( db_release_status=models.RELEASE_STATUS_LIVE) actual_status = spotify.get_status_from_store(upc=UPC, countries=COUNTRIES) mock_query_store.assert_has_calls(expected_store_calls) assert actual_status == expected_status def test_get_status_from_store_handles_empty_countries(): """Test that empty list of countries is handled.""" status = spotify.get_status_from_store(upc=UPC, countries=[]) assert status == ds.ReleaseStatus( db_release_status=models.RELEASE_STATUS_DELIVERED) @pytest.mark.parametrize( ['search_results', 'countries', 'expected_status'], [ ([None], ['foo'], models.RELEASE_STATUS_DELIVERED), ([None, 'valid result'], ['foo', 'bar'], models.RELEASE_STATUS_LIVE) ] ) def test_get_status_from_store_handles_none_search_result( search_results, countries, expected_status, mocker): """Test that None search result is handled and steps to next country.""" mock_query_store = mocker.patch( 'availability.logic.polling.stores.spotify.spotify.query_store', side_effect=search_results) expected_store_calls = [mocker.call(UPC, c) for c in countries] expected_status = ds.ReleaseStatus(db_release_status=expected_status) release_status_from_dict_mock = mocker.patch( 'availability.logic.polling.stores.spotify.release_status_from_dict', return_value=expected_status) actual_status = spotify.get_status_from_store(upc=UPC, countries=countries) assert actual_status == expected_status assert mock_query_store.call_count == len(search_results) mock_query_store.assert_has_calls(expected_store_calls) if len(search_results) > 1: release_status_from_dict_mock.assert_called_once_with( search_results[-1]) @pytest.mark.parametrize( 'file_path, live_countries', [ ('spotify_available_markets.json', ['CA', 'US']), ('spotify_available_markets_empty.json', []), ('spotify_available_markets_absent.json', []), ]) def test_release_status_from_dict_success(file_path, live_countries): """Test parsing Spotify JSON response successful parsing.""" response_data = _get_spotify_response_dict(file_path) expected_status = ds.ReleaseStatus( live_countries=live_countries, store_release_id=SPOTIFY_INTERNAL_RELEASE_ID, ) assert spotify.release_status_from_dict(response_data) == expected_status def test_release_status_from_dict_empty(): """Test parsing Spotify empty JSON response returns None.""" response_data = _get_spotify_response_dict('spotify_no_match.json') assert spotify.release_status_from_dict(response_data) is None @pytest.mark.parametrize( 'file_path', [ 'spotify_not_a_mapping.json', 'spotify_no_total.json', 'spotify_no_items.json', 'spotify_no_id.json', 'spotify_multiple_total.json', 'spotify_multiple_items.json', ]) def test_release_status_from_dict_invalid_json(file_path): """Test parsing Spotify JSON invalid response handling.""" response_data = _get_spotify_response_dict(file_path) with pytest.raises(exceptions.StoreResponseParseError): spotify.release_status_from_dict(response_data) def test_get_status_from_store_checks_each_country_in_list(mocker): """Assert each country from list is checked.""" countries = ['US', 'GB', 'ES'] mock_search = mocker.patch( 'availability.connectors.stores.spotify.spotipy.Spotify.search', return_value={'albums': {'items': []}}) spotify.get_status_from_store(upc=UPC, countries=countries) expected_calls = [ mocker.call(q='upc:{}'.format(UPC), type='album', market=market) for market in countries] mock_search.assert_has_calls(expected_calls) def test_get_status_from_store_stops_once_release_is_found(mocker): """Assert store will be queried only until release is found.""" empty_response = {'albums': {'items': []}} response_with_release = _get_spotify_response_dict( 'spotify_available_markets.json') mock_search = mocker.patch( 'availability.connectors.stores.spotify.spotipy.Spotify.search', side_effect=[empty_response, response_with_release]) countries = ['US', 'CA', 'ES'] expected_calls = [ mocker.call(q='upc:{}'.format(UPC), type='album', market=market) for market in ['US', 'CA']] expected_status_dict = { 'db_release_status': 'live', 'live_countries': ['CA', 'US'], 'store_release_id': '5jIArwISz7uEAip1gFK1Z3', 'store_release_status': None } received_status = spotify.get_status_from_store( upc=UPC, countries=countries) mock_search.assert_has_calls(expected_calls) assert mock_search.call_count == 2 assert received_status.as_dict() == expected_status_dict def _get_spotify_response_dict(file_path): """Return test spotify response JSON file contents as dict.""" with open(os.path.join('tests', 'files', 'spotify', file_path)) as file: response_data = json.load(file) return response_data