"""Unit tests for sound recording streams_by_product logic layer.""" import datetime from unittest.mock import patch import pytest from sound_recordings.api import app from sound_recordings.logic import streams_by_product as streams_by_product @pytest.fixture def mock_get_streams_by_product_model_payload(): """Mock payload for sound recording streams_by_product model.""" return [ { "product_id": "123", "date": datetime.date(2018, 6, 28), "streams": 500, "streams_with_skips": 0, "skips": None, "saves": None, }, { "product_id": "456", "date": datetime.date(2018, 6, 28), "streams": 3000, "streams_with_skips": 2000, "skips": 300, "saves": 600, }, { "product_id": "321", "date": datetime.date(2018, 6, 28), "streams": 3000, "streams_with_skips": 2000, "skips": 300, "saves": 600, }, { "product_id": "123", "date": datetime.date(2018, 6, 29), "streams": 2000, "streams_with_skips": 1000, "skips": 200, "saves": 400, }, { "product_id": "321", "date": datetime.date(2018, 6, 29), "streams": 1000, "streams_with_skips": 0, "skips": None, "saves": None, }, ] @pytest.fixture def expected_payload(): """Return expected payload from streams_by_product logic.""" return { "isrc": "isrc", "products": [ { "product_id": "321", "items": [ { "streams": 3000, "saves": 600, "skip_rate": 0.13043478260869565, "date": "2018-06-28T00:00:00Z", }, { "streams": 1000, "saves": None, "skip_rate": None, "date": "2018-06-29T00:00:00Z", }, ], }, { "product_id": "456", "items": [ { "streams": 3000, "saves": 600, "skip_rate": 0.13043478260869565, "date": "2018-06-28T00:00:00Z", }, { "streams": 0, "saves": None, "skip_rate": None, "date": "2018-06-29T00:00:00Z", }, ], }, { "product_id": "123", "items": [ { "streams": 500, "saves": None, "skip_rate": None, "date": "2018-06-28T00:00:00Z", }, { "streams": 2000, "saves": 400, "skip_rate": 0.16666666666666666, "date": "2018-06-29T00:00:00Z", }, ], }, ], } @pytest.fixture def mock_get_streams_by_product_model_success( mock_get_streams_by_product_model_payload, ): """Mock successful get_streams_by_product model response.""" with patch( "sound_recordings.models.streams_by_product.get_streams_by_product" ) as get_streams_by_product: get_streams_by_product.return_value = mock_get_streams_by_product_model_payload yield get_streams_by_product @pytest.fixture def mock_get_streams_by_product_model_failure(): """Mock failure get_streams_by_product model response.""" with patch( "sound_recordings.models.streams_by_product.get_streams_by_product" ) as get_streams_by_product: get_streams_by_product.return_value = [] yield get_streams_by_product class TestGetStreamsByProductWithLabel: """Test get_streams_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_streams_by_product_model_success, request_context_for_label, mock_permissions_for_label, ): """Run get_streams_by_product.""" return streams_by_product.get_streams_by_product( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload): """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) def test_get_streams_by_product_model_is_called( self, response, mock_get_streams_by_product_model_success, permissions_for_label ): """Test get_streams_by_product model is called.""" mock_get_streams_by_product_model_success.assert_called_once_with( permissions_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_streams_by_product_model_fails( self, mock_get_streams_by_product_model_failure, mock_permissions_for_label, request_context_for_label, ): """Test failure response when streams_by_product model fails.""" response = streams_by_product.get_streams_by_product( request_context_for_label, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) assert response.status == 404 # assert response.status == 200 # assert response.message == { # 'isrc': self.isrc, # 'products': [] # } class TestGetStreamsByProductWithSubaccount: """Test get_streams_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_streams_by_product_model_success, mock_permissions_for_subaccount, request_context_for_subaccount, ): """Run get_streams_by_product.""" with app.test_request_context(): return streams_by_product.get_streams_by_product( request_context_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload): """Test successful response.""" assert response.status == 200 assert sorted(response.message) == sorted(expected_payload) def test_get_streams_by_product_model_is_called( self, response, mock_get_streams_by_product_model_success, permissions_for_subaccount, ): """Test get_streams_by_product model is called.""" mock_get_streams_by_product_model_success.assert_called_once_with( permissions_for_subaccount, self.isrc, ["theorchard"], [], [], self.start_date, self.end_date, ) def test_fails_when_streams_by_product_model_fails( self, mock_get_streams_by_product_model_failure, mock_permissions_for_subaccount, request_context_for_subaccount, ): """Test failure response when streams_by_product model fails.""" response = streams_by_product.get_streams_by_product( request_context_for_subaccount, self.isrc, ["theorchard"] ) assert response.status == 404 # assert response.status == 200 # assert response.message == { # 'isrc': self.isrc, # 'countries': [] # }