from typing import get_args import pytest from dmp.ad_reporting.dtos import AdReportingAdCriteria from dmp.ad_reporting.enums import ( AdReportingCreativeType, AdReportingObjective, AdReportingPlatform, ) from dmp.ad_reporting.models import ( AdReportingAdDbt, AdReportingCampaignDbt, AdReportingCreativeThumbnail, ) from dmp.ad_reporting.repositories import AdReportingAdRepository from dmp.ad_reporting.types import AdReportingAdOrderBy from dmp.config import Settings from tests.unit.faker import FakerTyped from tests.unit.types import CreateReportingModel class TestAdReportingAdRepository: @pytest.mark.db def test_find_by_criteria( self, repository: AdReportingAdRepository, fake: FakerTyped, ) -> None: repository.find_by_criteria( AdReportingAdCriteria( search="test", ad_set_id=fake.uuid4_string(), global_participant_id=fake.uuid4_string(), platform=AdReportingPlatform.META, objective=AdReportingObjective.OUTCOME_TRAFFIC, account_ids={fake.uuid4_string(), fake.uuid4_string()}, campaign_ids={fake.uuid4_string()}, ), limit=10, offset=5, ) @pytest.mark.db @pytest.mark.parametrize("order_by", get_args(AdReportingAdOrderBy)) def test_find_by_criteria_supported_order_by_columns( self, repository: AdReportingAdRepository, order_by: AdReportingAdOrderBy, ) -> None: repository.find_by_criteria( AdReportingAdCriteria(), order_by=[order_by], ) @pytest.mark.db @pytest.mark.parametrize("order_by", get_args(AdReportingAdOrderBy)) def test_find_by_criteria_grouped_supported_order_by_columns( self, repository: AdReportingAdRepository, order_by: AdReportingAdOrderBy, ) -> None: repository.find_by_criteria_grouped( AdReportingAdCriteria(), order_by=[order_by], ) @pytest.mark.db @pytest.mark.parametrize("order_by", get_args(AdReportingAdOrderBy)) def test_find_by_criteria_grouped_country_supported_order_by_columns( self, repository: AdReportingAdRepository, order_by: AdReportingAdOrderBy, ) -> None: repository.find_by_criteria_grouped( AdReportingAdCriteria(countries=["US"]), order_by=[order_by], ) @pytest.mark.db def test_find_by_criteria_fields( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, ) -> None: ad = create_reporting_model( AdReportingAdDbt, platform=AdReportingPlatform.META, ) ads = repository.find_by_criteria( AdReportingAdCriteria(), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.id == ad.id assert result.name == ad.name assert result.campaign_id == ad.campaign_id assert result.campaign_name == ad.campaign_name assert result.ad_set_id == ad.ad_set_id assert result.ad_set_name == ad.ad_set_name assert result.account_id == ad.account_id assert result.accounts == set() assert result.global_participant_ids == {ad.campaign_global_participant_id} assert result.platform == ad.platform assert result.objective == ad.campaign_objective assert result.start_at == ad.ad_set_start_at assert result.end_at == ad.ad_set_end_at assert result.clicks == ad.clicks assert result.impressions == ad.impressions assert result.reach == ad.reach assert result.estimated_ad_recallers == ad.estimated_ad_recallers assert result.views_p25 == ad.views_p25 assert result.views == ad.views assert result.purchases == ad.purchases assert result.follows == ad.follows assert result.spend == ad.spend assert result.currency == ad.currency assert result.spend_usd == ad.spend_usd assert result.actions == ad.actions assert result.action_type == ad.action_type assert result.rate == ad.rate assert result.rate_type == ad.rate_type assert result.cost_per_action == ad.cost_per_action assert result.cost_per_action_usd == ad.cost_per_action_usd assert result.frequency == ad.frequency @pytest.mark.db def test_find_by_criteria_creative_image_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, settings: Settings, ) -> None: ad = create_reporting_model(AdReportingAdDbt) thumbnail = create_reporting_model( AdReportingCreativeThumbnail, creative_id=ad.creative_id, ) ads = repository.find_by_criteria( AdReportingAdCriteria( ad_ids={ ad.id, } ), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url == ad.creative_image_url assert result.creative_type == AdReportingCreativeType.IMAGE assert result.creative_thumbnail == ( f"https://{settings.assets_cdn_domain}/{thumbnail.img_s3_obj_key}" ) @pytest.mark.db def test_find_by_criteria_creative_video_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, fake: FakerTyped, settings: Settings, ) -> None: ad = create_reporting_model( AdReportingAdDbt, creative_image_url=None, platform=fake.choice( [AdReportingPlatform.META, AdReportingPlatform.TIKTOK] ), ) thumbnail = create_reporting_model( AdReportingCreativeThumbnail, creative_id=ad.creative_id, ) ads = repository.find_by_criteria( AdReportingAdCriteria(ad_ids={ad.id}), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url == ad.creative_video_url assert result.creative_type == AdReportingCreativeType.VIDEO assert result.creative_thumbnail == ( f"https://{settings.assets_cdn_domain}/{thumbnail.img_s3_obj_key}" ) @pytest.mark.db def test_find_by_criteria_creative_youtube_video_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, fake: FakerTyped, settings: Settings, ) -> None: ad = create_reporting_model( AdReportingAdDbt, creative_image_url=None, creative_video_url=f"https://www.YouTube.com/watch{fake.pystr()}", platform=AdReportingPlatform.GOOGLE, ) thumbnail = create_reporting_model( AdReportingCreativeThumbnail, creative_id=ad.creative_id, ) ads = repository.find_by_criteria( AdReportingAdCriteria(ad_ids={ad.id}), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url == ad.creative_video_url assert result.creative_type == AdReportingCreativeType.YOUTUBE_VIDEO assert result.creative_thumbnail == ( f"https://{settings.assets_cdn_domain}/{thumbnail.img_s3_obj_key}" ) @pytest.mark.db def test_find_by_criteria_tiktok_platform_creative_post_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, settings: Settings, ) -> None: ad = create_reporting_model( AdReportingAdDbt, creative_image_url=None, creative_video_url=None, platform=AdReportingPlatform.TIKTOK, ) thumbnail = create_reporting_model( AdReportingCreativeThumbnail, creative_id=ad.creative_id, ) ads = repository.find_by_criteria( AdReportingAdCriteria(ad_ids={ad.id}), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url == ad.creative_post_url assert result.creative_type == AdReportingCreativeType.TIKTOK_POST assert result.creative_thumbnail == ( f"https://{settings.assets_cdn_domain}/{thumbnail.img_s3_obj_key}" ) @pytest.mark.db def test_find_by_criteria_meta_platform_creative_post_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, settings: Settings, ) -> None: ad = create_reporting_model( AdReportingAdDbt, creative_image_url=None, creative_video_url=None, platform=AdReportingPlatform.META, ) thumbnail = create_reporting_model( AdReportingCreativeThumbnail, creative_id=ad.creative_id, ) ads = repository.find_by_criteria( AdReportingAdCriteria(ad_ids={ad.id}), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url == ad.creative_post_url assert result.creative_type == AdReportingCreativeType.INSTAGRAM_POST assert result.creative_thumbnail == ( f"https://{settings.assets_cdn_domain}/{thumbnail.img_s3_obj_key}" ) @pytest.mark.db def test_find_by_criteria_creative_thumbnail_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, settings: Settings, ) -> None: ad = create_reporting_model( AdReportingAdDbt, creative_image_url=None, creative_video_url=None, creative_post_url=None, ) thumbnail = create_reporting_model( AdReportingCreativeThumbnail, creative_id=ad.creative_id, ) ads = repository.find_by_criteria( AdReportingAdCriteria(ad_ids={ad.id}), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url == ( f"https://{settings.assets_cdn_domain}/{thumbnail.img_s3_obj_key}" ) assert result.creative_type == AdReportingCreativeType.IMAGE_THUMBNAIL assert result.thumbnail_url == ( f"https://{settings.assets_cdn_domain}/{thumbnail.timg64x64_s3_obj_key}" ) assert result.creative_thumbnail == ( f"https://{settings.assets_cdn_domain}/{thumbnail.img_s3_obj_key}" ) @pytest.mark.db def test_find_by_criteria_empty_creative_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, ) -> None: ad = create_reporting_model( AdReportingAdDbt, creative_image_url=None, creative_video_url=None, creative_post_url=None, ) ads = repository.find_by_criteria( AdReportingAdCriteria(ad_ids={ad.id}), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url is None assert result.creative_type is None assert result.creative_thumbnail is None @pytest.mark.db def test_find_by_criteria_failed_thumbnail_download_result_creative_url_field( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, ) -> None: ad = create_reporting_model( AdReportingAdDbt, creative_image_url=None, creative_video_url=None, creative_post_url=None, ) create_reporting_model( AdReportingCreativeThumbnail, creative_id=ad.creative_id, img_s3_obj_key=None, timg64x64_s3_obj_key=None, ) ads = repository.find_by_criteria( AdReportingAdCriteria(ad_ids={ad.id}), limit=1, offset=0, ) assert len(ads) == 1 result = ads[0] assert result.creative_url is None assert result.creative_type is None assert result.thumbnail_url is None assert result.creative_thumbnail is None @pytest.mark.db def test_summary_filter_by_ad_set_id( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, fake: FakerTyped, ) -> None: ad = create_reporting_model( AdReportingAdDbt, platform=AdReportingPlatform.META, ad_set_id=fake.uuid4_string(), spend=150.0, spend_usd=100.0, ) create_reporting_model( AdReportingAdDbt, platform=AdReportingPlatform.META, ad_set_id=fake.uuid4_string(), spend=200.0, spend_usd=150.0, ) summary = repository.summary_by_criteria( AdReportingAdCriteria( ad_set_id=ad.ad_set_id, ) ) assert summary.spend_usd == 100.0 @pytest.mark.db def test_filter_ads_by_global_participant_id( self, repository: AdReportingAdRepository, create_reporting_model: CreateReportingModel, ) -> None: campaign_1 = create_reporting_model(AdReportingCampaignDbt) campaign_1.global_participant_ids = {"gp1", "gp2"} ad_1 = create_reporting_model(AdReportingAdDbt, campaign_id=campaign_1.id) campaign_2 = create_reporting_model(AdReportingCampaignDbt) campaign_2.global_participant_ids = {"gp3", "gp4"} ad_2 = create_reporting_model(AdReportingAdDbt, campaign_id=campaign_2.id) ads = repository.find_by_criteria( AdReportingAdCriteria(global_participant_id="gp1") ) assert len(ads) == 1 assert ads[0].id == ad_1.id ads = repository.find_by_criteria( AdReportingAdCriteria(global_participant_id="gp2") ) assert len(ads) == 1 assert ads[0].id == ad_1.id ads = repository.find_by_criteria( AdReportingAdCriteria(global_participant_id="gp3") ) assert len(ads) == 1 assert ads[0].id == ad_2.id ads = repository.find_by_criteria( AdReportingAdCriteria(global_participant_id="gp4") ) assert len(ads) == 1 assert ads[0].id == ad_2.id