from unittest import mock import pytest from faker import Faker from fansifter_common.email import EmailType from email_campaigns.campaigns.handlers import GetCampaignPublicPreviewHandler from email_campaigns.campaigns.models import EmailCampaign from email_campaigns.emails.enums import TokenDecryptionStatus from email_campaigns.emails.exceptions import ( EmailContentMissingError, EmailNotFoundError, EmailPublicPreviewTokenExpiredError, ) from email_campaigns.emails.handlers import GetEmailPublicPreviewRequest from email_campaigns.emails.tokens import TokenDecryptionResult from tests.unit.types import CreateModel class TestGetCampaignPublicPreviewHandler: @pytest.mark.db def test_get_campaign_public_preview( self, handler: GetCampaignPublicPreviewHandler, create_model: CreateModel, campaign_public_preview_cache_mock: mock.MagicMock, stripo_client_mock: mock.MagicMock, sendgrid_client_mock: mock.MagicMock, tokens_mock: mock.MagicMock, ) -> None: stripo_client_mock.reset_mock() campaign_public_preview_cache_mock.reset_mock() sendgrid_client_mock.reset_mock() campaign = create_model( EmailCampaign, html_content="

html content

-privacyFooterBlock-", css_content="p { color: red; }", ) tokens_mock.decrypt_token.return_value = TokenDecryptionResult( status=TokenDecryptionStatus.VALID, email_id=campaign.id, ) campaign_public_preview_cache_mock.get.return_value = None compressed_html = ( "

compressed

-privacyFooterBlock-" ) stripo_client_mock.compress.return_value = compressed_html footer_html = "
Privacy Footer
" sendgrid_client_mock.get_user_privacy_footer_block.return_value = footer_html response = handler.handle( GetEmailPublicPreviewRequest( email_id=campaign.id, token="valid_token", ) ) stripo_client_mock.compress.assert_called_once_with( campaign.html_content, campaign.css_content, ) sendgrid_client_mock.get_user_privacy_footer_block.assert_called_once() expected_html = compressed_html.replace("-privacyFooterBlock-", footer_html) campaign_public_preview_cache_mock.set.assert_called_once_with( campaign.id, EmailType.CAMPAIGN, expected_html ) assert response.html == expected_html assert footer_html in response.html @pytest.mark.db def test_get_campaign_public_preview_no_token( self, handler: GetCampaignPublicPreviewHandler, create_model: CreateModel, ) -> None: campaign = create_model(EmailCampaign) with pytest.raises(EmailNotFoundError): handler.handle( GetEmailPublicPreviewRequest( email_id=campaign.id, token=None, ) ) @pytest.mark.db def test_get_campaign_public_preview_invalid_token( self, handler: GetCampaignPublicPreviewHandler, create_model: CreateModel, tokens_mock: mock.MagicMock, ) -> None: campaign = create_model(EmailCampaign) tokens_mock.decrypt_token.return_value = TokenDecryptionResult( status=TokenDecryptionStatus.INVALID, email_id=None, ) with pytest.raises(EmailNotFoundError): handler.handle( GetEmailPublicPreviewRequest( email_id=campaign.id, token="invalid_token", ) ) @pytest.mark.db def test_get_campaign_public_preview_mismatched_campaign_id( self, handler: GetCampaignPublicPreviewHandler, create_model: CreateModel, faker: Faker, tokens_mock: mock.MagicMock, ) -> None: campaign = create_model(EmailCampaign) different_id = faker.uuid4() tokens_mock.decrypt_token.return_value = TokenDecryptionResult( status=TokenDecryptionStatus.VALID, email_id=different_id, ) with pytest.raises(EmailNotFoundError): handler.handle( GetEmailPublicPreviewRequest( email_id=campaign.id, token="token_with_different_id", ) ) @pytest.mark.db def test_get_campaign_public_preview_campaign_deleted( self, handler: GetCampaignPublicPreviewHandler, faker: Faker, tokens_mock: mock.MagicMock, ) -> None: campaign_id = faker.uuid4() tokens_mock.decrypt_token.return_value = TokenDecryptionResult( status=TokenDecryptionStatus.VALID, email_id=campaign_id, ) with pytest.raises(EmailNotFoundError): handler.handle( GetEmailPublicPreviewRequest( email_id=campaign_id, token="valid_token", ) ) @pytest.mark.db def test_get_campaign_public_preview_missing_content( self, handler: GetCampaignPublicPreviewHandler, create_model: CreateModel, campaign_public_preview_cache_mock: mock.MagicMock, tokens_mock: mock.MagicMock, ) -> None: campaign = create_model( EmailCampaign, html_content=None, css_content=None, ) tokens_mock.decrypt_token.return_value = TokenDecryptionResult( status=TokenDecryptionStatus.VALID, email_id=campaign.id, ) campaign_public_preview_cache_mock.get.return_value = None with pytest.raises(EmailContentMissingError): handler.handle( GetEmailPublicPreviewRequest( email_id=campaign.id, token="valid_token", ) ) @pytest.mark.db def test_get_campaign_public_preview_expired_token( self, handler: GetCampaignPublicPreviewHandler, create_model: CreateModel, tokens_mock: mock.MagicMock, ) -> None: campaign = create_model(EmailCampaign) tokens_mock.decrypt_token.return_value = TokenDecryptionResult( status=TokenDecryptionStatus.EXPIRED, email_id=campaign.id, ) with pytest.raises(EmailPublicPreviewTokenExpiredError): handler.handle( GetEmailPublicPreviewRequest( email_id=campaign.id, token="expired_token", ) ) @pytest.mark.db def test_get_campaign_public_preview_replaces_first_name_with_fallback( self, handler: GetCampaignPublicPreviewHandler, create_model: CreateModel, campaign_public_preview_cache_mock: mock.MagicMock, stripo_client_mock: mock.MagicMock, sendgrid_client_mock: mock.MagicMock, tokens_mock: mock.MagicMock, ) -> None: stripo_client_mock.reset_mock() campaign_public_preview_cache_mock.reset_mock() sendgrid_client_mock.reset_mock() campaign = create_model( EmailCampaign, html_content="

Hi -firstName-!

-privacyFooterBlock-", css_content="p { color: red; }", ) tokens_mock.decrypt_token.return_value = TokenDecryptionResult( status=TokenDecryptionStatus.VALID, email_id=campaign.id, ) campaign_public_preview_cache_mock.get.return_value = None stripo_client_mock.compress.return_value = ( "

Hi -firstName-!

-privacyFooterBlock-" ) sendgrid_client_mock.get_user_privacy_footer_block.return_value = "