from collections.abc import Iterator from unittest import mock import pytest from anydi import Container from email_campaigns.automated.exceptions import SourceCampaignNotFoundError from email_campaigns.automated.handlers import ( GetSourceCampaignAutomatedEmailsHandler, GetSourceCampaignAutomatedEmailsRequest, SourceCampaignAutomatedEmailItem, ) from email_campaigns.automated.models import ( AutomatedEmail, AutomatedEmailTrigger, SourceCampaign, ) from tests.unit.types import CreateModel class TestGetSourceCampaignAutomatedEmailsHandler: @pytest.fixture(autouse=True) def _mock_find_potential_mailing_list_ids( self, container: Container ) -> Iterator[mock.MagicMock]: handler = container.resolve(GetSourceCampaignAutomatedEmailsHandler) with mock.patch.object( handler.source_campaign_repository, "find_potential_mailing_list_ids", return_value={}, ) as mocked: yield mocked @pytest.mark.db def test_returns_connected_automated_emails( self, handler: GetSourceCampaignAutomatedEmailsHandler, create_model: CreateModel, ) -> None: source_campaign = create_model( SourceCampaign, source="smf", campaign_id="campaign-123", ) automated_email = create_model( AutomatedEmail, source_campaign_connections=[ AutomatedEmailTrigger(source_campaign_id=source_campaign.id) ], ) response = handler.handle( GetSourceCampaignAutomatedEmailsRequest( source="smf", campaign_id="campaign-123", ) ) assert len(response.items) == 1 assert isinstance(response.items[0], SourceCampaignAutomatedEmailItem) assert response.items[0].id == automated_email.id assert response.items[0].subscription_only is False @pytest.mark.db def test_raises_not_found_when_source_campaign_missing( self, handler: GetSourceCampaignAutomatedEmailsHandler, ) -> None: with pytest.raises(SourceCampaignNotFoundError): handler.handle( GetSourceCampaignAutomatedEmailsRequest( source="smf", campaign_id="nonexistent", ) ) @pytest.mark.db def test_returns_empty_list_when_no_connected_automated_emails( self, handler: GetSourceCampaignAutomatedEmailsHandler, create_model: CreateModel, ) -> None: create_model( SourceCampaign, source="smf", campaign_id="campaign-456", ) response = handler.handle( GetSourceCampaignAutomatedEmailsRequest( source="smf", campaign_id="campaign-456", ) ) assert len(response.items) == 0 @pytest.mark.db def test_returns_subscription_only_from_trigger( self, handler: GetSourceCampaignAutomatedEmailsHandler, create_model: CreateModel, ) -> None: source_campaign = create_model( SourceCampaign, source="smf", campaign_id="campaign-789", ) create_model( AutomatedEmail, source_campaign_connections=[ AutomatedEmailTrigger( source_campaign_id=source_campaign.id, subscription_only=True, ) ], ) response = handler.handle( GetSourceCampaignAutomatedEmailsRequest( source="smf", campaign_id="campaign-789", ) ) assert len(response.items) == 1 assert response.items[0].subscription_only is True @pytest.mark.db def test_returns_correct_subscription_only_per_item( self, handler: GetSourceCampaignAutomatedEmailsHandler, create_model: CreateModel, ) -> None: source_campaign = create_model( SourceCampaign, source="smf", campaign_id="campaign-multi", ) email_1 = create_model( AutomatedEmail, source_campaign_connections=[ AutomatedEmailTrigger( source_campaign_id=source_campaign.id, subscription_only=False, ) ], ) email_2 = create_model( AutomatedEmail, source_campaign_connections=[ AutomatedEmailTrigger( source_campaign_id=source_campaign.id, subscription_only=True, ) ], ) response = handler.handle( GetSourceCampaignAutomatedEmailsRequest( source="smf", campaign_id="campaign-multi", ) ) result_by_id = {item.id: item for item in response.items} assert len(result_by_id) == 2 assert result_by_id[email_1.id].subscription_only is False assert result_by_id[email_2.id].subscription_only is True @pytest.mark.db def test_returns_potential_mailing_list_ids_per_item( self, handler: GetSourceCampaignAutomatedEmailsHandler, create_model: CreateModel, _mock_find_potential_mailing_list_ids: mock.MagicMock, ) -> None: source_campaign = create_model( SourceCampaign, source="smf", campaign_id="campaign-mailing", ) email_1 = create_model( AutomatedEmail, source_campaign_connections=[ AutomatedEmailTrigger(source_campaign_id=source_campaign.id) ], ) email_2 = create_model( AutomatedEmail, source_campaign_connections=[ AutomatedEmailTrigger(source_campaign_id=source_campaign.id) ], ) _mock_find_potential_mailing_list_ids.return_value = { email_1.id: ["ml-1", "ml-2"], email_2.id: ["ml-3"], } response = handler.handle( GetSourceCampaignAutomatedEmailsRequest( source="smf", campaign_id="campaign-mailing", ) ) result_by_id = {item.id: item for item in response.items} assert result_by_id[email_1.id].potential_mailing_list_ids == ["ml-1", "ml-2"] assert result_by_id[email_2.id].potential_mailing_list_ids == ["ml-3"] _mock_find_potential_mailing_list_ids.assert_called_once_with( source="smf", campaign_id="campaign-mailing", ) @pytest.mark.db def test_returns_empty_mailing_list_ids_when_email_not_in_result( self, handler: GetSourceCampaignAutomatedEmailsHandler, create_model: CreateModel, _mock_find_potential_mailing_list_ids: mock.MagicMock, ) -> None: source_campaign = create_model( SourceCampaign, source="smf", campaign_id="campaign-no-lists", ) create_model( AutomatedEmail, source_campaign_connections=[ AutomatedEmailTrigger(source_campaign_id=source_campaign.id) ], ) _mock_find_potential_mailing_list_ids.return_value = {} response = handler.handle( GetSourceCampaignAutomatedEmailsRequest( source="smf", campaign_id="campaign-no-lists", ) ) assert len(response.items) == 1 assert response.items[0].potential_mailing_list_ids == []