import pathlib from unittest import mock import pytest from freezegun import freeze_time from app.adapters.ows_dmp import AudienceSharePlatform, AudienceShareStatus from app.exceptions import HandlerError from app.handler import ShareAudienceHandler, ShareAudienceRequest from app.strategies import MetaAudienceShareStrategy from tests.unit.factories import AudienceShareFactory, MetaAudienceShareFactory def test_share_meta_audience_share_failed( handler: ShareAudienceHandler, ows_dmp_client_mock: mock.MagicMock, s3_client_mock: mock.MagicMock, audience_file: pathlib.Path, mock_download_fileobj_meta: None, ) -> None: audience_share = AudienceShareFactory.build( platform=AudienceSharePlatform.META, ) ows_dmp_client_mock.update_audience_share.return_value = audience_share ows_dmp_client_mock.get_meta_audience_share.side_effect = Exception("error") with pytest.raises(HandlerError) as exc_info: handler.handle( ShareAudienceRequest( bucket="test", key=f"shares/{audience_share.id}/{audience_share.id}_audience.csv", ) ) assert exc_info.value.code == "GET_META_AUDIENCE_SHARE_ERROR" ows_dmp_client_mock.update_audience_share.assert_has_calls( [ mock.call( audience_share.id, status=AudienceShareStatus.FAILED, processed_fans=None, ) ] ) def test_share_meta_audience_decrypt_failed( handler: ShareAudienceHandler, ows_dmp_client_mock: mock.MagicMock, s3_client_mock: mock.MagicMock, kms_client_mock: mock.MagicMock, mock_download_fileobj_meta: None, ) -> None: audience_share = AudienceShareFactory.build(platform=AudienceSharePlatform.META) share_data = MetaAudienceShareFactory.build() ows_dmp_client_mock.update_audience_share.return_value = audience_share ows_dmp_client_mock.get_meta_audience_share.return_value = share_data kms_client_mock.decrypt.side_effect = Exception("error") with pytest.raises(HandlerError) as exc_info: handler.handle( ShareAudienceRequest( bucket="test", key=f"shares/{audience_share.id}/{audience_share.id}_audience.csv", ) ) assert exc_info.value.code == "DECRYPT_USER_ACCESS_TOKEN_ERROR" ows_dmp_client_mock.update_audience_share.assert_has_calls( [ mock.call( audience_share.id, status=AudienceShareStatus.FAILED, processed_fans=None, ) ] ) @freeze_time("2023-11-03T12:09:52.902512") def test_share_meta_audience_upload_users_failed( handler: ShareAudienceHandler, ows_dmp_client_mock: mock.MagicMock, s3_client_mock: mock.MagicMock, kms_client_mock: mock.MagicMock, facebook_client_mock: mock.MagicMock, mock_download_fileobj_meta: None, ) -> None: session_id = 16990133929 audience_share = AudienceShareFactory.build( platform=AudienceSharePlatform.META, ) share_data = MetaAudienceShareFactory.build() ows_dmp_client_mock.update_audience_share.return_value = audience_share ows_dmp_client_mock.get_meta_audience_share.return_value = share_data kms_client_mock.decrypt.return_value = share_data.user_access_token facebook_client_mock.upload_users.side_effect = Exception("error") with pytest.raises(HandlerError) as exc_info: handler.handle( ShareAudienceRequest( bucket="test", key=f"shares/{audience_share.id}/{audience_share.id}_audience.csv", ) ) assert exc_info.value.code == "PROCESS_AUDIENCE_ERROR" ows_dmp_client_mock.update_audience_share.assert_has_calls( [ mock.call( audience_share.id, status=AudienceShareStatus.PROCESSING, processed_fans=None, ), mock.call( audience_share.id, status=AudienceShareStatus.FAILED, processed_fans=None, ), ] ) facebook_client_mock.upload_users.assert_has_calls( [ mock.call( share_data.user_access_token, audience_external_id=share_data.audience_external_id, session={ "session_id": session_id, "batch_seq": 1, "last_batch_flag": True, "estimated_num_total": share_data.fans_count, }, payload={ "schema": ["EMAIL", "PHONE"], "data": [ ["hash1", ""], ["hash2", "hash2"], ["hash3", "hash3"], ["hash4", "hash4"], ["hash5", "hash5"], ["hash6", "hash6"], ["hash7", "hash7"], ["hash8", "hash8"], ["hash9", "hash9"], ["hash10", "hash10"], ], }, ) ] ) @freeze_time("2023-11-03T12:09:52.902512") def test_share_meta_audience( handler: ShareAudienceHandler, ows_dmp_client_mock: mock.MagicMock, s3_client_mock: mock.MagicMock, kms_client_mock: mock.MagicMock, facebook_client_mock: mock.MagicMock, mock_download_fileobj_meta: None, meta_strategy: MetaAudienceShareStrategy, ) -> None: # Set chunk size to 3 to test multiple batches meta_strategy.upload_chunksize = 3 session_id = 16990133929 audience_share = AudienceShareFactory.build( platform=AudienceSharePlatform.META, ) meta_audience_share = MetaAudienceShareFactory.build(fansCount=10) ows_dmp_client_mock.update_audience_share.return_value = audience_share ows_dmp_client_mock.get_meta_audience_share.return_value = meta_audience_share kms_client_mock.decrypt.return_value = meta_audience_share.user_access_token handler.handle( ShareAudienceRequest( bucket="test", key=f"shares/{audience_share.id}/{audience_share.id}_audience.csv", ) ) ows_dmp_client_mock.update_audience_share.assert_has_calls( [ mock.call( audience_share.id, status=AudienceShareStatus.PROCESSING, processed_fans=None, ), mock.call( audience_share.id, status=AudienceShareStatus.COMPLETED, processed_fans=10, ), ], ) facebook_client_mock.upload_users.assert_has_calls( [ mock.call( meta_audience_share.user_access_token, audience_external_id=meta_audience_share.audience_external_id, session={ "session_id": session_id, "batch_seq": 1, "last_batch_flag": False, "estimated_num_total": meta_audience_share.fans_count, }, payload={ "schema": ["EMAIL", "PHONE"], "data": [ ["hash1", ""], ["hash2", "hash2"], ["hash3", "hash3"], ], }, ), mock.call( meta_audience_share.user_access_token, audience_external_id=meta_audience_share.audience_external_id, session={ "session_id": session_id, "batch_seq": 2, "last_batch_flag": False, "estimated_num_total": meta_audience_share.fans_count, }, payload={ "schema": ["EMAIL", "PHONE"], "data": [ ["hash4", "hash4"], ["hash5", "hash5"], ["hash6", "hash6"], ], }, ), mock.call( meta_audience_share.user_access_token, audience_external_id=meta_audience_share.audience_external_id, session={ "session_id": session_id, "batch_seq": 3, "last_batch_flag": False, "estimated_num_total": meta_audience_share.fans_count, }, payload={ "schema": ["EMAIL", "PHONE"], "data": [ ["hash7", "hash7"], ["hash8", "hash8"], ["hash9", "hash9"], ], }, ), mock.call( meta_audience_share.user_access_token, audience_external_id=meta_audience_share.audience_external_id, session={ "session_id": session_id, "batch_seq": 4, "last_batch_flag": True, "estimated_num_total": meta_audience_share.fans_count, }, payload={ "schema": ["EMAIL", "PHONE"], "data": [ ["hash10", "hash10"], ], }, ), ], any_order=True, )