"""Unit tests for streams_by_store model layer.""" import datetime from unittest.mock import patch import pytest from sound_recordings.models import streams_by_store as streams_by_store from tests.unit.models.conftest import snowflake_fetch_assert # This mock SQL is to test that filtering is correct MOCK_SQL = "{filter_clause}" @pytest.fixture def mock_load_query(): """Mock load query.""" with patch("sound_recordings.models.streams_by_store.SQLLoader") as sql_loader: load_query = sql_loader.load_query load_query.return_value = MOCK_SQL yield load_query @pytest.fixture def mock_store_availability(): """Mock store_availability.""" with patch( "sound_recordings.models.streams_by_store.store_availability" ) as store_availability: store_availability.get_store_ids.return_value = [1, 4, 286, 348, 496, 708, 716] store_availability.get_download_store_ids.return_value = [1, 187, 496] yield store_availability @pytest.fixture def db_result(): """Mock db result.""" return [ (1, datetime.date(2018, 7, 4), 40000, 1000, 300, 600), (1, datetime.date(2018, 7, 5), 2000, 1000, 400, 800), (286, datetime.date(2018, 7, 4), 126, 0, None, None), (286, datetime.date(2018, 7, 5), 3126, 0, None, None), (1, datetime.date(2018, 7, 6), 1126, 800, 400, 100), ] @pytest.fixture def db_result_country_filter(): """Mock db result.""" return [ (1, datetime.date(2018, 7, 4), 20000, 500, 150, 300), (286, datetime.date(2018, 7, 5), 1500, 0, None, None), ] @pytest.fixture def expected_response(): """Expect formatted response.""" return [ { "store_id": 1, "date": datetime.date(2018, 7, 4), "streams": 40000, "streams_with_skips": 1000, "skips": 300, "saves": 600, }, { "store_id": 1, "date": datetime.date(2018, 7, 5), "streams": 2000, "streams_with_skips": 1000, "skips": 400, "saves": 800, }, { "store_id": 286, "date": datetime.date(2018, 7, 4), "streams": 126, "streams_with_skips": 0, "skips": None, "saves": None, }, { "store_id": 286, "date": datetime.date(2018, 7, 5), "streams": 3126, "streams_with_skips": 0, "skips": None, "saves": None, }, { "store_id": 1, "date": datetime.date(2018, 7, 6), "streams": 1126, "streams_with_skips": 800, "skips": 400, "saves": 100, }, ] @pytest.fixture def expected_response_country_filter(): """Expect formatted response.""" return [ { "store_id": 1, "date": datetime.date(2018, 7, 4), "streams": 20000, "streams_with_skips": 500, "skips": 150, "saves": 300, }, { "store_id": 286, "date": datetime.date(2018, 7, 5), "streams": 1500, "streams_with_skips": 0, "skips": None, "saves": None, }, ] class TestGetStreamsByStoreWithLabel: """Test get_streams_by_store with Label.""" permissions_filter = { "label_ids": [7123], "artist_ids": None, "subaccount_ids": None, "feed_ids": [1, 2], } args = { "isrc": "isrc", "start_date": "2019-12-01", "end_date": "2019-12-01", "distributors": ["theorchard"], } expected_sql = ( "product_id IN (SELECT product_id FROM dim_release WHERE " "labelid IN (:label_ids)) " "AND (download_activity_date " "BETWEEN :start_date AND :end_date) AND feed_id " "IN (:feed_ids) " ) @pytest.fixture def mock_snowflake_fetchall(self, db_result): """Mock Snowflake fetchall.""" with patch( "sound_recordings.models.streams_by_store.snowflake.fetchall" ) as fetchall: fetchall.return_value = db_result yield fetchall @pytest.fixture(autouse=True) def no_cache(self): """Mock out caching of response.""" with patch("sound_recordings.connectors.redis.client.get") as get: get.return_value = None yield get @pytest.fixture def response( self, mock_snowflake_fetchall, mock_load_query, mock_store_availability, expected_response, ): """Return track streams.""" return streams_by_store.get_streams_by_store( self.permissions_filter, **self.args ) def test_succeeds(self, response, expected_response): """Test successful response.""" assert response == expected_response def test_query_is_loaded(self, response, mock_load_query): """Test correct query is loaded.""" mock_load_query.assert_called_once_with("streams_by_store") def test_loaded_query_is_run(self, response, mock_snowflake_fetchall): """Test loaded query is run.""" expected_args = self.args expected_args["store_ids"] = [1, 4, 286, 348, 496, 708, 716] snowflake_fetch_assert( mock_snowflake_fetchall, self.expected_sql, {**self.permissions_filter, **expected_args}, ) class TestGetStreamsByStoreWithCountryFilter: """Test get_streams_by_store with Label & with country filter.""" permissions_filter = { "label_ids": [7123], "artist_ids": None, "subaccount_ids": None, "feed_ids": [1, 2], } args = { "isrc": "isrc", "countries": ["US"], "start_date": "2019-12-01", "end_date": "2019-12-01", "distributors": ["theorchard"], } expected_sql = ( "product_id IN (SELECT product_id FROM dim_release WHERE " "labelid IN (:label_ids)) " "AND (download_activity_date " "BETWEEN :start_date AND :end_date) AND feed_id " "IN (:feed_ids) " ) @pytest.fixture def mock_snowflake_fetchall(self, db_result_country_filter): """Mock Snowflake fetchall.""" with patch( "sound_recordings.models.streams_by_store.snowflake.fetchall" ) as fetchall: fetchall.return_value = db_result_country_filter yield fetchall @pytest.fixture(autouse=True) def no_cache(self): """Mock out caching of response.""" with patch("sound_recordings.connectors.redis.client.get") as get: get.return_value = None yield get @pytest.fixture def response( self, mock_snowflake_fetchall, mock_load_query, mock_store_availability, expected_response_country_filter, ): """Return track streams.""" return streams_by_store.get_streams_by_store( self.permissions_filter, **self.args ) def test_succeeds(self, response, expected_response_country_filter): """Test successful response.""" assert response == expected_response_country_filter def test_query_is_loaded(self, response, mock_load_query): """Test correct query is loaded.""" mock_load_query.assert_called_once_with("streams_by_store_by_country") def test_loaded_query_is_run(self, response, mock_snowflake_fetchall): """Test loaded query is run.""" expected_args = self.args del expected_args["countries"] expected_args["country_codes"] = ["US"] expected_args["store_ids"] = [1, 4, 286, 348, 496, 708, 716] snowflake_fetch_assert( mock_snowflake_fetchall, self.expected_sql, {**self.permissions_filter, **expected_args}, ) class TestGetStreamsByStoreWithSubaccount: """Test get_streams_by_store with Subaccount.""" permissions_filter = { "label_ids": None, "artist_ids": None, "subaccount_ids": [345], "feed_ids": [1, 2], } args = { "isrc": "isrc", "distributors": ["theorchard"], "store_ids": [1, 286], "start_date": "2019-12-01", "end_date": "2019-12-01", } expected_sql = ( "product_id IN (SELECT product_id FROM dim_release WHERE " "subaccountid IN (:subaccount_ids)) " "AND (download_activity_date " "BETWEEN :start_date AND :end_date) AND feed_id " "IN (:feed_ids) " ) @pytest.fixture def mock_snowflake_fetchall(self, db_result): """Mock Snowflake fetchall.""" with patch( "sound_recordings.models.streams_by_store.snowflake.fetchall" ) as fetchall: fetchall.return_value = db_result yield fetchall @pytest.fixture(autouse=True) def no_cache(self): """Mock out caching of response.""" with patch("sound_recordings.connectors.redis.client.get") as get: get.return_value = None yield get @pytest.fixture def response( self, mock_snowflake_fetchall, mock_load_query, mock_store_availability, expected_response, ): """Return track streams.""" return streams_by_store.get_streams_by_store( self.permissions_filter, **self.args ) def test_succeeds(self, response, expected_response): """Test successful response.""" assert response == expected_response def test_query_is_loaded(self, response, mock_load_query): """Test correct query is loaded.""" mock_load_query.assert_called_once_with("streams_by_store") def test_loaded_query_is_run(self, response, mock_snowflake_fetchall): """Test loaded query is run.""" expected_args = self.args expected_args["store_ids"] = [1, 286] snowflake_fetch_assert( mock_snowflake_fetchall, self.expected_sql, {**self.permissions_filter, **expected_args}, )