from unittest import mock import faker import pytest from dirty_equals import IsList from fansifter_common.adapters.ows_account import Vendor from fansifter_common.adapters.sendgrid.models import Email, FanData, MergeTags from fansifter_common.core.enums import Brand from fansifter_common.email import EmailType from fansifter_common.legal_info.constants import DEFAULT_COUNTRY_CODE from fansifter_common.legal_info.types import LegalEntity from fansifter_common.translation.types import Terms from email_campaigns.campaigns.models import EmailCampaign from email_campaigns.emails.models import EmailDomain from email_campaigns.emails.repositories import EmailTestSendRepository from email_campaigns.emails.services import EmailSendService from email_campaigns.profile.models import Profile from tests.unit.types import BuildModel, CreateModel class TestEmailSendService: @pytest.mark.db def test_send_test_email_with_user_content( self, service: EmailSendService, create_model: CreateModel, build_model: BuildModel, email_test_send_repository: EmailTestSendRepository, identity_id: str, sendgrid_client_mock: mock.MagicMock, stripo_client_mock: mock.MagicMock, preference_center_encrypter_mock: mock.MagicMock, legal_info_service_mock: mock.MagicMock, translation_service_mock: mock.MagicMock, ows_account_client_mock: mock.MagicMock, faker: faker.Faker, ) -> None: privacy_links_block = faker.pystr() legal_entity = build_model(LegalEntity) terms = build_model(Terms) vendor = build_model(Vendor) legal_info_service_mock.prepare_privacy_links_for_country.return_value = ( privacy_links_block ) legal_info_service_mock.get_legal_entity.return_value = legal_entity translation_service_mock.get_translations_by_country_code.return_value = { "en": terms } ows_account_client_mock.get_vendor.return_value = vendor preference_center_encrypter_mock.encrypt.return_value = b"token" email_1 = faker.email() email_2 = faker.email() recipients = {email_1, email_2} create_model(Profile, email=email_1, first_name=None) email_domain = create_model(EmailDomain, domain="test.com", brand=Brand.AWAL) campaign = create_model( EmailCampaign, email_username=faker.pystr(), email_domain=email_domain, subject=None, ) email_html_content = faker.pystr() sendgrid_client_mock.send_mail.return_value = None service.send_test_email( email=campaign, content=email_html_content, emails=recipients, identity_id=identity_id, ) from_email = Email( email=f"{campaign.email_username}@test.com", name=campaign.sender_name, ) sendgrid_client_mock.send_mail.assert_called_with( email_id=campaign.id, email_type=EmailType.CAMPAIGN, automated_email_trigger_id=None, version="v2", brand=email_domain.brand, vendor_id=vendor.vendor_id, vendor_name=vendor.name, subject=f" [TEST] {campaign.name}", to_fans=IsList( FanData( email=email_2, profile_token=None, country_iso2=DEFAULT_COUNTRY_CODE, legal_entity_address=legal_entity.address, legal_entity_name=legal_entity.name, privacy_links_block=privacy_links_block, opt_in_info=terms.optInInfo, opt_in_info_external=terms.optInInfoExternal, unsubscribe_text=terms.unsubscribe, ), FanData( email=email_1, profile_token="token", country_iso2=DEFAULT_COUNTRY_CODE, legal_entity_address=legal_entity.address, legal_entity_name=legal_entity.name, privacy_links_block=privacy_links_block, opt_in_info=terms.optInInfo, opt_in_info_external=terms.optInInfoExternal, unsubscribe_text=terms.unsubscribe, ), check_order=False, ), from_email=from_email, html_content=email_html_content, preview_text=campaign.preview_text, is_test=True, ) stripo_client_mock.compress.assert_not_called() sends = email_test_send_repository.all() assert sends assert len(sends) == 1 email_send = sends[0] assert email_send.email_id == campaign.id assert email_send.email_type == EmailType.CAMPAIGN assert email_send.recipients == list(recipients) assert email_send.created_by == identity_id @pytest.mark.db def test_send_test_email_without_user_content( self, service: EmailSendService, create_model: CreateModel, build_model: BuildModel, email_test_send_repository: EmailTestSendRepository, identity_id: str, sendgrid_client_mock: mock.MagicMock, stripo_client_mock: mock.MagicMock, legal_info_service_mock: mock.MagicMock, preference_center_encrypter_mock: mock.MagicMock, translation_service_mock: mock.MagicMock, ows_account_client_mock: mock.MagicMock, faker: faker.Faker, ) -> None: privacy_links_block = faker.pystr() legal_entity = build_model(LegalEntity) terms = build_model(Terms) vendor = build_model(Vendor) legal_info_service_mock.prepare_privacy_links_for_country.return_value = ( privacy_links_block ) legal_info_service_mock.get_legal_entity.return_value = legal_entity translation_service_mock.get_translations_by_country_code.return_value = { "en": terms } ows_account_client_mock.get_vendor.return_value = vendor preference_center_encrypter_mock.encrypt.return_value = b"token" email_1 = faker.email() email_2 = faker.email() recipients = {email_1, email_2} create_model(Profile, email=email_1, first_name=None) email_domain = create_model(EmailDomain, domain="test.com", brand=Brand.AWAL) campaign = create_model( EmailCampaign, email_username=faker.pystr(), email_domain=email_domain, subject=None, ) email_html_content = faker.pystr() stripo_client_mock.compress.return_value = email_html_content sendgrid_client_mock.send_mail.return_value = None service.send_test_email( email=campaign, content=None, emails=recipients, identity_id=identity_id, ) from_email = Email( email=f"{campaign.email_username}@test.com", name=campaign.sender_name, ) sendgrid_client_mock.send_mail.assert_called_with( email_id=campaign.id, email_type=EmailType.CAMPAIGN, automated_email_trigger_id=None, version="v2", brand=email_domain.brand, vendor_id=vendor.vendor_id, vendor_name=vendor.name, subject=f" [TEST] {campaign.name}", to_fans=IsList( FanData( email=email_2, profile_token=None, country_iso2=DEFAULT_COUNTRY_CODE, legal_entity_address=legal_entity.address, legal_entity_name=legal_entity.name, privacy_links_block=privacy_links_block, opt_in_info=terms.optInInfo, opt_in_info_external=terms.optInInfoExternal, unsubscribe_text=terms.unsubscribe, ), FanData( email=email_1, profile_token="token", country_iso2=DEFAULT_COUNTRY_CODE, legal_entity_address=legal_entity.address, legal_entity_name=legal_entity.name, privacy_links_block=privacy_links_block, opt_in_info=terms.optInInfo, opt_in_info_external=terms.optInInfoExternal, unsubscribe_text=terms.unsubscribe, ), check_order=False, ), from_email=from_email, html_content=email_html_content, preview_text=campaign.preview_text, is_test=True, ) sends = email_test_send_repository.all() assert sends assert len(sends) == 1 email_send = sends[0] assert email_send.email_id == campaign.id assert email_send.email_type == EmailType.CAMPAIGN assert email_send.recipients == list(recipients) assert email_send.created_by == identity_id @pytest.mark.db def test_send_test_email_with_unapplied_changes_uses_unsaved_subject_prefix( self, service: EmailSendService, create_model: CreateModel, build_model: BuildModel, identity_id: str, sendgrid_client_mock: mock.MagicMock, legal_info_service_mock: mock.MagicMock, translation_service_mock: mock.MagicMock, ows_account_client_mock: mock.MagicMock, preference_center_encrypter_mock: mock.MagicMock, faker: faker.Faker, ) -> None: legal_info_service_mock.prepare_privacy_links_for_country.return_value = ( faker.pystr() ) legal_info_service_mock.get_legal_entity.return_value = build_model(LegalEntity) translation_service_mock.get_translations_by_country_code.return_value = { "en": build_model(Terms) } ows_account_client_mock.get_vendor.return_value = build_model(Vendor) preference_center_encrypter_mock.encrypt.return_value = b"token" email_domain = create_model(EmailDomain, domain="test.com", brand=Brand.AWAL) campaign = create_model( EmailCampaign, email_username=faker.pystr(), email_domain=email_domain, subject=None, has_unapplied_changes=True, ) sendgrid_client_mock.reset_mock() sendgrid_client_mock.send_mail.return_value = None service.send_test_email( email=campaign, content=faker.pystr(), emails={faker.email()}, identity_id=identity_id, with_unapplied_changes=True, ) [call] = sendgrid_client_mock.send_mail.call_args_list assert call.kwargs["subject"] == f" [TEST-Unsaved version] {campaign.name}" @pytest.mark.db def test_send_test_email_flag_set_but_no_unapplied_changes_uses_test_prefix( self, service: EmailSendService, create_model: CreateModel, build_model: BuildModel, identity_id: str, sendgrid_client_mock: mock.MagicMock, legal_info_service_mock: mock.MagicMock, translation_service_mock: mock.MagicMock, ows_account_client_mock: mock.MagicMock, preference_center_encrypter_mock: mock.MagicMock, faker: faker.Faker, ) -> None: legal_info_service_mock.prepare_privacy_links_for_country.return_value = ( faker.pystr() ) legal_info_service_mock.get_legal_entity.return_value = build_model(LegalEntity) translation_service_mock.get_translations_by_country_code.return_value = { "en": build_model(Terms) } ows_account_client_mock.get_vendor.return_value = build_model(Vendor) preference_center_encrypter_mock.encrypt.return_value = b"token" email_domain = create_model(EmailDomain, domain="test.com", brand=Brand.AWAL) campaign = create_model( EmailCampaign, email_username=faker.pystr(), email_domain=email_domain, subject=None, has_unapplied_changes=False, ) sendgrid_client_mock.reset_mock() sendgrid_client_mock.send_mail.return_value = None service.send_test_email( email=campaign, content=faker.pystr(), emails={faker.email()}, identity_id=identity_id, with_unapplied_changes=True, ) [call] = sendgrid_client_mock.send_mail.call_args_list assert call.kwargs["subject"] == f" [TEST] {campaign.name}" @pytest.mark.db def test_send_test_email_populates_first_name_merge_tag( self, service: EmailSendService, create_model: CreateModel, build_model: BuildModel, identity_id: str, sendgrid_client_mock: mock.MagicMock, legal_info_service_mock: mock.MagicMock, translation_service_mock: mock.MagicMock, ows_account_client_mock: mock.MagicMock, preference_center_encrypter_mock: mock.MagicMock, faker: faker.Faker, ) -> None: legal_info_service_mock.prepare_privacy_links_for_country.return_value = ( faker.pystr() ) legal_info_service_mock.get_legal_entity.return_value = build_model(LegalEntity) translation_service_mock.get_translations_by_country_code.return_value = { "en": build_model(Terms) } ows_account_client_mock.get_vendor.return_value = build_model(Vendor) preference_center_encrypter_mock.encrypt.return_value = b"token" email_known = "fan@known.com" email_unknown = "fan@unknown.com" create_model(Profile, email=email_known, first_name="Anna") email_domain = create_model(EmailDomain, domain="test.com", brand=Brand.AWAL) campaign = create_model( EmailCampaign, email_username=faker.pystr(), email_domain=email_domain, ) sendgrid_client_mock.reset_mock() sendgrid_client_mock.send_mail.return_value = None service.send_test_email( email=campaign, content=faker.pystr(), emails={email_known, email_unknown}, identity_id=identity_id, ) [call] = sendgrid_client_mock.send_mail.call_args_list to_fans = call.kwargs["to_fans"] fans_by_email = {fan.email: fan for fan in to_fans} assert fans_by_email[email_known].merge_tags == MergeTags(first_name="Anna") assert fans_by_email[email_unknown].merge_tags == MergeTags(first_name=None)