HH/apps/notifications/tests_email.py
2026-07-12 11:18:20 +03:00

130 lines
5.4 KiB
Python

"""
Tests for the email reminder template consistency fixes:
- Part D: NotificationService.send_email auto-wraps plain-text in branded template
- Part A: dept-champion notification uses email= (not recipient=) kwarg
- Part B/C: branded reminder templates render with the expected context
"""
from unittest.mock import patch
from django.template.loader import render_to_string
from django.test import TestCase
from apps.notifications.services import NotificationService
class AutoWrapBrandedTemplateTests(TestCase):
"""Part D — plain-text messages are auto-wrapped in the branded template."""
@patch("apps.notifications.services.send_mail")
def test_plain_text_gets_branded_html(self, mock_send_mail):
NotificationService.send_email(
email="patient@example.com",
subject="Test Subject",
message="Line one.\n\nLine two.\nLine three.",
)
# send_mail was called with an html_message
_, kwargs = mock_send_mail.call_args
self.assertIsNotNone(kwargs.get("html_message"))
html = kwargs["html_message"]
# The branded template contributes these structural markers
self.assertIn("email-container", html) # the 600px card from base_email_template
self.assertIn("<!DOCTYPE", html) # full HTML document shell
# Plain-text content was converted to HTML paragraphs
self.assertIn("Line one.", html)
self.assertIn("<br>", html) # single newline -> <br>
self.assertIn("<p>", html) # double newline -> new paragraph
@patch("apps.notifications.services.send_mail")
def test_explicit_html_message_is_not_overwritten(self, mock_send_mail):
"""Callers that already provide html_message keep it as-is (no double-wrapping)."""
custom_html = "<div>My custom layout</div>"
NotificationService.send_email(
email="patient@example.com",
subject="Test",
message="Plain text fallback",
html_message=custom_html,
)
_, kwargs = mock_send_mail.call_args
self.assertEqual(kwargs["html_message"], custom_html)
class DeptChampionNotificationKwargTests(TestCase):
"""Part A — the recipient= bug is fixed (send_email uses email= kwarg).
We verify indirectly: send_email no longer receives an unexpected 'recipient'
kwarg, which used to cause a TypeError swallowed by try/except.
"""
@patch("apps.notifications.services.send_mail")
def test_send_email_signature_rejects_recipient_kwarg(self, mock_mail):
"""The send_email method must not accept 'recipient' as a kwarg (the bug).
Python validates kwargs at call time, so TypeError fires before the
body runs — we must NOT mock send_email itself.
"""
with self.assertRaises(TypeError):
NotificationService.send_email(
recipient="someone@example.com", # wrong kwarg — should TypeError
subject="Test",
message="Test",
)
class BrandedReminderTemplateTests(TestCase):
"""Parts B & C — the reminder templates extend the base and render branded HTML."""
def _assert_branded(self, html):
"""Structural markers contributed by base_email_template.html."""
self.assertIn("<!DOCTYPE", html)
self.assertIn("email-container", html)
def test_inquiry_dept_response_reminder_renders(self):
html = render_to_string("emails/inquiry_dept_response_reminder.html", {
"inquiry": type("Obj", (), {"reference_number": "INQ-001", "subject": "Test"})(),
"department_name": "Lab",
"hours_remaining": 12,
"sla_due_at": "2026-07-15T10:00:00",
"inquiry_url": "https://example.com/inquiries/1/",
})
self._assert_branded(html)
self.assertIn("INQ-001", html)
self.assertIn("Lab", html)
def test_observation_dept_response_reminder_renders(self):
html = render_to_string("emails/observation_dept_response_reminder.html", {
"observation": type("Obj", (), {"tracking_code": "OBS-001", "title": "Spill"})(),
"department_name": "Lab",
"hours_remaining": 8,
"sla_due_at": "2026-07-15T10:00:00",
"observation_url": "https://example.com/observations/1/",
})
self._assert_branded(html)
self.assertIn("OBS-001", html)
def test_inquiry_sla_reminder_renders(self):
html = render_to_string("emails/inquiry_sla_reminder.html", {
"inquiry": type("Obj", (), {
"reference_number": "INQ-002",
"subject": "Billing",
"due_at": "2026-07-15T10:00:00",
})(),
"hours_remaining": 24,
"inquiry_url": "https://example.com/inquiries/2/",
})
self._assert_branded(html)
self.assertIn("INQ-002", html)
def test_inquiry_sla_second_reminder_renders_urgent(self):
html = render_to_string("emails/inquiry_sla_second_reminder.html", {
"inquiry": type("Obj", (), {
"reference_number": "INQ-003",
"subject": "Billing",
"due_at": "2026-07-15T10:00:00",
})(),
"hours_remaining": 2,
"inquiry_url": "https://example.com/inquiries/3/",
})
self._assert_branded(html)
self.assertIn("URGENT", html)
self.assertIn("#dc2626", html) # red accent for urgency