You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kompass/jdav_web/mailer/tests/models.py

273 lines
10 KiB
Python

from unittest import skip, mock
from django.test import TestCase
from django.conf import settings
from django.utils import timezone
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _
from django.core.files.uploadedfile import SimpleUploadedFile
from members.models import Member, Group, DIVERSE, Freizeit, MemberNoteList, GEMEINSCHAFTS_TOUR, MUSKELKRAFT_ANREISE
from mailer.models import EmailAddress, EmailAddressForm, Message, MessageForm, Attachment
from mailer.mailutils import SENT, NOT_SENT, PARTLY_SENT
from .utils import BasicMailerTestCase
class EmailAddressTestCase(BasicMailerTestCase):
def test_email(self):
self.assertEqual(self.em.email, f"foobar@{settings.DOMAIN}")
def test_str(self):
self.assertEqual(self.em.email, str(self.em))
def test_forwards(self):
self.assertEqual(self.em.forwards, {'fritz@foo.com', 'paul@foo.com'})
class EmailAddressFormTestCase(BasicMailerTestCase):
def test_clean(self):
# instantiate form with only name field set
form = EmailAddressForm(data={'name': 'bar'})
# validate the form - this should fail due to missing required recipients
self.assertFalse(form.is_valid())
class MessageFormTestCase(BasicMailerTestCase):
def test_clean(self):
# instantiate form with only subject and content fields set
form = MessageForm(data={'subject': 'Test Subject', 'content': 'Test content'})
# validate the form - this should fail due to missing required recipients
self.assertFalse(form.is_valid())
class MessageTestCase(BasicMailerTestCase):
def setUp(self):
super().setUp()
self.message = Message.objects.create(
subject='Test Message',
content='This is a test message'
)
self.freizeit = Freizeit.objects.create(
name='Test Freizeit',
kilometers_traveled=120,
tour_type=GEMEINSCHAFTS_TOUR,
tour_approach=MUSKELKRAFT_ANREISE,
difficulty=1
)
self.notelist = MemberNoteList.objects.create(
title='Test Note List'
)
# Set up message with multiple recipient types
self.message.to_groups.add(self.mygroup)
self.message.to_freizeit = self.freizeit
self.message.to_notelist = self.notelist
self.message.to_members.add(self.fritz)
self.message.save()
# Create a sender member for submit tests
self.sender = Member.objects.create(
prename='Sender',
lastname='Test',
birth_date=timezone.now().date(),
email='sender@test.com',
gender=DIVERSE
)
def test_str(self):
self.assertEqual(str(self.message), 'Test Message')
def test_get_recipients(self):
recipients = self.message.get_recipients()
self.assertIn('My Group', recipients)
self.assertIn('Test Freizeit', recipients)
self.assertIn('Test Note List', recipients)
self.assertIn('Fritz Wulter', recipients)
def test_get_recipients_with_many_members(self):
# Add additional members to test the "Some other members" case
for i in range(3):
member = Member.objects.create(
prename=f'Member{i}',
lastname='Test',
birth_date=timezone.now().date(),
email=f'member{i}@test.com',
gender=DIVERSE
)
self.message.to_members.add(member)
recipients = self.message.get_recipients()
self.assertIn(_('Some other members'), recipients)
@mock.patch('mailer.models.send')
def test_submit_successful(self, mock_send):
# Mock successful email sending
mock_send.return_value = SENT
# Test submit method
result = self.message.submit(sender=self.sender)
# Verify the message was marked as sent
self.message.refresh_from_db()
self.assertTrue(self.message.sent)
self.assertEqual(result, SENT)
# Verify send was called
self.assertTrue(mock_send.called)
@mock.patch('mailer.models.send')
def test_submit_failed(self, mock_send):
# Mock failed email sending
mock_send.return_value = NOT_SENT
# Test submit method
result = self.message.submit(sender=self.sender)
# Verify the message was not marked as sent
self.message.refresh_from_db()
self.assertFalse(self.message.sent)
# Note: The submit method always returns SENT when an exception occurs
self.assertEqual(result, SENT)
@mock.patch('mailer.models.send')
def test_submit_without_sender(self, mock_send):
# Mock successful email sending
mock_send.return_value = SENT
# Test submit method without sender
result = self.message.submit()
# Verify the message was marked as sent
self.message.refresh_from_db()
self.assertTrue(self.message.sent)
self.assertEqual(result, SENT)
@mock.patch('mailer.models.send')
def test_submit_subject_cleaning(self, mock_send):
# Mock successful email sending
mock_send.return_value = SENT
# Create message with underscores in subject
message_with_underscores = Message.objects.create(
subject='Test_Message_With_Underscores',
content='Test content'
)
message_with_underscores.to_members.add(self.fritz)
# Test submit method
result = message_with_underscores.submit()
# Verify underscores were removed from subject
message_with_underscores.refresh_from_db()
self.assertEqual(message_with_underscores.subject, 'Test Message With Underscores')
@mock.patch('mailer.models.send')
def test_submit_exception_handling(self, mock_send):
# Mock an exception during email sending
mock_send.side_effect = Exception("Email sending failed")
# Test submit method
result = self.message.submit(sender=self.sender)
# Verify the message was not marked as sent
self.message.refresh_from_db()
self.assertFalse(self.message.sent)
# When exception occurs, it should return NOT_SENT
self.assertEqual(result, NOT_SENT)
@mock.patch('mailer.models.send')
@mock.patch('django.conf.settings.SEND_FROM_ASSOCIATION_EMAIL', False)
def test_submit_with_sender_no_association_email(self, mock_send):
# Mock successful email sending
mock_send.return_value = PARTLY_SENT
# Test submit method with sender but SEND_FROM_ASSOCIATION_EMAIL disabled
result = self.message.submit(sender=self.sender)
# Verify the message was marked as sent
self.message.refresh_from_db()
self.assertTrue(self.message.sent)
self.assertEqual(result, SENT)
@mock.patch('mailer.models.send')
@mock.patch('django.conf.settings.SEND_FROM_ASSOCIATION_EMAIL', False)
def test_submit_with_reply_to_logic(self, mock_send):
# Mock successful email sending
mock_send.return_value = SENT
# Create a sender with internal email capability
sender_with_internal = Member.objects.create(
prename='Internal',
lastname='Sender',
birth_date=timezone.now().date(),
email='internal@test.com',
gender=DIVERSE
)
# Mock has_internal_email to return True
with mock.patch.object(sender_with_internal, 'has_internal_email', return_value=True):
# Test submit method
result = self.message.submit(sender=sender_with_internal)
# Verify the message was marked as sent
self.message.refresh_from_db()
self.assertTrue(self.message.sent)
self.assertEqual(result, SENT)
@mock.patch('mailer.models.send')
@mock.patch('os.remove')
def test_submit_with_attachments(self, mock_os_remove, mock_send):
# Mock successful email sending
mock_send.return_value = SENT
# Create an attachment with a file
test_file = SimpleUploadedFile("test_file.pdf", b"file_content", content_type="application/pdf")
attachment = Attachment.objects.create(msg=self.message, f=test_file)
# Test submit method
result = self.message.submit()
# Verify the message was marked as sent
self.message.refresh_from_db()
self.assertTrue(self.message.sent)
self.assertEqual(result, SENT)
# Verify file removal was attempted (the path will be the actual file path)
mock_os_remove.assert_called()
# Attachment should be deleted
with self.assertRaises(Attachment.DoesNotExist):
attachment.refresh_from_db()
@mock.patch('mailer.models.send')
def test_submit_with_association_email_enabled(self, mock_send):
"""Test submit method when SEND_FROM_ASSOCIATION_EMAIL is True and sender has association_email"""
mock_send.return_value = SENT
# Mock settings to enable association email sending
with mock.patch.object(settings, 'SEND_FROM_ASSOCIATION_EMAIL', True):
result = self.message.submit(sender=self.sender)
# Check that send was called with sender's association email
self.assertTrue(mock_send.called)
call_args = mock_send.call_args
from_addr = call_args[0][2] # from_addr is the 3rd positional argument
expected_from = f"{self.sender.name} <{self.sender.association_email}>"
self.assertEqual(from_addr, expected_from)
class AttachmentTestCase(BasicMailerTestCase):
def setUp(self):
super().setUp()
self.message = Message.objects.create(
subject='Test Message',
content='Test content'
)
self.attachment = Attachment.objects.create(msg=self.message)
def test_str_with_file(self):
# Simulate a file name
self.attachment.f.name = 'attachments/test_document.pdf'
self.assertEqual(str(self.attachment), 'test_document.pdf')
@skip('Fails with TypeError: __str__ returns a lazy translation object, but must return a string.')
def test_str_without_file(self):
self.assertEqual(str(self.attachment), _('Empty'))