"""Unit tests for tasks of Apple Music Source of Stream Workflow.""" import datetime from unittest.mock import ANY from unittest.mock import MagicMock from unittest.mock import Mock from unittest.mock import call from unittest.mock import patch from garcon.contrib.dynamo_feed_status import \ feed_status_ingestion as feed_status import pytest from analytics_aggregation.flows.apple_music_sos import tasks from analytics_aggregation.flows.apple_music_sos import utils @pytest.fixture() def date_range(): """Date range structure.""" return {'start_date': '2017-01-01', 'end_date': '2017-01-02'} class _DateWithTodayMock(datetime.date): """Mock datetime.date.today to return constant date.""" @classmethod def today(cls): return cls(2017, 1, 1) @pytest.yield_fixture def mock_executor_context(): """Yield executor context.""" sf_executor_class_path = ( 'analytics_aggregation.flows.apple_music_sos.tasks.AppleExecutor') with patch(sf_executor_class_path) as sf_executor: mock_executor_context = sf_executor.return_value.__enter__.return_value yield mock_executor_context @patch('analytics_aggregation.flows.apple_music_sos.tasks.datetime') @patch('analytics_aggregation.util.common') def test_extract_date_all_processed(common, date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock activity_mock = MagicMock() get_am_status_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_apple_music_ingested', get_am_status_mock) get_overall_feed_status_mock = MagicMock( return_value=feed_status.STATUS_INGESTED) monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) tasks.extract_date(activity_mock, 'feed_name', None, None) assert common.exit_message.called_with( 'There is no data to aggregate for 2016-12-25_2017-01-01 range') @patch('analytics_aggregation.flows.apple_music_sos.tasks.datetime') def test_extract_date_not_processed(date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock activity_mock = MagicMock() get_am_status_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_apple_music_ingested', get_am_status_mock) get_overall_feed_status_mock = MagicMock(return_value='bullsquaw') monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) today = '2017-01-01' week_ago = '2016-12-25' result = tasks.extract_date(activity_mock, 'feed_name', None, None) assert not result['reload'] assert result['date_range']['start_date'] == week_ago assert result['date_range']['end_date'] == today result = tasks.extract_date( activity_mock, 'feed_name', '2017-03-30_2017-03-31', True) assert result['reload'] assert result['date_range']['start_date'] == '2017-03-30' assert result['date_range']['end_date'] == '2017-03-31' @patch('analytics_aggregation.flows.apple_music_sos.tasks.datetime') def test_find_range_to_process_all_processed(date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock get_am_status_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_apple_music_ingested', get_am_status_mock) get_overall_feed_status_mock = MagicMock( return_value=feed_status.STATUS_INGESTED) monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) assert tasks._find_range_to_process('feed_name') == { 'found_days': False, 'week_range': '2016-12-25_2017-01-01' } @patch('analytics_aggregation.flows.apple_music_sos.tasks.datetime') def test_find_range_to_process_not_processed(date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock get_am_status_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_apple_music_ingested', get_am_status_mock) get_overall_feed_status_mock = MagicMock(return_value='bullsquaw') monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) assert tasks._find_range_to_process('feed_name') == { 'found_days': True, 'week_range': '2016-12-25_2017-01-01', 'start_date': '2016-12-25', 'end_date': '2017-01-01' } @patch('analytics_aggregation.flows.apple_music_sos.tasks.utils') def test_check_apple_music_ingested(utils_mock, date_range): """Test check_apple_music_ingested task.""" get_apple_music_status_mock = MagicMock() utils_mock.is_apple_music_ingested = get_apple_music_status_mock result = tasks.check_apple_music_ingested(Mock(), date_range) assert result is None get_apple_music_status_mock.assert_has_calls([ call('2017-01-01'), call('2017-01-02')], any_order=True) @patch('analytics_aggregation.flows.apple_music_sos.tasks.utils') def test_check_apple_music_ingested_fail(utils_mock, date_range): """Test check_apple_music_ingested task.""" get_apple_music_status_mock = MagicMock(return_value=False) utils_mock.is_apple_music_ingested = get_apple_music_status_mock result = tasks.check_apple_music_ingested(Mock(), date_range) assert result['stop'] def test_cleanup_staging_sos(date_range, mock_executor_context): """Test cleanup_staging_sos.""" tasks.cleanup_staging_sos(Mock(), date_range) mock_executor_context.cleanup_staging_sos.assert_called_with( labelids_clause=ANY, params=ANY) def test_populate_staging_sos_with_apple_music_data( date_range, mock_executor_context): """Test populate_staging_sos.""" tasks.populate_staging_with_apple_music_data(Mock(), date_range) mock_executor_context.populate_staging_sos.assert_called_with( labelids_clause=ANY, params=ANY)