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.
351 lines
14 KiB
Python
351 lines
14 KiB
Python
import json
|
|
from http import HTTPStatus
|
|
from unittest.mock import patch
|
|
|
|
from django.conf import settings
|
|
from django.contrib.admin.sites import AdminSite
|
|
from django.contrib.auth.models import User
|
|
from django.contrib.messages import get_messages
|
|
from django.contrib.messages.middleware import MessageMiddleware
|
|
from django.contrib.messages.storage.fallback import FallbackStorage
|
|
from django.contrib.sessions.middleware import SessionMiddleware
|
|
from django.http import HttpResponseRedirect
|
|
from django.test import RequestFactory
|
|
from django.test import TestCase
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext_lazy as _
|
|
from members.models import DIVERSE
|
|
from members.models import Group
|
|
from members.models import Member
|
|
from members.tests.utils import create_custom_user
|
|
|
|
from ..admin import MessageAdmin
|
|
from ..admin import submit_message
|
|
from ..mailutils import NOT_SENT
|
|
from ..mailutils import PARTLY_SENT
|
|
from ..mailutils import SENT
|
|
from ..models import EmailAddress
|
|
from ..models import Message
|
|
|
|
|
|
class AdminTestCase(TestCase):
|
|
def setUp(self, model, admin):
|
|
self.factory = RequestFactory()
|
|
self.model = model
|
|
if model is not None and admin is not None:
|
|
self.admin = admin(model, AdminSite())
|
|
User.objects.create_superuser(username="superuser", password="secret")
|
|
create_custom_user("standard", ["Standard"], "Paul", "Wulter")
|
|
create_custom_user("trainer", ["Standard", "Trainings"], "Lise", "Lotte")
|
|
|
|
def _add_middleware(self, request):
|
|
"""Add required middleware to request."""
|
|
# Session middleware
|
|
middleware = SessionMiddleware(lambda x: None)
|
|
middleware.process_request(request)
|
|
request.session.save()
|
|
|
|
# Messages middleware
|
|
messages_middleware = MessageMiddleware(lambda x: None)
|
|
messages_middleware.process_request(request)
|
|
request._messages = FallbackStorage(request)
|
|
|
|
|
|
class MessageAdminTestCase(AdminTestCase):
|
|
def setUp(self):
|
|
super().setUp(Message, MessageAdmin)
|
|
|
|
# Create test data
|
|
self.group = Group.objects.create(name="Test Group")
|
|
self.email_address = EmailAddress.objects.create(name="testmail")
|
|
|
|
# Create test member with internal email
|
|
self.internal_member = Member.objects.create(
|
|
prename="Internal",
|
|
lastname="User",
|
|
birth_date=timezone.now().date(),
|
|
email=f"internal@{settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER[0]}",
|
|
gender=DIVERSE,
|
|
)
|
|
|
|
# Create test member with external email
|
|
self.external_member = Member.objects.create(
|
|
prename="External",
|
|
lastname="User",
|
|
birth_date=timezone.now().date(),
|
|
email="external@example.com",
|
|
gender=DIVERSE,
|
|
)
|
|
|
|
# Create users for testing
|
|
self.user_with_internal_member = User.objects.create_user(
|
|
username="testuser", password="secret"
|
|
)
|
|
self.user_with_internal_member.member = self.internal_member
|
|
self.user_with_internal_member.save()
|
|
|
|
self.user_with_external_member = User.objects.create_user(
|
|
username="external_user", password="secret"
|
|
)
|
|
self.user_with_external_member.member = self.external_member
|
|
self.user_with_external_member.save()
|
|
|
|
self.user_without_member = User.objects.create_user(
|
|
username="no_member_user", password="secret"
|
|
)
|
|
|
|
# Create test message
|
|
self.message = Message.objects.create(subject="Test Message", content="Test content")
|
|
self.message.to_groups.add(self.group)
|
|
self.message.to_members.add(self.internal_member)
|
|
|
|
def test_save_model_sets_created_by(self):
|
|
"""Test that save_model sets created_by when creating new message."""
|
|
request = self.factory.post("/admin/mailer/message/add/")
|
|
request.user = self.user_with_internal_member
|
|
|
|
# Create new message
|
|
new_message = Message(subject="New Message", content="New content")
|
|
|
|
# Test save_model for new object (change=False)
|
|
self.admin.save_model(request, new_message, None, change=False)
|
|
|
|
self.assertEqual(new_message.created_by, self.internal_member)
|
|
|
|
def test_save_model_does_not_change_created_by_on_update(self):
|
|
"""Test that save_model doesn't change created_by when updating."""
|
|
request = self.factory.post("/admin/mailer/message/1/change/")
|
|
request.user = self.user_with_internal_member
|
|
|
|
# Message already has created_by set
|
|
self.message.created_by = self.external_member
|
|
|
|
# Test save_model for existing object (change=True)
|
|
self.admin.save_model(request, self.message, None, change=True)
|
|
|
|
self.assertEqual(self.message.created_by, self.external_member)
|
|
|
|
@patch("mailer.models.Message.submit")
|
|
def test_submit_message_success(self, mock_submit):
|
|
"""Test submit_message with successful send."""
|
|
mock_submit.return_value = SENT
|
|
|
|
request = self.factory.post("/admin/mailer/message/")
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
# Test submit_message
|
|
submit_message(self.message, request)
|
|
|
|
# Verify submit was called with correct sender
|
|
mock_submit.assert_called_once_with(self.internal_member)
|
|
|
|
# Check success message
|
|
messages_list = list(get_messages(request))
|
|
self.assertEqual(len(messages_list), 1)
|
|
self.assertIn(str(_("Successfully sent message")), str(messages_list[0]))
|
|
|
|
@patch("mailer.models.Message.submit")
|
|
def test_submit_message_not_sent(self, mock_submit):
|
|
"""Test submit_message when sending fails."""
|
|
mock_submit.return_value = NOT_SENT
|
|
|
|
request = self.factory.post("/admin/mailer/message/")
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
# Test submit_message
|
|
submit_message(self.message, request)
|
|
|
|
# Check error message
|
|
messages_list = list(get_messages(request))
|
|
self.assertEqual(len(messages_list), 1)
|
|
self.assertIn(str(_("Failed to send message")), str(messages_list[0]))
|
|
|
|
@patch("mailer.models.Message.submit")
|
|
def test_submit_message_partly_sent(self, mock_submit):
|
|
"""Test submit_message when partially sent."""
|
|
mock_submit.return_value = PARTLY_SENT
|
|
|
|
request = self.factory.post("/admin/mailer/message/")
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
# Test submit_message
|
|
submit_message(self.message, request)
|
|
|
|
# Check warning message
|
|
messages_list = list(get_messages(request))
|
|
self.assertEqual(len(messages_list), 1)
|
|
self.assertIn(str(_("Failed to send some messages")), str(messages_list[0]))
|
|
|
|
def test_submit_message_user_has_no_member(self):
|
|
"""Test submit_message when user has no associated member."""
|
|
request = self.factory.post("/admin/mailer/message/")
|
|
request.user = self.user_without_member
|
|
self._add_middleware(request)
|
|
|
|
# Test submit_message
|
|
submit_message(self.message, request)
|
|
|
|
# Check error message
|
|
messages_list = list(get_messages(request))
|
|
self.assertEqual(len(messages_list), 1)
|
|
self.assertIn(
|
|
str(
|
|
_(
|
|
"Your account is not connected to a member. Please contact your system administrator."
|
|
)
|
|
),
|
|
str(messages_list[0]),
|
|
)
|
|
|
|
def test_submit_message_user_has_external_email(self):
|
|
"""Test submit_message when user has external email."""
|
|
request = self.factory.post("/admin/mailer/message/")
|
|
request.user = self.user_with_external_member
|
|
self._add_middleware(request)
|
|
|
|
# Test submit_message
|
|
submit_message(self.message, request)
|
|
|
|
# Check error message
|
|
messages_list = list(get_messages(request))
|
|
self.assertEqual(len(messages_list), 1)
|
|
self.assertIn(
|
|
str(
|
|
_(
|
|
"Your email address is not an internal email address. Please use an email address with one of the following domains: %(domains)s."
|
|
)
|
|
% {"domains": ", ".join(settings.ALLOWED_EMAIL_DOMAINS_FOR_INVITE_AS_USER)}
|
|
),
|
|
str(messages_list[0]),
|
|
)
|
|
|
|
@patch("mailer.admin.submit_message")
|
|
def test_send_message_action_confirmed(self, mock_submit_message):
|
|
"""Test send_message action when confirmed."""
|
|
request = self.factory.post("/admin/mailer/message/", {"confirmed": "true"})
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
queryset = Message.objects.filter(pk=self.message.pk)
|
|
|
|
# Test send_message action
|
|
result = self.admin.send_message(request, queryset)
|
|
|
|
# Verify submit_message was called for each message
|
|
mock_submit_message.assert_called_once_with(self.message, request)
|
|
|
|
# Should return None when confirmed (no template response)
|
|
self.assertIsNone(result)
|
|
|
|
def test_send_message_action_not_confirmed(self):
|
|
"""Test send_message action when not confirmed (shows confirmation page)."""
|
|
request = self.factory.post("/admin/mailer/message/")
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
queryset = Message.objects.filter(pk=self.message.pk)
|
|
|
|
# Test send_message action
|
|
result = self.admin.send_message(request, queryset)
|
|
|
|
# Should return HttpResponse with confirmation template
|
|
self.assertIsNotNone(result)
|
|
self.assertEqual(result.status_code, HTTPStatus.OK)
|
|
|
|
@patch("mailer.admin.submit_message")
|
|
def test_response_change_with_send(self, mock_submit_message):
|
|
"""Test response_change when _send is in POST."""
|
|
request = self.factory.post("/admin/mailer/message/1/change/", {"_send": "Send"})
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
# Test response_change
|
|
with patch.object(self.admin.__class__.__bases__[2], "response_change") as mock_super:
|
|
mock_super.return_value = HttpResponseRedirect("/admin/")
|
|
self.admin.response_change(request, self.message)
|
|
|
|
# Verify submit_message was called
|
|
mock_submit_message.assert_called_once_with(self.message, request)
|
|
|
|
# Verify super method was called
|
|
mock_super.assert_called_once()
|
|
|
|
@patch("mailer.admin.submit_message")
|
|
def test_response_change_without_send(self, mock_submit_message):
|
|
"""Test response_change when _send is not in POST."""
|
|
request = self.factory.post("/admin/mailer/message/1/change/", {"_save": "Save"})
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
# Test response_change
|
|
with patch.object(self.admin.__class__.__bases__[2], "response_change") as mock_super:
|
|
mock_super.return_value = HttpResponseRedirect("/admin/")
|
|
self.admin.response_change(request, self.message)
|
|
|
|
# Verify submit_message was NOT called
|
|
mock_submit_message.assert_not_called()
|
|
|
|
# Verify super method was called
|
|
mock_super.assert_called_once()
|
|
|
|
@patch("mailer.admin.submit_message")
|
|
def test_response_add_with_send(self, mock_submit_message):
|
|
"""Test response_add when _send is in POST."""
|
|
request = self.factory.post("/admin/mailer/message/add/", {"_send": "Send"})
|
|
request.user = self.user_with_internal_member
|
|
self._add_middleware(request)
|
|
|
|
# Test response_add
|
|
with patch.object(self.admin.__class__.__bases__[2], "response_add") as mock_super:
|
|
mock_super.return_value = HttpResponseRedirect("/admin/")
|
|
self.admin.response_add(request, self.message)
|
|
|
|
# Verify submit_message was called
|
|
mock_submit_message.assert_called_once_with(self.message, request)
|
|
|
|
# Verify super method was called
|
|
mock_super.assert_called_once()
|
|
|
|
def test_get_form_with_members_param(self):
|
|
"""Test get_form when members parameter is provided."""
|
|
# Create request with members parameter
|
|
members_ids = [self.internal_member.pk, self.external_member.pk]
|
|
request = self.factory.get(f"/admin/mailer/message/add/?members={json.dumps(members_ids)}")
|
|
request.user = self.user_with_internal_member
|
|
|
|
# Test get_form
|
|
form_class = self.admin.get_form(request)
|
|
form = form_class()
|
|
|
|
# Verify initial members are set
|
|
self.assertEqual(
|
|
list(form.fields["to_members"].initial), [self.internal_member, self.external_member]
|
|
)
|
|
|
|
def test_get_form_with_invalid_members_param(self):
|
|
"""Test get_form when members parameter is not a list."""
|
|
# Create request with invalid members parameter
|
|
request = self.factory.get('/admin/mailer/message/add/?members="not_a_list"')
|
|
request.user = self.user_with_internal_member
|
|
|
|
# Test get_form
|
|
form_class = self.admin.get_form(request)
|
|
|
|
# Should return form without modification
|
|
self.assertIsNotNone(form_class)
|
|
|
|
def test_get_form_without_members_param(self):
|
|
"""Test get_form when no members parameter is provided."""
|
|
# Create request without members parameter
|
|
request = self.factory.get("/admin/mailer/message/add/")
|
|
request.user = self.user_with_internal_member
|
|
|
|
# Test get_form
|
|
form_class = self.admin.get_form(request)
|
|
|
|
# Should return form without modification
|
|
self.assertIsNotNone(form_class)
|