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)