"""Unit tests for sound recording streams logic layer.""" import datetime from decimal import Decimal from unittest.mock import patch import pytest from oto import response as oto_response from sound_recordings.api import app from sound_recordings.logic import streams as streams @pytest.fixture def mock_get_streams_model_payload(): """Mock payload for sound recording streams model.""" return [ { "store_id": 1, "date": datetime.date(2018, 6, 28), "streams": 500, "streams_with_skips": 0, "skips": None, "saves": None, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 1, "date": datetime.date(2018, 6, 29), "streams": 1000, "streams_with_skips": 0, "skips": None, "saves": None, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 286, "date": datetime.date(2018, 6, 28), "streams": 3000, "streams_with_skips": 2000, "skips": 300, "saves": 600, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 286, "date": datetime.date(2018, 6, 29), "streams": 2000, "streams_with_skips": 1000, "skips": 200, "saves": 400, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 1, "date": datetime.date(2018, 7, 5), "streams": 1000, "streams_with_skips": 0, "skips": None, "saves": None, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 1, "date": datetime.date(2018, 7, 6), "streams": 2000, "streams_with_skips": 0, "skips": None, "saves": None, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 286, "date": datetime.date(2018, 7, 5), "streams": 6000, "streams_with_skips": 0, "skips": None, "saves": None, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 286, "date": datetime.date(2018, 7, 6), "streams": 4000, "streams_with_skips": 3000, "skips": 400, "saves": 800, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc", }, { "store_id": 286, "date": datetime.date(2018, 7, 6), "streams": 4000, "streams_with_skips": 3000, "skips": 400, "saves": 800, "max_available_date": datetime.date(2018, 7, 6), "isrc": "isrc2", }, ] @pytest.fixture def mock_get_streams_all_time_model_payload(): """Mock payload for sound recording streams model.""" return [ { "store_id": 1, "all_time": 50000, "growth_percentage": Decimal(1.0), "isrc": "isrc", }, { "store_id": 286, "all_time": 100000, "growth_percentage": Decimal(1.0), "isrc": "isrc", }, { "store_id": 286, "all_time": 100000, "growth_percentage": Decimal(1.0), "isrc": "isrc2", }, ] @pytest.fixture def mock_get_streams_all_time_model_payload_no_recent_streams(): """Mock payload for sound recording streams model.""" return [ {"store_id": 1, "all_time": 50000, "growth_percentage": None, "isrc": "isrc"}, { "store_id": 286, "all_time": 100000, "growth_percentage": None, "isrc": "isrc", }, ] @pytest.fixture def mock_get_streams_all_time_model_payload_last_two_weeks(): """Mock payload for sound recording streams model.""" return [ {"store_id": 1, "all_time": 4500, "growth_percentage": None, "isrc": "isrc"}, {"store_id": 286, "all_time": 15000, "growth_percentage": None, "isrc": "isrc"}, ] @pytest.fixture def empty_all_time_streams_payload(): """Payload for sound recording with empty recent and all time streams.""" return { "isrc": "isrc", "aggregate": {"items": [], "all_time": 0}, "stores": [], "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, ], } @pytest.fixture def all_time_streams_with_empty_recent_streams_payload(): """Payload for sound rec with all time streams and no recent streams.""" return { "isrc": "isrc", "aggregate": { "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-29T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, ], "all_time": 150000, "skip_rate": None, "growth_percentage": None, }, "stores": [ { "id": 1, "name": "Apple Music", "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-29T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, ], "all_time": 50000, "skip_rate": None, "growth_percentage": None, }, { "id": 286, "name": "Spotify", "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-29T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, ], "all_time": 100000, "skip_rate": None, "growth_percentage": None, }, ], "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, ], } @pytest.fixture def all_time_streams_equals_prev_and_current_week_payload(): """Payload for sound rec with all time streams and no recent streams.""" return { "isrc": "isrc", "aggregate": { "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 3500, "saves": 600, "skip_rate": 300 / (300 + 2000), }, { "date": "2018-06-29T00:00:00Z", "streams": 3000, "saves": 400, "skip_rate": 200 / (200 + 1000), }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 7000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 6000, "saves": 800, "skip_rate": 400 / (400 + 3000), }, ], "all_time": 19500, "skip_rate": (300 + 200 + 400) / (300 + 200 + 400 + 2000 + 1000 + 3000), "growth_percentage": None, }, "stores": [ { "id": 1, "name": "Apple Music", "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 500, "saves": None, "skip_rate": None, }, { "date": "2018-06-29T00:00:00Z", "streams": 1000, "saves": None, "skip_rate": None, }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 1000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 2000, "saves": None, "skip_rate": None, }, ], "all_time": 4500, "skip_rate": None, "growth_percentage": None, }, { "id": 286, "name": "Spotify", "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 3000, "saves": 600, "skip_rate": 300 / (300 + 2000), }, { "date": "2018-06-29T00:00:00Z", "streams": 2000, "saves": 400, "skip_rate": 200 / (200 + 1000), }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 6000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 4000, "saves": 800, "skip_rate": 400 / (400 + 3000), }, ], "all_time": 15000, "skip_rate": (300 + 200 + 400) / (300 + 200 + 400 + 2000 + 1000 + 3000), "growth_percentage": None, }, ], "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, ], } @pytest.fixture def expected_payload(): """Return expected payload from logic.""" return { "isrc": "isrc", "aggregate": { "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 3500, "saves": 600, "skip_rate": 300 / (300 + 2000), }, { "date": "2018-06-29T00:00:00Z", "streams": 3000, "saves": 400, "skip_rate": 200 / (200 + 1000), }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 7000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 6000, "saves": 800, "skip_rate": 400 / (400 + 3000), }, ], "all_time": 150000, "skip_rate": (300 + 200 + 400) / (300 + 200 + 400 + 2000 + 1000 + 3000), "growth_percentage": 1.0, }, "stores": [ { "id": 1, "name": "Apple Music", "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 500, "saves": None, "skip_rate": None, }, { "date": "2018-06-29T00:00:00Z", "streams": 1000, "saves": None, "skip_rate": None, }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 1000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 2000, "saves": None, "skip_rate": None, }, ], "all_time": 50000, "skip_rate": None, "growth_percentage": 1.0, }, { "id": 286, "name": "Spotify", "items": [ { "date": "2018-06-09T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-10T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-11T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-12T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-13T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-14T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-15T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-16T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-17T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-18T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-19T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-20T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-21T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-22T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-23T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-24T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-25T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-26T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-27T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-06-28T00:00:00Z", "streams": 3000, "saves": 600, "skip_rate": 300 / (300 + 2000), }, { "date": "2018-06-29T00:00:00Z", "streams": 2000, "saves": 400, "skip_rate": 200 / (200 + 1000), }, { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 6000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 4000, "saves": 800, "skip_rate": 400 / (400 + 3000), }, ], "all_time": 100000, "skip_rate": (300 + 200 + 400) / (300 + 200 + 400 + 2000 + 1000 + 3000), "growth_percentage": 1.0, }, ], "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, ], } @pytest.fixture def expected_payload_for_second_isrc(): """Return expected payload from logic.""" return { "aggregate": { "all_time": 100000, "growth_percentage": None, "items": [ { "date": "2018-06-09T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-10T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-11T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-12T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-13T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-14T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-15T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-16T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-17T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-18T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-19T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-20T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-21T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-22T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-23T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-24T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-25T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-26T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-27T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-28T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-29T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-30T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-01T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-02T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-03T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-04T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-05T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-06T00:00:00Z", "saves": 800, "skip_rate": 0.11764705882352941, "streams": 4000, }, ], "skip_rate": 0.11764705882352941, }, "isrc": "isrc2", "sources": [ {"id": 286, "name": "Spotify"}, {"error": {"code": "unreliable"}, "id": 1, "name": "Apple Music"}, ], "stores": [ { "all_time": 100000, "growth_percentage": 1.0, "id": 286, "items": [ { "date": "2018-06-09T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-10T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-11T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-12T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-13T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-14T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-15T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-16T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-17T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-18T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-19T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-20T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-21T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-22T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-23T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-24T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-25T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-26T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-27T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-28T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-29T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-06-30T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-01T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-02T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-03T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-04T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-05T00:00:00Z", "saves": None, "skip_rate": None, "streams": 0, }, { "date": "2018-07-06T00:00:00Z", "saves": 800, "skip_rate": 0.11764705882352941, "streams": 4000, }, ], "name": "Spotify", "skip_rate": 0.11764705882352941, } ], } @pytest.fixture def expected_payload_seven_days(): """Return expected payload from logic.""" return { "isrc": "isrc", "aggregate": { "items": [ { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 7000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 6000, "saves": 800, "skip_rate": 400 / (400 + 3000), }, ], "all_time": 150000, "skip_rate": 400 / (400 + 3000), "growth_percentage": None, }, "stores": [ { "id": 1, "name": "Apple Music", "items": [ { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 1000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 2000, "saves": None, "skip_rate": None, }, ], "all_time": 50000, "skip_rate": None, "growth_percentage": 1.0, }, { "id": 286, "name": "Spotify", "items": [ { "date": "2018-06-30T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-01T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-02T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-03T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-04T00:00:00Z", "streams": 0, "saves": None, "skip_rate": None, }, { "date": "2018-07-05T00:00:00Z", "streams": 6000, "saves": None, "skip_rate": None, }, { "date": "2018-07-06T00:00:00Z", "streams": 4000, "saves": 800, "skip_rate": (400 / (400 + 3000)), }, ], "all_time": 100000, "skip_rate": 400 / (400 + 3000), "growth_percentage": 1.0, }, ], "sources": [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music", "error": {"code": "unreliable"}}, ], } @pytest.fixture def mock_add_outage_error_to_stores(): """Mock add_outage_error_to_stores.""" with patch( "sound_recordings.logic.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", "error": {"code": "unreliable"}}, ] yield add_outage_error_to_stores @pytest.fixture def mock_get_streams_model_success(mock_get_streams_model_payload): """Mock successful get_streams model response.""" with patch("sound_recordings.models.streams.get_streams_bulk") as get_streams: get_streams.return_value = oto_response.Response(mock_get_streams_model_payload) with app.test_request_context(): yield get_streams @pytest.fixture def mock_get_streams_all_time_model_success(mock_get_streams_all_time_model_payload): """Mock successful get_streams_all_time model response.""" with patch( "sound_recordings.models.streams.get_streams_all_time_bulk" ) as get_streams: get_streams.return_value = oto_response.Response( mock_get_streams_all_time_model_payload ) with app.test_request_context(): yield get_streams @pytest.fixture def mock_get_streams_all_time_model_success_no_recent_streams( mock_get_streams_all_time_model_payload_no_recent_streams, ): """Mock successful get_streams_all_time model response.""" with patch( "sound_recordings.models.streams.get_streams_all_time_bulk" ) as get_streams_all_time: get_streams_all_time.return_value = oto_response.Response( mock_get_streams_all_time_model_payload_no_recent_streams ) with app.test_request_context(): yield get_streams_all_time @pytest.fixture def mock_get_streams_all_time_model_success_last_two_weeks( mock_get_streams_all_time_model_payload_last_two_weeks, ): """Mock successful get_streams_all_time model response.""" with patch( "sound_recordings.models.streams.get_streams_all_time_bulk" ) as get_streams: get_streams.return_value = oto_response.Response( mock_get_streams_all_time_model_payload_last_two_weeks ) with app.test_request_context(): yield get_streams @pytest.fixture def mock_get_max_available_date_success(): """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 = "2018-07-06" yield get_max_available_date @pytest.fixture def mock_get_streams_model_failure(): """Mock failure get_streams model response.""" with patch("sound_recordings.models.streams.get_streams_bulk") as get_streams: get_streams.return_value = oto_response.Response([]) with app.test_request_context(): yield get_streams @pytest.fixture def mock_get_streams_all_time_model_failure(): """Mock failure get_streams_all_time model response.""" with patch( "sound_recordings.models.streams.get_streams_all_time_bulk" ) as get_streams: get_streams.return_value = oto_response.Response([]) with app.test_request_context(): yield get_streams @pytest.fixture def mock_get_max_available_date_failure(): """Mock failure get_max_available_date model response.""" with patch( "sound_recordings.logic.streams.data_availability." "get_max_available_date" ) as get_streams: get_streams.return_value = None yield get_streams @pytest.fixture def mock_store_availability(): """Mock store_availability.""" with patch( "sound_recordings.logic.streams.store_availability" ) as store_availability: store_availability.get_sources.return_value = [ {"id": 286, "name": "Spotify"}, {"id": 1, "name": "Apple Music"}, ] store_availability.get_store_names.return_value = { 286: "Spotify", 1: "Apple Music", } yield store_availability class TestGetStreamsWithLabel: """Test get_streams with label.""" isrcs = ["isrc", "isrc2"] @pytest.fixture def response( self, mock_get_streams_model_success, mock_get_streams_all_time_model_success, mock_get_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_streams.""" with app.test_request_context(): return streams.get_streams_bulk( request_context_for_label, self.isrcs, ["theorchard"], [], [] ) def test_succeeds( self, response, expected_payload, expected_payload_for_second_isrc ): """Test successful response.""" assert response.status == 200 response_message = response.message["isrc"] response_sources = response_message["sources"] expected_sources = expected_payload["sources"] assert response_sources == expected_sources response_stores = response_message["stores"] expected_stores = expected_payload["stores"] assert response_stores == expected_stores response_aggregate = response_message["aggregate"] expected_aggregate = expected_payload["aggregate"] assert response_aggregate == expected_aggregate second_isrc_response = response.message["isrc2"] assert second_isrc_response == expected_payload_for_second_isrc def test_get_streams_model_is_called( self, response, mock_get_streams_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_streams model is called.""" mock_get_streams_model_success.assert_called_once_with( permissions_for_label, self.isrcs, ["theorchard"], [], [], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) def test_get_streams_all_time_model_is_called( self, response, mock_get_streams_all_time_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_streams_all_time model is called.""" mock_get_streams_all_time_model_success.assert_called_once_with( permissions_for_label, self.isrcs, ["theorchard"], [], [] ) def test_when_only_recent_streams_is_empty( self, response, mock_get_streams_model_failure, mock_get_streams_all_time_model_success_no_recent_streams, mock_get_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_label, request_context_for_label, all_time_streams_with_empty_recent_streams_payload, mock_store_availability, ): """Test response when get_streams_model returns empty.""" response = streams.get_streams_bulk( request_context_for_label, self.isrcs, ["theorchard"], [], [] ) assert ( response.message["isrc"]["aggregate"] == all_time_streams_with_empty_recent_streams_payload["aggregate"] ) assert ( response.message["isrc"] == all_time_streams_with_empty_recent_streams_payload ) assert response.status == 200 def test_when_all_time_equals_prev_and_current_streams( self, mock_get_streams_model_success, mock_get_streams_all_time_model_success_last_two_weeks, mock_get_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_label, request_context_for_label, all_time_streams_equals_prev_and_current_week_payload, mock_store_availability, ): """Test response when get_streams_model returns empty.""" response = streams.get_streams_bulk( request_context_for_label, self.isrcs, ["theorchard"] ) first_isrc = response.message["isrc"] assert ( first_isrc["stores"][0] == all_time_streams_equals_prev_and_current_week_payload["stores"][0] ) assert ( first_isrc["stores"][1] == all_time_streams_equals_prev_and_current_week_payload["stores"][1] ) assert ( first_isrc["aggregate"] == all_time_streams_equals_prev_and_current_week_payload["aggregate"] ) assert response.status == 200 # # Same result always occurs when all_time model fails def test_when_all_time_streams_is_empty( self, mock_get_streams_model_success, mock_get_streams_all_time_model_failure, mock_add_outage_error_to_stores, mock_permissions_for_label, request_context_for_label, empty_all_time_streams_payload, mock_store_availability, ): """Test failure response when get_streams_all_time fails.""" response = streams.get_streams_bulk( request_context_for_label, self.isrcs, ["theorchard"] ) assert response.message["isrc"] == empty_all_time_streams_payload assert response.status == 200 class TestGetStreamsWithLabelSevenDaysBack: """Test get_streams with label.""" isrc = "isrc" start_date = datetime.date(2018, 6, 30) end_date = datetime.date(2018, 7, 6) @pytest.fixture def response( self, mock_get_streams_model_success, mock_get_streams_all_time_model_success, mock_get_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_streams.""" with app.test_request_context(): return streams.get_streams_bulk( request_context_for_label, [self.isrc], ["theorchard"], [], [], self.start_date, self.end_date, ) def test_succeeds(self, response, expected_payload_seven_days): """Test successful response.""" assert response.status == 200 response_message = response.message["isrc"] response_sources = response_message["sources"] expected_sources = expected_payload_seven_days["sources"] del response_message["sources"] del expected_payload_seven_days["sources"] assert response.message["isrc"] == expected_payload_seven_days assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_streams_model_is_called( self, response, mock_get_streams_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_streams model is called.""" mock_get_streams_model_success.assert_called_once_with( permissions_for_label, [self.isrc], ["theorchard"], [], [], datetime.date(2018, 6, 30), datetime.date(2018, 7, 6), ) def test_get_streams_all_time_model_is_called( self, response, mock_get_streams_all_time_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_streams_all_time model is called.""" mock_get_streams_all_time_model_success.assert_called_once_with( permissions_for_label, [self.isrc], ["theorchard"], [], [] ) def test_when_only_recent_streams_is_empty( self, mock_get_streams_model_failure, mock_get_streams_all_time_model_success_no_recent_streams, mock_get_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_label, request_context_for_label, all_time_streams_with_empty_recent_streams_payload, mock_store_availability, ): """Test response when get_streams_model returns empty.""" response = streams.get_streams_bulk( request_context_for_label, [self.isrc], ["theorchard"] ) assert ( response.message["isrc"] == all_time_streams_with_empty_recent_streams_payload ) assert response.status == 200 def test_when_all_time_equals_prev_and_current_streams( self, mock_get_streams_model_success, mock_get_streams_all_time_model_success_last_two_weeks, mock_get_max_available_date_success, mock_add_outage_error_to_stores, mock_permissions_for_label, request_context_for_label, all_time_streams_equals_prev_and_current_week_payload, mock_store_availability, ): """Test response when get_streams_model returns empty.""" response = streams.get_streams_bulk( request_context_for_label, [self.isrc], ["theorchard"], [] ) assert ( response.message["isrc"] == all_time_streams_equals_prev_and_current_week_payload ) assert response.status == 200 # Same result always occurs when all_time model fails def test_when_all_time_streams_is_empty( self, mock_get_streams_model_success, mock_get_streams_all_time_model_failure, mock_add_outage_error_to_stores, mock_permissions_for_label, request_context_for_label, empty_all_time_streams_payload, mock_store_availability, ): """Test failure response when get_streams_all_time fails.""" response = streams.get_streams_bulk( request_context_for_label, [self.isrc], ["theorchard"], [] ) assert response.message["isrc"] == empty_all_time_streams_payload assert response.status == 200 class TestGetStreamsWithSubaccount: """Test get_streams with subaccount.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_streams_model_success, mock_get_max_available_date_success, mock_get_streams_all_time_model_success, mock_add_outage_error_to_stores, mock_permissions_for_subaccount, request_context_for_subaccount, mock_store_availability, ): """Run get_streams.""" with app.test_request_context(): return streams.get_streams_bulk( request_context_for_subaccount, [self.isrc], ["theorchard"], [], [] ) def test_succeeds(self, response, expected_payload): """Test successful response.""" assert response.status == 200 assert response.message["isrc"] == expected_payload def test_get_streams_model_is_called( self, response, mock_get_streams_model_success, permissions_for_subaccount ): """Test get_streams model is called.""" mock_get_streams_model_success.assert_called_once_with( permissions_for_subaccount, [self.isrc], ["theorchard"], [], [], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) def test_get_streams_all_time_model_is_called( self, response, mock_get_streams_all_time_model_success, permissions_for_subaccount, ): """Test get_streams_all_time model is called.""" mock_get_streams_all_time_model_success.assert_called_once_with( permissions_for_subaccount, [self.isrc], ["theorchard"], [], [] ) def test_when_all_time_streams_is_empty( self, mock_get_streams_model_success, mock_get_streams_all_time_model_failure, mock_add_outage_error_to_stores, empty_all_time_streams_payload, request_context_for_subaccount, mock_store_availability, ): """Test failure response when get_streams_model fails.""" response = streams.get_streams_bulk( request_context_for_subaccount, [self.isrc], ["theorchard"], [] ) assert response.status == 200 expected_payload = empty_all_time_streams_payload response_message = response.message["isrc"] response_sources = response_message["sources"] expected_sources = expected_payload["sources"] assert response_message == expected_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) class TestGetStreamsWithSuperNewRelease: """Test get_streams with super new release.""" isrc = "isrc" @pytest.fixture def response( self, mock_get_streams_model_success, mock_get_streams_all_time_model_success, mock_get_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_store_availability, ): """Run get_streams.""" return streams.get_streams_bulk( request_context_for_label, [self.isrc], ["theorchard"] ) def test_succeeds(self, response, expected_payload): """Test successful response.""" payload = {**expected_payload} assert response.status == 200 assert response.message["isrc"] == payload class TestGetStreamsFilteredByCountries: """Test get_streams filtered by countries.""" isrc = "isrc" countries = ["US", "NO", "SE"] store_ids = [1, 286] @pytest.fixture def response( self, mock_get_streams_model_success, mock_get_streams_all_time_model_success, mock_get_max_available_date_success, mock_add_outage_error_to_stores, request_context_for_label, mock_permissions_for_label, mock_store_availability, ): """Run get_streams.""" return streams.get_streams_bulk( request_context_for_label, [self.isrc], ["theorchard"], self.countries, self.store_ids, ) def test_succeeds(self, response, expected_payload): """Test successful response.""" assert response.status == 200 response_message = response.message["isrc"] response_sources = response_message["sources"] expected_sources = expected_payload["sources"] del response_message["sources"] del expected_payload["sources"] assert response_message == expected_payload assert sorted(response_sources, key=lambda x: x["id"]) == sorted( expected_sources, key=lambda x: x["id"] ) def test_get_streams_model_is_called( self, response, mock_get_streams_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_streams model is called.""" mock_get_streams_model_success.assert_called_once_with( permissions_for_label, [self.isrc], ["theorchard"], self.countries, [1, 286], datetime.date(2018, 7, 6) - datetime.timedelta(days=28 - 1), datetime.date(2018, 7, 6), ) def test_get_streams_all_time_model_is_called( self, response, mock_get_streams_all_time_model_success, mock_add_outage_error_to_stores, permissions_for_label, ): """Test get_streams_all_time model is called.""" mock_get_streams_all_time_model_success.assert_called_once_with( permissions_for_label, [self.isrc], ["theorchard"], self.countries, [1, 286] )