import faker import pytest from fansifter_common.auth.account import Account from fansifter_common.exceptions import Error from fansifter_common.utils import timezone from email_campaigns.audiences.enums import AudienceTarget from email_campaigns.audiences.exceptions import ( ArchivedAudienceError, EmptyAudienceError, NotSupportedAudienceTargetError, ) from email_campaigns.audiences.models import Audience from email_campaigns.campaigns.exceptions import EmailCampaignUniqueNameError from email_campaigns.campaigns.models import EmailCampaign from email_campaigns.campaigns.types import EmailCampaignErrorSummary from email_campaigns.campaigns.validators import CampaignValidator from email_campaigns.emails.models import EmailDomain from tests.unit.types import CreateModel, CreatePgModel class TestEmailCampaignValidator: @pytest.mark.db def test_validate_name(self, validator: CampaignValidator) -> None: validator.validate_name( name="Test Campaign", account=Account(vendor_id=10, subaccount_id=0) ) assert True @pytest.mark.db def test_validate_name_existing( self, validator: CampaignValidator, create_model: CreateModel, ) -> None: campaign = create_model(EmailCampaign) validator.validate_name( name=campaign.name, account=campaign.account, campaign=campaign, ) assert True @pytest.mark.db def test_validate_name_invalid( self, validator: CampaignValidator, create_model: CreateModel, ) -> None: campaign = create_model(EmailCampaign) with pytest.raises(EmailCampaignUniqueNameError): validator.validate_name(name=campaign.name, account=campaign.account) @pytest.mark.db def test_validate_required_fields( self, validator: CampaignValidator, create_model: CreateModel, faker: faker.Faker, ) -> None: email_domain = create_model(EmailDomain) campaign = create_model( EmailCampaign, audience_id=faker.uuid4(cast_to=str), sender_name=faker.name(), subject=faker.sentence(), preview_text=faker.sentence(), email_domain=email_domain, email_username=faker.user_name(), send_at=faker.past_datetime(tzinfo=timezone.UTC), ) error_summary = validator.validate_required_fields(campaign) assert error_summary is None @pytest.mark.db def test_validate_required_fields_with_data( self, validator: CampaignValidator, create_model: CreateModel, faker: faker.Faker, ) -> None: email_domain = create_model(EmailDomain) campaign = create_model( EmailCampaign, audience_id=None, sender_name=faker.name(), subject=faker.sentence(), preview_text=None, email_domain=email_domain, email_username=faker.user_name(), send_at=faker.past_datetime(tzinfo=timezone.UTC), ) error_summary = validator.validate_required_fields( campaign, data={"audience_id": "skip"} ) assert error_summary is None @pytest.mark.db def test_validate_required_fields_missing_subject( self, validator: CampaignValidator, create_model: CreateModel, faker: faker.Faker, ) -> None: email_domain = create_model(EmailDomain) campaign = create_model( EmailCampaign, audience_id=faker.uuid4(cast_to=str), sender_name=faker.name(), subject=None, email_domain=email_domain, email_username=faker.user_name(), send_at=faker.past_datetime(tzinfo=timezone.UTC), ) error_summary = validator.validate_required_fields(campaign) assert error_summary == EmailCampaignErrorSummary( subject=Error(code="missing", message="Field required"), ) @pytest.mark.db def test_validate_audience_success( self, validator: CampaignValidator, create_pg_model: CreatePgModel ) -> None: audience = create_pg_model( Audience, archived_at=None, target=AudienceTarget.EMAIL, fan_count=100, ) validator.validate_audience(audience) assert True @pytest.mark.db def test_validate_audience_archived( self, validator: CampaignValidator, create_pg_model: CreatePgModel, faker: faker.Faker, ) -> None: audience = create_pg_model( Audience, archived_at=faker.past_datetime(tzinfo=timezone.UTC) ) with pytest.raises(ArchivedAudienceError): validator.validate_audience(audience) @pytest.mark.db def test_validate_audience_invalid( self, validator: CampaignValidator, create_pg_model: CreatePgModel ) -> None: audience = create_pg_model( Audience, archived_at=None, target=AudienceTarget.TEXT ) with pytest.raises(NotSupportedAudienceTargetError): validator.validate_audience(audience) @pytest.mark.db def test_validate_audience_empty( self, validator: CampaignValidator, create_pg_model: CreatePgModel ) -> None: audience = create_pg_model( Audience, archived_at=None, target=AudienceTarget.EMAIL, fan_count=0, ) with pytest.raises(EmptyAudienceError): validator.validate_audience(audience)