"""Unit tests for physical_reporting tasks workflow.""" from unittest.mock import MagicMock, patch import pytest from feed_ingestion.flows.physical_reporting import config from feed_ingestion.flows.physical_reporting import tasks _date = '2026-02-24' _report = 'dpworld' @pytest.fixture def expected_bootstrap_response_dpworld(): """Response for bootstrap task with dpworld report.""" return { 'feed_name': 'physical_reporting_dpworld', 'date': '2026-02-24', 'report_name': 'dpworld', 'secrets_path': 'swf-physical-reporting', 's3_download_path': f's3://{config.drop_bucket}/ftp/dpworld/', 's3_archive_path': ( f's3://{config.data_bucket}/physical_reporting/dpworld/' f'archives/2026-02-24/' ), 'drop_file_name': 'dpwstock_orchard_20260224.csv', 'staging_raw_table_name': 'staging_raw_physical_daily_dpw', } def test_bootstrap_dpworld(expected_bootstrap_response_dpworld): """Test bootstrap task with dpworld report.""" result = tasks.bootstrap( MagicMock(), _date, report='dpworld') assert result == expected_bootstrap_response_dpworld def test_bootstrap_invalid_report(): """Test bootstrap task raises assertion error with invalid report.""" with pytest.raises(AssertionError): tasks.bootstrap(MagicMock(), _date, report='invalid_report') @pytest.fixture def mock_task_status(): """Yield task status.""" task_status_path = ( 'feed_ingestion.flows.physical_reporting.tasks.task_status') with patch(task_status_path) as task_status: task_status.is_completed_task.return_value = False task_status.mark_completed_task = MagicMock() yield task_status @pytest.fixture def mock_s3_tasks(): """Mock s3_tasks module.""" path = 'feed_ingestion.flows.physical_reporting.tasks.s3_tasks' with patch(path) as mock_s3: yield mock_s3 @pytest.fixture def mock_set_overall_status_enhanced(): """Mock set_overall_status_enhanced function.""" path = ( 'feed_ingestion.flows.physical_reporting.tasks.' 'set_overall_status_enhanced' ) with patch(path) as mock_status: yield mock_status def test_grab_drop_files_success( mock_task_status, mock_s3_tasks, mock_set_overall_status_enhanced): """Test grab_drop_files when file is successfully copied.""" # Mock successful copy_files result mock_s3_tasks.copy_files.return_value = { 'files_copied': ['dpwstock_orchard_20260224.csv'] } mock_activity = MagicMock() result = tasks.grab_drop_files( mock_activity, feed_name='physical_reporting_dpworld', date=_date, s3_archive_path=( f's3://{config.data_bucket}/physical_reporting/dpworld/' f'archives/2026-02-24/' ), s3_download_path=f's3://{config.drop_bucket}/ftp/dpworld/', drop_file_name='dpwstock_orchard_20260224.csv') # Verify is_completed_task was checked mock_task_status.is_completed_task.assert_called_once_with( 'physical_reporting_dpworld', _date, 'grab_drop_files' ) # Verify copy_files was called with correct parameters mock_s3_tasks.copy_files.assert_called_once() call_kwargs = mock_s3_tasks.copy_files.call_args[1] assert call_kwargs['s3_archive_path'] == ( f's3://{config.data_bucket}/physical_reporting/dpworld/' f'archives/2026-02-24/' ) assert ( call_kwargs['s3_download_path'] == f's3://{config.drop_bucket}/ftp/dpworld/' ) assert ( call_kwargs['source_files_dict']['files'][0]['file_name'] == 'dpwstock_orchard_20260224.csv' ) assert ( call_kwargs['source_files_dict']['files'][0]['found'] is False ) assert call_kwargs['need_all_files'] is True # Verify task was marked as completed mock_task_status.mark_completed_task.assert_called_once_with( 'physical_reporting_dpworld', _date, 'grab_drop_files' ) # Verify status was set to DOWNLOADED mock_set_overall_status_enhanced.assert_called_once_with( 'physical_reporting_dpworld', _date, 'DOWNLOADED', mock_activity ) # Verify result doesn't contain stop flag assert result.get('files_copied') == ['dpwstock_orchard_20260224.csv'] def test_grab_drop_files_file_not_found( mock_task_status, mock_s3_tasks, mock_set_overall_status_enhanced): """Test grab_drop_files when file is not available.""" # Mock task is not completed mock_task_status.is_completed_task.return_value = False # Mock copy_files returning stop flag mock_s3_tasks.copy_files.return_value = {'stop': True} mock_activity = MagicMock() result = tasks.grab_drop_files( mock_activity, feed_name='physical_reporting_dpworld', date=_date, s3_archive_path=( f's3://{config.data_bucket}/physical_reporting/dpworld/' f'archives/2026-02-24/' ), s3_download_path=f's3://{config.drop_bucket}/ftp/dpworld/', drop_file_name='dpwstock_orchard_20260224.csv') # Verify status was set to NOT_AVAILABLE mock_set_overall_status_enhanced.assert_called_once_with( 'physical_reporting_dpworld', _date, 'NOT_AVAILABLE', mock_activity ) # Verify task was NOT marked as completed mock_task_status.mark_completed_task.assert_not_called() # Verify result contains stop flag assert result == {'stop': True} def test_grab_drop_files_already_completed( mock_task_status, mock_s3_tasks, mock_set_overall_status_enhanced): """Test grab_drop_files when task is already completed.""" # Mock task is already completed mock_task_status.is_completed_task.return_value = True mock_activity = MagicMock() result = tasks.grab_drop_files( mock_activity, feed_name='physical_reporting_dpworld', date=_date, s3_archive_path=( f's3://{config.data_bucket}/physical_reporting/dpworld/' f'archives/2026-02-24/' ), s3_download_path=f's3://{config.drop_bucket}/ftp/dpworld/', drop_file_name='dpwstock_orchard_20260224.csv') # Verify is_completed_task was checked mock_task_status.is_completed_task.assert_called_once_with( 'physical_reporting_dpworld', _date, 'grab_drop_files' ) # Verify copy_files was NOT called (task already completed) mock_s3_tasks.copy_files.assert_not_called() # Verify task was NOT marked as completed again mock_task_status.mark_completed_task.assert_not_called() # Verify status was NOT set mock_set_overall_status_enhanced.assert_not_called() # Verify result contains source_files_dict with found=True assert result == { 'files': [ { 'file_name': 'dpwstock_orchard_20260224.csv', 'found': True, } ] }