"""Unit tests for SES email connector.""" from unittest.mock import MagicMock from unittest.mock import patch import pytest from src.connectors.ses import create_csv_content from src.connectors.ses import send_email_via_ses from src.connectors.ses import send_email_with_csv def test_create_csv_with_single_email(): """Test CSV creation with a single email.""" emails = ['test@example.com'] result = create_csv_content(emails) # Decode bytes to string for assertion content = result.decode('utf-8') # Check header assert 'Email_Address' in content # Check email is quoted assert '"test@example.com"' in content def test_create_csv_with_multiple_emails(): """Test CSV creation with multiple emails.""" emails = ['test1@example.com', 'test2@example.com', 'test3@example.com'] result = create_csv_content(emails) content = result.decode('utf-8') # Check all emails are present for email in emails: assert f'"{email}"' in content # Check header is present only once assert content.count('Email_Address') == 1 def test_create_csv_with_empty_list(): """Test CSV creation with empty email list.""" emails = [] result = create_csv_content(emails) content = result.decode('utf-8') # Should only have header assert 'Email_Address' in content lines = content.strip().split('\n') assert len(lines) == 1 # Only header @patch('src.connectors.ses.send_email_via_ses') @patch('src.connectors.ses.datetime') def test_send_email_with_csv(mock_datetime, mock_send_email): """Test sending email with CSV attachment.""" # Mock datetime mock_now = MagicMock() mock_now.strftime.side_effect = lambda fmt: { '%m/%d/%Y': '01/07/2026', '%m.%d.%Y': '01.07.2026' }[fmt] mock_datetime.now.return_value = mock_now # Test data vendor_name = 'TestVendor' emails_list = ['test1@example.com', 'test2@example.com'] to_addresses = ['vendor@example.com'] cc_addresses = ['cc@example.com'] sender_email = 'sender@example.com' sender_display_name = 'Test Sender' # Call function send_email_with_csv( vendor_name=vendor_name, emails_list=emails_list, to_addresses=to_addresses, cc_addresses=cc_addresses, sender_email=sender_email, sender_display_name=sender_display_name ) # Verify send_email_via_ses was called mock_send_email.assert_called_once() # Verify call arguments call_args = mock_send_email.call_args[1] assert call_args['subject'] == 'Sony Music Fan Delete Request - TestVendor - 01/07/2026' assert 'TestVendor' in call_args['body'] assert call_args['to_addresses'] == to_addresses assert call_args['cc_addresses'] == cc_addresses assert call_args['sender_email'] == sender_email assert call_args['sender_display_name'] == sender_display_name assert call_args['csv_filename'] == 'Sony Music Fan Delete Request - TestVendor - 01.07.2026.csv' assert isinstance(call_args['csv_content'], bytes) @patch('src.connectors.ses.send_email_via_ses') @patch('src.connectors.ses.logger') def test_send_email_with_empty_list(mock_logger, mock_send_email): """Test that no email is sent with empty list.""" send_email_with_csv( vendor_name='TestVendor', emails_list=[], to_addresses=['vendor@example.com'], cc_addresses=[], sender_email='sender@example.com', sender_display_name='Test Sender' ) # Verify no email was sent mock_send_email.assert_not_called() # Verify log message mock_logger.info.assert_called() @patch('src.connectors.ses.boto3.client') def test_send_email_via_ses_success(mock_boto_client): """Test successful email sending via SES.""" # Mock SES client mock_ses = MagicMock() mock_ses.send_raw_email.return_value = {'MessageId': 'test-message-id'} mock_boto_client.return_value = mock_ses # Test data subject = 'Test Subject' body = '
Test Body
' to_addresses = ['to@example.com'] cc_addresses = ['cc@example.com'] sender_email = 'sender@example.com' sender_display_name = 'Test Sender' csv_filename = 'test.csv' csv_content = b'Email_Address\n"test@example.com"\n' # Call function send_email_via_ses( subject=subject, body=body, to_addresses=to_addresses, cc_addresses=cc_addresses, sender_email=sender_email, sender_display_name=sender_display_name, csv_filename=csv_filename, csv_content=csv_content ) # Verify SES client was called mock_ses.send_raw_email.assert_called_once() # Verify call arguments call_args = mock_ses.send_raw_email.call_args[1] assert call_args['Source'] == sender_email assert call_args['Destinations'] == to_addresses + cc_addresses assert 'RawMessage' in call_args @patch('src.connectors.ses.boto3.client') def test_send_email_via_ses_failure(mock_boto_client): """Test email sending failure handling.""" # Mock SES client to raise exception mock_ses = MagicMock() mock_ses.send_raw_email.side_effect = Exception('SES Error') mock_boto_client.return_value = mock_ses # Test data subject = 'Test Subject' body = 'Test Body
' to_addresses = ['to@example.com'] cc_addresses = [] sender_email = 'sender@example.com' sender_display_name = 'Test Sender' csv_filename = 'test.csv' csv_content = b'Email_Address\n' # Verify exception is raised with pytest.raises(Exception) as exc_info: send_email_via_ses( subject=subject, body=body, to_addresses=to_addresses, cc_addresses=cc_addresses, sender_email=sender_email, sender_display_name=sender_display_name, csv_filename=csv_filename, csv_content=csv_content ) assert 'SES Error' in str(exc_info.value)