from unittest import mock import pytest from app.adapters.ows_dmp import AudienceExportStatus from app.config.settings import Settings from app.exceptions import HandlerError from app.handlers import ExportAudienceFileHandler, ExportAudienceFileRequest from tests.unit.factories import AudienceExportFactory TEST_PASSWORD = "Test123" @pytest.fixture(autouse=True) def remove_tmp(settings: Settings) -> None: for file in settings.tmp_dir.glob("*"): if file.name == ".gitignore": continue file.unlink() @pytest.fixture def handler( s3_client_mock: mock.MagicMock, ows_dmp_client_mock: mock.MagicMock, ows_notifications_client_mock: mock.MagicMock, settings: Settings, ) -> ExportAudienceFileHandler: return ExportAudienceFileHandler( s3_client=s3_client_mock, ows_dmp_client=ows_dmp_client_mock, ows_notifications_client=ows_notifications_client_mock, tmp_dir=settings.tmp_dir, generate_password_func=lambda: TEST_PASSWORD, ) def test_export_audience( handler: ExportAudienceFileHandler, ows_dmp_client_mock: mock.MagicMock, ows_notifications_client_mock: mock.MagicMock, ) -> None: export = AudienceExportFactory.build() ows_dmp_client_mock.update_audience_export.return_value = export handler.handle( ExportAudienceFileRequest( bucket="test", key=f"raw/{export.id}/audience.csv", ) ) ows_dmp_client_mock.update_audience_export.assert_has_calls( calls=[ mock.call( export_id=export.id, status=AudienceExportStatus.PROCESSING, zip_key=None, ), mock.call( export_id=export.id, status=AudienceExportStatus.COMPLETED, zip_key=f"zip/{export.id}/audience.csv.zip", ), ], ) ows_notifications_client_mock.notify_audience_file_exported.assert_called_once_with( identity_id=export.created_by, audience_name=export.audience_name, filename="audience.csv.zip", password=TEST_PASSWORD, ) def test_export_audience_update_status_fail( handler: ExportAudienceFileHandler, ows_dmp_client_mock: mock.MagicMock ) -> None: export = AudienceExportFactory.build() ows_dmp_client_mock.update_audience_export.side_effect = ValueError("error") with pytest.raises(HandlerError) as exc_info: handler.handle( ExportAudienceFileRequest( bucket="test", key=f"raw/{export.id}/audience.csv", ) ) assert exc_info.value.code == "UPDATE_EXPORT_ERROR" assert exc_info.value.message == ( f"Failed to change export `{export.id}` status to `PROCESSING`." ) def test_export_audience_download_fail( handler: ExportAudienceFileHandler, s3_client_mock: mock.MagicMock, ows_dmp_client_mock: mock.MagicMock, ) -> None: export = AudienceExportFactory.build() ows_dmp_client_mock.update_audience_export.return_value = export s3_client_mock.download_fileobj.side_effect = ValueError("error") with pytest.raises(HandlerError) as exc_info: handler.handle( ExportAudienceFileRequest( bucket="test", key=f"raw/{export.id}/audience.csv", ) ) assert exc_info.value.code == "UPLOAD_ERROR" assert exc_info.value.message == ( f"Failed to upload secured zip file `raw/{export.id}/audience.csv`." ) def test_export_audience_notification_send_fail( handler: ExportAudienceFileHandler, ows_dmp_client_mock: mock.MagicMock, ows_notifications_client_mock: mock.MagicMock, ) -> None: export = AudienceExportFactory.build() ows_dmp_client_mock.update_audience_export.return_value = export ows_notifications_client_mock.notify_audience_file_exported.side_effect = ( ValueError("error") ) with pytest.raises(HandlerError) as exc_info: handler.handle( ExportAudienceFileRequest( bucket="test", key=f"raw/{export.id}/audience.csv", ) ) assert exc_info.value.code == "NOTIFICATION_SEND_ERROR" assert exc_info.value.message == ( "Failed to send exported file notification: error." )