"""Unit tests for the source of streams logic layer.""" import datetime from unittest.mock import patch import pytest from sound_recordings.logic import source_of_streams @pytest.fixture def mock_get_sos_model_payload(): """Mock payload for source of streams model.""" return { "isrc": "TEST", "streams_passive_7_days": 0, "streams_active_7_days": 2, "streams_collection_7_days": 2, "streams_7_days": 4, "streams_active_7_days_growth": -0.5, "streams_passive_7_days_growth": 0.333, "streams_collection_7_days_growth": None, } @pytest.fixture def mock_get_dynamic_sos_model_payload(): """Mock payload for source of streams model.""" return { "isrc": "TEST", "streams_passive": 0, "streams_active": 2, "streams_collection": 2, "streams": 4, } @pytest.fixture def mock_get_sos_model_payload_zero_streams(): """Mock payload for source of streams model.""" return { "isrc": "TEST", "streams_passive_7_days": 0, "streams_active_7_days": 0, "streams_collection_7_days": 0, "streams_7_days": 0, "streams_active_7_days_growth": 0, "streams_passive_7_days_growth": 0, "streams_collection_7_days_growth": None, } @pytest.fixture def expected_payload(): """Return expected payload from logic.""" return { "isrc": "TEST", "active": {"value": 0.5, "growth_percentage": -0.5, "total": 2}, "passive": {"value": 0, "growth_percentage": 0.333, "total": 0}, "collection": {"value": 0.5, "growth_percentage": None, "total": 2}, "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music"}, {"id": 716, "name": "Amazon Unlimited"}, ], } @pytest.fixture def expected_dynamic_payload(): """Return expected payload from logic.""" return { "isrc": "TEST", "active": {"value": 0.5, "growth_percentage": None, "total": 2}, "passive": {"value": 0, "growth_percentage": None, "total": 0}, "collection": {"value": 0.5, "growth_percentage": None, "total": 2}, "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music"}, {"id": 716, "name": "Amazon Unlimited"}, ], } @pytest.fixture def expected_payload_zero_streams(): """Return expected payload from logic.""" return { "isrc": "TEST", "active": {"value": 0, "growth_percentage": 0, "total": 0}, "passive": {"value": 0, "growth_percentage": 0, "total": 0}, "collection": {"value": 0, "growth_percentage": None, "total": 0}, "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music"}, {"id": 716, "name": "Amazon Unlimited"}, ], } @pytest.fixture def mock_add_outage_error_to_stores(): """Mock add_outage_error_to_stores.""" with patch( "sound_recordings.logic.source_of_streams.add_outage_error_to_stores" ) as add_outage_error_to_stores: add_outage_error_to_stores.return_value = [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music"}, {"id": 716, "name": "Amazon Unlimited"}, ] yield add_outage_error_to_stores @pytest.fixture def mock_get_sos_breakdown_success( mock_get_sos_model_payload, mock_add_outage_error_to_stores ): """Mock successful get_sos_breakdown model response.""" with patch( "sound_recordings.models.source_of_streams.get_sos_breakdown" ) as get_sos_breakdown: get_sos_breakdown.return_value = mock_get_sos_model_payload yield get_sos_breakdown @pytest.fixture def mock_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 = "2019-12-31" yield get_max_available_date @pytest.fixture def mock_get_dynamic_sos_breakdown_success( mock_get_dynamic_sos_model_payload, mock_add_outage_error_to_stores, mock_max_available_date, ): """Mock successful get_sos_breakdown model response.""" with patch( "sound_recordings.models.source_of_streams." "get_dynamic_sos_breakdown" ) as get_dynamic_sos_breakdown: get_dynamic_sos_breakdown.return_value = mock_get_dynamic_sos_model_payload yield get_dynamic_sos_breakdown @pytest.fixture def mock_get_sos_breakdown_success_zero_streams( mock_get_sos_model_payload_zero_streams, mock_add_outage_error_to_stores ): """Mock successful get_sos_breakdown model response with zero streams.""" with patch( "sound_recordings.models.source_of_streams.get_sos_breakdown" ) as get_sos_breakdown: get_sos_breakdown.return_value = mock_get_sos_model_payload_zero_streams yield get_sos_breakdown @pytest.fixture def mock_get_sos_breakdown_failure(mock_add_outage_error_to_stores): """Mock failure sos_breakdown model response.""" with patch( "sound_recordings.models.source_of_streams.get_sos_breakdown" ) as get_sos_breakdown: get_sos_breakdown.return_value = None yield get_sos_breakdown @pytest.fixture def mock_get_dynamic_sos_breakdown_failure(mock_add_outage_error_to_stores): """Mock failure sos_breakdown model response.""" with patch( "sound_recordings.models.source_of_streams" ".get_dynamic_sos_breakdown" ) as get_dynamic_sos_breakdown: get_dynamic_sos_breakdown.return_value = None yield get_dynamic_sos_breakdown @pytest.fixture def mock_store_availability(): """Mock store_availability.""" with patch( "sound_recordings.models.source_of_streams.store_availability" ) as store_availability: store_availability.get_sources.return_value = [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music"}, ] yield store_availability @pytest.fixture def get_source_breakdown_response( mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, ): """Return response from get_source_breakdown.""" return source_of_streams.get_source_breakdown( request_context_for_label, "TEST", [], [], None, None, ["theorchard"] ) @pytest.fixture def get_source_breakdown_response_with_start_and_end_date( mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, ): """Return response from get_source_breakdown.""" return source_of_streams.get_source_breakdown( request_context_for_label, "TEST", [], [], "2019-11-01", "2019-12-01", ["theorchard"], ) @pytest.fixture def get_source_breakdown_response_with_countries( mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, ): """Return response from get_source_breakdown.""" return source_of_streams.get_source_breakdown( request_context_for_label, "TEST", ["DE", "NO", "US"], [], None, None, ["theorchard"], ) @pytest.fixture def get_source_breakdown_response_with_store_ids( mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, ): """Return response from get_source_breakdown.""" return source_of_streams.get_source_breakdown( request_context_for_label, "TEST", [], [1, 286], None, None, ["theorchard"] ) def test_get_source_breakdown_model_called( mock_get_sos_breakdown_success, permissions_for_label, get_source_breakdown_response, mock_add_outage_error_to_stores, ): """Test model layer called from logic.""" mock_get_sos_breakdown_success.assert_called_once_with( permissions_for_label, "TEST", ["theorchard"] ) def test_get_source_breakdown_model_called_with_start_and_end_date( mock_get_dynamic_sos_breakdown_success, permissions_for_label, get_source_breakdown_response_with_start_and_end_date, mock_add_outage_error_to_stores, ): """Test model layer called from logic.""" mock_get_dynamic_sos_breakdown_success.assert_called_once_with( permissions_for_label, "TEST", ["theorchard"], [], [], "2019-11-01", "2019-12-01", ) def test_get_source_breakdown_model_called_with_countries( mock_get_dynamic_sos_breakdown_success, permissions_for_label, get_source_breakdown_response_with_countries, mock_add_outage_error_to_stores, ): """Test model layer called from logic.""" mock_get_dynamic_sos_breakdown_success.assert_called_once_with( permissions_for_label, "TEST", ["theorchard"], ["DE", "NO", "US"], [], datetime.date(2019, 12, 31) - datetime.timedelta(days=7 - 1), datetime.date(2019, 12, 31), ) def test_get_source_breakdown_model_called_with_store_ids( mock_get_dynamic_sos_breakdown_success, permissions_for_label, get_source_breakdown_response_with_store_ids, mock_add_outage_error_to_stores, ): """Test model layer called from logic.""" mock_get_dynamic_sos_breakdown_success.assert_called_once_with( permissions_for_label, "TEST", ["theorchard"], [], [1, 286], datetime.date(2019, 12, 31) - datetime.timedelta(days=7 - 1), datetime.date(2019, 12, 31), ) def test_get_source_breakdown_success( mock_get_sos_breakdown_success, expected_payload, get_source_breakdown_response, mock_add_outage_error_to_stores, ): """Test successful response.""" assert get_source_breakdown_response.status == 200 assert get_source_breakdown_response.message == expected_payload def test_get_source_breakdown_success_with_start_and_end_date( mock_get_dynamic_sos_breakdown_success, expected_dynamic_payload, get_source_breakdown_response_with_start_and_end_date, mock_add_outage_error_to_stores, ): """Test successful response.""" assert get_source_breakdown_response_with_start_and_end_date.status == 200 assert ( get_source_breakdown_response_with_start_and_end_date.message == expected_dynamic_payload ) def test_get_source_breakdown_success_with_countries( mock_get_dynamic_sos_breakdown_success, expected_dynamic_payload, get_source_breakdown_response_with_countries, mock_add_outage_error_to_stores, ): """Test successful response.""" assert get_source_breakdown_response_with_countries.status == 200 assert ( get_source_breakdown_response_with_countries.message == expected_dynamic_payload ) def test_get_source_breakdown_success_with_store_ids( mock_get_dynamic_sos_breakdown_success, expected_dynamic_payload, get_source_breakdown_response_with_store_ids, mock_add_outage_error_to_stores, ): """Test successful response.""" assert get_source_breakdown_response_with_store_ids.status == 200 assert ( get_source_breakdown_response_with_store_ids.message == expected_dynamic_payload ) def test_get_source_breakdown_success_zero_streams( mock_get_sos_breakdown_success_zero_streams, expected_payload_zero_streams, get_source_breakdown_response, mock_add_outage_error_to_stores, ): """Test successful response.""" assert get_source_breakdown_response.status == 200 assert get_source_breakdown_response.message == expected_payload_zero_streams def test_get_source_breakdown_failure( mock_get_sos_breakdown_failure, get_source_breakdown_response, mock_add_outage_error_to_stores, expected_payload, ): """Test get_source_breakdown when model fails.""" assert get_source_breakdown_response.status == 200 expected_payload["active"] = {} expected_payload["passive"] = {} expected_payload["collection"] = {} assert get_source_breakdown_response.message == expected_payload def test_get_source_breakdown_failure_with_start_and_end_date( mock_get_dynamic_sos_breakdown_failure, get_source_breakdown_response_with_start_and_end_date, mock_add_outage_error_to_stores, expected_dynamic_payload, ): """Test get_source_breakdown when model fails.""" assert get_source_breakdown_response_with_start_and_end_date.status == 200 expected_dynamic_payload["active"] = {} expected_dynamic_payload["passive"] = {} expected_dynamic_payload["collection"] = {} assert ( get_source_breakdown_response_with_start_and_end_date.message == expected_dynamic_payload ) def test_get_source_breakdown_failure_with_countries( mock_get_dynamic_sos_breakdown_failure, get_source_breakdown_response_with_countries, mock_add_outage_error_to_stores, expected_dynamic_payload, ): """Test get_source_breakdown when model fails.""" assert get_source_breakdown_response_with_countries.status == 200 expected_dynamic_payload["active"] = {} expected_dynamic_payload["passive"] = {} expected_dynamic_payload["collection"] = {} assert ( get_source_breakdown_response_with_countries.message == expected_dynamic_payload ) def test_get_source_breakdown_failure_with_store_ids( mock_get_dynamic_sos_breakdown_failure, get_source_breakdown_response_with_store_ids, mock_add_outage_error_to_stores, expected_dynamic_payload, ): """Test get_source_breakdown when model fails.""" assert get_source_breakdown_response_with_store_ids.status == 200 expected_dynamic_payload["active"] = {} expected_dynamic_payload["passive"] = {} expected_dynamic_payload["collection"] = {} assert ( get_source_breakdown_response_with_store_ids.message == expected_dynamic_payload )