from unittest import mock import pytest from faker import Faker from fansifter_common.auth.exceptions import PermissionDenied from fansifter_common.constants import PROD_ENVIRONMENT from email_campaigns.campaigns.handlers import GenerateCampaignPublicPreviewUrlHandler from email_campaigns.campaigns.models import EmailCampaign from email_campaigns.emails.exceptions import EmailNotFoundError from email_campaigns.emails.handlers import GenerateEmailPublicPreviewUrlRequest from tests.unit.helpers import override_settings from tests.unit.types import CreateModel class TestGenerateCampaignPublicPreviewUrlHandler: @pytest.mark.db def test_generate_campaign_public_preview_url_dev_environment( self, handler: GenerateCampaignPublicPreviewUrlHandler, create_model: CreateModel, identity_id: str, faker: Faker, tokens_mock: mock.MagicMock, ) -> None: """Test URL generation in dev environment uses QA domain.""" campaign = create_model(EmailCampaign) expected_token = faker.uuid4() requested_domain = "theorchard.com" tokens_mock.encrypt_email_id.return_value = expected_token response = handler.handle( GenerateEmailPublicPreviewUrlRequest( identity_id=identity_id, email_id=campaign.id, domain=requested_domain, ) ) # In dev environment, should use QA domain regardless of requested domain expected_url = f"https://fansifter-emails.qapdesuite.com/{campaign.id}?pwd={expected_token}" assert response.url == expected_url @pytest.mark.db def test_generate_campaign_public_preview_url_unauthorized( self, handler: GenerateCampaignPublicPreviewUrlHandler, create_model: CreateModel, identity_id: str, auth_service_mock: mock.MagicMock, ) -> None: campaign = create_model(EmailCampaign) domain = "fansifter.theorchard.com" auth_service_mock.authorize_account.side_effect = PermissionDenied() with pytest.raises(PermissionDenied): handler.handle( GenerateEmailPublicPreviewUrlRequest( identity_id=identity_id, email_id=campaign.id, domain=domain, ) ) @pytest.mark.db def test_generate_campaign_public_preview_url_campaign_not_found( self, handler: GenerateCampaignPublicPreviewUrlHandler, identity_id: str, faker: Faker, ) -> None: campaign_id = faker.uuid4() domain = "fansifter.theorchard.com" with pytest.raises(EmailNotFoundError): handler.handle( GenerateEmailPublicPreviewUrlRequest( identity_id=identity_id, email_id=campaign_id, domain=domain, ) ) @pytest.mark.db def test_generate_campaign_public_preview_url_token_parameters( self, handler: GenerateCampaignPublicPreviewUrlHandler, create_model: CreateModel, identity_id: str, faker: Faker, tokens_mock: mock.MagicMock, ) -> None: """Test that encrypt_email_id is called with correct campaign ID.""" campaign = create_model(EmailCampaign) expected_token = faker.uuid4() domain = "theorchard.com" tokens_mock.encrypt_email_id.return_value = expected_token handler.handle( GenerateEmailPublicPreviewUrlRequest( identity_id=identity_id, email_id=campaign.id, domain=domain, ) ) tokens_mock.encrypt_email_id.assert_called_once_with(campaign.id) @pytest.mark.db def test_generate_campaign_public_preview_url_prod_valid_domain( self, handler: GenerateCampaignPublicPreviewUrlHandler, create_model: CreateModel, identity_id: str, faker: Faker, tokens_mock: mock.MagicMock, ) -> None: """Test URL generation in prod with valid domain uses requested domain.""" campaign = create_model(EmailCampaign) expected_token = faker.uuid4() requested_domain = "theorchard.com" tokens_mock.encrypt_email_id.return_value = expected_token with override_settings( environment=PROD_ENVIRONMENT, email_public_preview_available_domains=["theorchard.com", "awal.com"], ): response = handler.handle( GenerateEmailPublicPreviewUrlRequest( identity_id=identity_id, email_id=campaign.id, domain=requested_domain, ) ) expected_url = f"https://fansifter-emails.theorchard.com/{campaign.id}?pwd={expected_token}" assert response.url == expected_url @pytest.mark.db def test_generate_campaign_public_preview_url_prod_invalid_domain_fallback( self, handler: GenerateCampaignPublicPreviewUrlHandler, create_model: CreateModel, identity_id: str, faker: Faker, tokens_mock: mock.MagicMock, ) -> None: """Test URL generation in prod with invalid domain falls back to first allowed domain.""" campaign = create_model(EmailCampaign) expected_token = faker.uuid4() invalid_domain = "invalid.com" tokens_mock.encrypt_email_id.return_value = expected_token with override_settings( environment=PROD_ENVIRONMENT, email_public_preview_available_domains=["theorchard.com", "awal.com"], ): response = handler.handle( GenerateEmailPublicPreviewUrlRequest( identity_id=identity_id, email_id=campaign.id, domain=invalid_domain, ) ) # Should fall back to first allowed domain expected_url = f"https://fansifter-emails.theorchard.com/{campaign.id}?pwd={expected_token}" assert response.url == expected_url @pytest.mark.db @pytest.mark.parametrize( "environment,requested_domain,expected_domain", [ ("dev", "theorchard.com", "qapdesuite.com"), ("qa", "awal.com", "qapdesuite.com"), ("test", "theorchard.com", "qapdesuite.com"), ], ) def test_generate_campaign_public_preview_url_non_prod_uses_qa_domain( self, handler: GenerateCampaignPublicPreviewUrlHandler, create_model: CreateModel, identity_id: str, faker: Faker, tokens_mock: mock.MagicMock, environment: str, requested_domain: str, expected_domain: str, ) -> None: """Test that non-prod environments always use QA domain.""" campaign = create_model(EmailCampaign) expected_token = faker.uuid4() tokens_mock.encrypt_email_id.return_value = expected_token with override_settings(environment=environment): response = handler.handle( GenerateEmailPublicPreviewUrlRequest( identity_id=identity_id, email_id=campaign.id, domain=requested_domain, ) ) expected_url = f"https://fansifter-emails.{expected_domain}/{campaign.id}?pwd={expected_token}" assert response.url == expected_url