from unittest import mock import pytest from campaigns.auth.dtos import User from campaigns.connectors.db import Database from campaigns.connectors.facebook.enums import AdSetFacebookPosition from campaigns.connectors.facebook.models import AdPreviewData from campaigns.meta.dtos import AdFormat from campaigns.meta.enums import ( AdFormatGroup, AssetPositionGroup, CampaignCallToAction, CampaignContentType, CampaignPlatform, ) from campaigns.meta.exceptions import ( CampaignAdFormatDoesNotExist, CampaignAdImageDoesNotExist, CampaignAdPreviewIsUnavailable, CampaignAdVideoDoesNotExist, ) from campaigns.meta.handlers import ( GetCampaignAdPreviewHandler, GetCampaignAdPreviewRequest, ) from campaigns.meta.handlers.get_campaign_ad_preview import GetCampaignAdPreviewResponse from campaigns.meta.models import Campaign, CampaignImage from campaigns.meta.repositories import AdFormatRepository from campaigns.meta.services import CampaignPostService, CampaignService from tests.unit.faker import FakerTyped from tests.unit.types import CreateModel @pytest.fixture def ad_format() -> AdFormat: return AdFormat( id="DESKTOP_FEED_STANDARD", name="Facebook Feed", group=AdFormatGroup.FEED, position_group=AssetPositionGroup.RATIO_1_1, platform=CampaignPlatform.FACEBOOK, position=AdSetFacebookPosition.FEED, height=100, width=200, ) @pytest.fixture def ad_format_repository(ad_format: AdFormat) -> AdFormatRepository: ad_format_repository = AdFormatRepository() ad_format_repository.formats = [ad_format] return ad_format_repository @pytest.fixture def handler( db: Database, facebook_client_mock: mock.MagicMock, ad_format_repository: AdFormatRepository, campaign_service: CampaignService, campaign_post_service: CampaignPostService, ) -> GetCampaignAdPreviewHandler: return GetCampaignAdPreviewHandler( db=db, facebook_client=facebook_client_mock, ad_format_repository=ad_format_repository, campaign_service=campaign_service, campaign_post_service=campaign_post_service, ) async def test_get_campaign_ad_preview_wrong_ad_format_id( handler: GetCampaignAdPreviewHandler, create_model: CreateModel, fake: FakerTyped, user: User, ) -> None: campaign = await create_model(Campaign) request = GetCampaignAdPreviewRequest( user=user, campaign_id=campaign.id, ad_format_id=fake.pystr(), content_type=CampaignContentType.IMAGE, post_external_id=None, primary_text=fake.pystr(), headline=fake.pystr(), description=fake.pystr(), website_url=fake.uri(), call_to_action=CampaignCallToAction.SHOP_NOW, ) with pytest.raises(CampaignAdFormatDoesNotExist): await handler.handle(request=request) async def test_get_campaign_ad_preview_no_image( handler: GetCampaignAdPreviewHandler, ad_format: AdFormat, create_model: CreateModel, fake: FakerTyped, user: User, ) -> None: campaign = await create_model(Campaign, images=[]) request = GetCampaignAdPreviewRequest( user=user, campaign_id=campaign.id, ad_format_id=ad_format.id, content_type=CampaignContentType.IMAGE, post_external_id=None, primary_text=fake.pystr(), headline=fake.pystr(), description=fake.pystr(), website_url=fake.uri(), call_to_action=CampaignCallToAction.SHOP_NOW, ) with pytest.raises(CampaignAdImageDoesNotExist): await handler.handle(request=request) async def test_get_campaign_ad_preview_no_video( handler: GetCampaignAdPreviewHandler, ad_format: AdFormat, create_model: CreateModel, fake: FakerTyped, user: User, ) -> None: campaign = await create_model(Campaign, videos=[]) request = GetCampaignAdPreviewRequest( user=user, campaign_id=campaign.id, ad_format_id=ad_format.id, content_type=CampaignContentType.VIDEO, post_external_id=None, primary_text=fake.pystr(), headline=fake.pystr(), description=fake.pystr(), website_url=fake.uri(), call_to_action=CampaignCallToAction.SHOP_NOW, ) with pytest.raises(CampaignAdVideoDoesNotExist): await handler.handle(request=request) async def test_get_campaign_ad_preview( handler: GetCampaignAdPreviewHandler, ad_format: AdFormat, create_model: CreateModel, fake: FakerTyped, facebook_client_mock: mock.MagicMock, user: User, ) -> None: image = await create_model(CampaignImage, image_hash=fake.pystr()) campaign = await create_model(Campaign, images=[image]) request = GetCampaignAdPreviewRequest( user=user, campaign_id=campaign.id, ad_format_id=ad_format.id, content_type=CampaignContentType.IMAGE, post_external_id=None, primary_text=fake.pystr(), headline=fake.pystr(), description=fake.pystr(), website_url=fake.uri(), call_to_action=CampaignCallToAction.SHOP_NOW, ) src = fake.pystr() body = f'' ad_preview = AdPreviewData(body=body) facebook_client_mock.get_ad_preview.return_value = ad_preview result = await handler.handle(request=request) assert result == GetCampaignAdPreviewResponse( body=ad_preview.body, src=src, height=ad_format.height, width=ad_format.width, ) async def test_get_campaign_ad_preview_is_unavailable( handler: GetCampaignAdPreviewHandler, ad_format: AdFormat, create_model: CreateModel, fake: FakerTyped, facebook_client_mock: mock.MagicMock, user: User, ) -> None: image = await create_model(CampaignImage, image_hash=fake.pystr()) campaign = await create_model(Campaign, images=[image]) request = GetCampaignAdPreviewRequest( user=user, campaign_id=campaign.id, ad_format_id=ad_format.id, content_type=CampaignContentType.IMAGE, post_external_id=None, primary_text=fake.pystr(), headline=fake.pystr(), description=fake.pystr(), website_url=fake.uri(), call_to_action=CampaignCallToAction.SHOP_NOW, ) body = '' ad_preview = AdPreviewData(body=body) facebook_client_mock.get_ad_preview.return_value = ad_preview with pytest.raises(CampaignAdPreviewIsUnavailable): await handler.handle(request=request)