from unittest import mock import pytest from campaigns.auth.dtos import User from campaigns.connectors.db import Database from campaigns.connectors.facebook.arguments import GetAudienceSummaryArgs from campaigns.connectors.facebook.base import FacebookClient from campaigns.connectors.facebook.enums import ( AdSetFacebookPosition, AdSetInstagramPosition, ) from campaigns.connectors.facebook.models import AudienceSummary from campaigns.meta.dtos import AdFormat from campaigns.meta.enums import ( AdFormatGroup, AssetPositionGroup, CampaignContentType, CampaignPlatform, ) from campaigns.meta.handlers import ( GetCampaignAudienceSummaryHandler, GetCampaignAudienceSummaryRequest, ) from campaigns.meta.models import Campaign, CampaignImage from campaigns.meta.repositories import AdFormatRepository from campaigns.meta.services import AdFormatService, CampaignService from tests.unit.faker import FakerTyped from tests.unit.types import CreateModel @pytest.fixture def facebook_client_mock() -> mock.MagicMock: return mock.MagicMock(spec=FacebookClient) @pytest.fixture def facebook_ad_format() -> AdFormat: return AdFormat( id="DESKTOP_FEED_STANDARD", name="Facebook Feed", position=AdSetFacebookPosition.FEED, group=AdFormatGroup.FEED, position_group=AssetPositionGroup.RATIO_1_1, platform=CampaignPlatform.FACEBOOK, height=100, width=100, ) @pytest.fixture def instagram_ad_format() -> AdFormat: return AdFormat( id="INSTAGRAM_STANDARD", name="Instagram Feed", position=AdSetInstagramPosition.STREAM, group=AdFormatGroup.FEED, position_group=AssetPositionGroup.RATIO_1_1, platform=CampaignPlatform.INSTAGRAM, height=100, width=100, ) @pytest.fixture def ad_format_repository( facebook_ad_format: AdFormat, instagram_ad_format: AdFormat ) -> AdFormatRepository: ad_format_repository = AdFormatRepository() ad_format_repository.formats = [facebook_ad_format, instagram_ad_format] return ad_format_repository @pytest.fixture def ad_format_service(ad_format_repository: AdFormatRepository) -> AdFormatService: return AdFormatService(ad_format_repository=ad_format_repository) @pytest.fixture def handler( db: Database, facebook_client_mock: mock.MagicMock, campaign_service: CampaignService, ad_format_service: AdFormatService, ) -> GetCampaignAudienceSummaryHandler: return GetCampaignAudienceSummaryHandler( db=db, facebook_client=facebook_client_mock, campaign_service=campaign_service, ad_format_service=ad_format_service, ) async def test_get_campaign_audience_summary( handler: GetCampaignAudienceSummaryHandler, create_model: CreateModel, fake: FakerTyped, facebook_client_mock: mock.MagicMock, user: User, ) -> None: campaign = await create_model(Campaign, platforms=None) request = GetCampaignAudienceSummaryRequest( user=user, campaign_id=campaign.id, genders=[fake.choice([1, 2])] ) audience_summary = AudienceSummary( users_lower_bound=fake.integer(6), users_upper_bound=fake.integer(7), estimate_ready=True, ) facebook_client_mock.get_audience_summary.return_value = audience_summary result = await handler.handle(request) assert result == audience_summary async def test_get_campaign_audience_summary_platform_and_positions( handler: GetCampaignAudienceSummaryHandler, create_model: CreateModel, fake: FakerTyped, facebook_client_mock: mock.MagicMock, facebook_ad_format: AdFormat, instagram_ad_format: AdFormat, user: User, ) -> None: platforms = [CampaignPlatform.FACEBOOK, CampaignPlatform.INSTAGRAM] image = await create_model( CampaignImage, is_valid=True, position_group=AssetPositionGroup.RATIO_1_1 ) campaign = await create_model( Campaign, platforms=platforms, content_type=CampaignContentType.IMAGE, images=[image], ) request = GetCampaignAudienceSummaryRequest( user=user, campaign_id=campaign.id, genders=[fake.choice([1, 2])], ) audience_summary = AudienceSummary( users_lower_bound=fake.integer(6), users_upper_bound=fake.integer(7), estimate_ready=True, ) audience_summary_mock = facebook_client_mock.get_audience_summary audience_summary_mock.return_value = audience_summary await handler.handle(request) audience_summary_mock.assert_called_once_with( GetAudienceSummaryArgs( genders=request.genders, publisher_platforms=[ platform.to_ad_campaign_platform() for platform in platforms ], facebook_positions=[facebook_ad_format.position], instagram_positions=[instagram_ad_format.position], ) )