"""Unit tests for spotify models layer.""" import time from unittest import mock from unittest.mock import call from unittest.mock import Mock import pytest import requests from analytics.models import spotify @pytest.mark.parametrize('display_name', ['', None]) def test_spotify_api_playlist_data_returns_owner_id_if_no_display_name( display_name): """Test _spotify_api_playlist_data returns owner id.""" return_value = spotify._spotify_api_playlist_data('fake_playlist_link', { 'images': [{'url': 'fake_image_url'}], 'followers': {'total': 82000}, 'name': 'James Loves Tupac', 'external_urls': {'spotify': 'http://external_url'}, 'owner': {'display_name': display_name, 'id': 'test-dj'}}) assert return_value == { 'playlist_link': 'fake_playlist_link', 'playlist_title': 'James Loves Tupac', 'playlist_author': 'test-dj', 'image': 'fake_image_url', 'display_link': 'http://external_url', 'followers': 82000} @pytest.fixture def metadata_fixture(monkeypatch): """Test data and mocked general functions for get_playlist_metadata.""" result = Mock() result.playlist_link = 'playlist_link' result.headers = {} result.playlist_author = 'playlist_author' result.playlist_id = 'playlist_id' result.api_url = spotify.metadata_url_template.format( owner_id=result.playlist_author, playlist_id=result.playlist_id) requests_get = Mock() result.requests_get_result = requests_get.return_value result.requests_get_result.headers = result.headers monkeypatch.setattr(requests, 'get', requests_get) result.requests_get = requests_get fail_details = Mock() fail_details.return_value = {} result.fail_details = fail_details.return_value monkeypatch.setattr(spotify, '_get_fail_details', fail_details) time_sleep = Mock() result.time_sleep = time_sleep monkeypatch.setattr(time, 'sleep', time_sleep) return result def test_get_playlist_metadata_success(monkeypatch, metadata_fixture): """Test _get_playlist_metadata success response.""" # Mocking status_code = 200 metadata_fixture.requests_get_result.status_code = status_code playlist_data = Mock() playlist_data_result = {'playlist_link': metadata_fixture.playlist_link} playlist_data.return_value = playlist_data_result expected_result = playlist_data_result expected_result.update({'status_code': status_code}) monkeypatch.setattr(spotify, '_spotify_api_playlist_data', playlist_data) result = spotify._get_playlist_metadata( metadata_fixture.playlist_link, metadata_fixture.playlist_id, metadata_fixture.headers, Mock()) assert result == expected_result metadata_fixture.requests_get.assert_called_once_with( metadata_fixture.api_url, headers=metadata_fixture.headers, timeout=3) def test_get_playlist_metadata_not_found(metadata_fixture): """Test _get_playlist_metadata not found response.""" # Mocking status_code = 404 metadata_fixture.requests_get_result.status_code = status_code logger = Mock() expected_result = { 'playlist_link': metadata_fixture.playlist_link, 'status_code': status_code} result = spotify._get_playlist_metadata( metadata_fixture.playlist_link, metadata_fixture.playlist_id, metadata_fixture.headers, logger) assert result == expected_result logger.info.assert_called_once_with( "Playlist wasn't found. " 'Playlist link: {}'.format(metadata_fixture.playlist_link)) def test_get_playlist_metadata_throttling( monkeypatch, metadata_fixture, mock_sentry): """Test _get_playlist_metadata for proper throttling processing.""" # Mocking status_code = 429 metadata_fixture.requests_get_result.status_code = status_code expected_result = { 'playlist_link': metadata_fixture.playlist_link, 'status_code': status_code} general_failure = call( 'Failed to obtain Spotify playlist metadata.', extra=metadata_fixture.fail_details) # Tested function call result = spotify._get_playlist_metadata( metadata_fixture.playlist_link, metadata_fixture.playlist_id, metadata_fixture.headers, Mock()) # Checks assert result == expected_result mock_sentry.captureMessage.assert_has_calls([ call('Spotify API limit was reached.', extra=metadata_fixture.fail_details)]) assert general_failure not in mock_sentry.captureMessage.mock_calls def test_get_playlist_metadata_general_failure(metadata_fixture, mock_sentry): """Test _get_playlist_metadata for proper Sentry message on failure.""" # Mocking status_code = 500 metadata_fixture.requests_get_result.status_code = status_code expected_result = { 'playlist_link': metadata_fixture.playlist_link, 'status_code': status_code} result = spotify._get_playlist_metadata( metadata_fixture.playlist_link, metadata_fixture.playlist_id, metadata_fixture.headers, Mock()) throttling_failure = call('Spotify API limit was reached.', extra=mock.ANY) assert result == expected_result mock_sentry.captureMessage.assert_has_calls( [call( 'Failed to obtain Spotify playlist metadata.', extra=metadata_fixture.fail_details)]) assert throttling_failure not in mock_sentry.captureMessage.mock_calls def test_get_playlist_metadata_exception(metadata_fixture, mock_sentry): """Test _get_playlist_metadata for raised exception.""" metadata_fixture.requests_get.side_effect = Exception() result = spotify._get_playlist_metadata( metadata_fixture.playlist_link, metadata_fixture.playlist_id, metadata_fixture.headers, Mock()) expected_result = { 'playlist_link': metadata_fixture.playlist_link, 'status_code': 500} assert result == expected_result def test_get_playlist_metadata_timeout_exception( metadata_fixture, mock_sentry, timeout_exception_class): """Test _get_playlist_metadata for raised timeout exception.""" metadata_fixture.requests_get.side_effect = timeout_exception_class() result = spotify._get_playlist_metadata( metadata_fixture.playlist_link, metadata_fixture.playlist_id, metadata_fixture.headers, Mock()) expected_result = { 'playlist_link': metadata_fixture.playlist_link, 'status_code': 504} assert result == expected_result def test_get_playlists_metadata(monkeypatch): """Test get_playlists_metadata function.""" playlists = [{ 'playlist_link': 'playlist_link', 'playlist_id': 'playlist_id'}] obtain_access_token = Mock() token = obtain_access_token.return_value monkeypatch.setattr(spotify, '_obtain_access_token', obtain_access_token) auth_headers = Mock() monkeypatch.setattr(spotify, '_auth_headers', auth_headers) get_playlist_metadata = Mock() metadata = {} get_playlist_metadata.return_value = metadata monkeypatch.setattr( spotify, '_get_playlist_metadata', get_playlist_metadata) expected_result = [metadata] logger = Mock() result = spotify.get_playlists_metadata( playlists, logger, [1, 2], ['theorchard']) assert result.message == expected_result assert obtain_access_token.call_count == 1 auth_headers.assert_called_once_with(token) def test_get_personalized_playlists_metadata_with_valid_playlist(): """Test get_personalized_playlists_metadata returns correct metadata.""" valid_playlist = { 'playlist_link': 'spotify-personalized-playlist:discoverWeekly', 'playlist_id': 'discoverWeekly'} logger = Mock() return_value = spotify.get_personalized_playlists_metadata([ valid_playlist], logger, [1, 2], ['theorchard']) assert return_value.message == [{ 'display_link': 'https://support.spotify.com' '/us/using_spotify/playlists/discover-weekly/', 'playlist_author': 'Spotify', 'playlist_link': 'spotify-personalized-playlist:discoverWeekly', 'playlist_title': 'Discover Weekly', 'image': 'https://cdn.theorchard.io/web-icons/discoverWeekly.png', 'status_code': 200}] def test_get_personalized_playlists_metadata_with_unknown_playlist(): """Test get_personalized_playlists_metadata returns unknown metadata.""" unknown_playlist = { 'playlist_link': 'spotify-personalized-playlist:unknown_playlist_name', 'playlist_id': 'unknown_playlist_name'} logger = Mock() return_value = spotify.get_personalized_playlists_metadata([ unknown_playlist], logger, [1, 2], ['theorchard']) assert return_value.message == [{ 'playlist_link': 'spotify-personalized-playlist:unknown_playlist_name', 'playlist_title': 'Spotify Personalized Playlist', 'playlist_author': 'Spotify', 'status_code': 200}]