Coverage for tests/utils/test_email.py: 100%
52 statements
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-08 22:07 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-08 22:07 +0000
1import unittest
2from unittest.mock import patch, MagicMock
3from webapp.utils.emailer import Emailer, SMTPConfig, EmailerError
6class TestEmailer(unittest.TestCase):
7 def setUp(self):
8 self.smtp_config = SMTPConfig(
9 host="smtp.test.com",
10 port=587,
11 username="testuser@canonical.com",
12 password="testpass",
13 domain="example.com",
14 )
15 self.emailer = Emailer(self.smtp_config)
17 @patch("smtplib.SMTP")
18 def test_send_email_success(self, mock_smtp):
19 subject = "Test subject"
20 body = "Test body"
21 to_email = "recipient@test.com"
23 mock_server = MagicMock()
24 mock_smtp.return_value.__enter__.return_value = mock_server
26 self.emailer.send_email(subject, body, to_email)
28 mock_smtp.assert_called_once_with(
29 self.smtp_config.host, self.smtp_config.port
30 )
31 mock_server.starttls.assert_called_once()
32 mock_server.login.assert_called_with(
33 self.smtp_config.username, self.smtp_config.password
34 )
36 @patch("smtplib.SMTP")
37 def test_send_email_template_success(self, mock_smtp):
38 with patch("webapp.utils.emailer.render_template") as mock_render:
39 mock_render.return_value = "<h1>Hello</h1>"
40 mock_server = MagicMock()
41 mock_smtp.return_value.__enter__.return_value = mock_server
43 self.emailer.send_email_template(
44 to_email="recipient@test.com",
45 subject="Test Template",
46 template_path="template.html",
47 context={"name": "Test"},
48 )
50 mock_render.assert_called_once_with(
51 "template.html", **{"name": "Test"}
52 )
53 mock_server.send_message.assert_called()
55 def test_validate_config_missing_fields(self):
56 incomplete_config = SMTPConfig(
57 host=None,
58 port=587,
59 username=None,
60 password=None,
61 domain="example.com",
62 )
63 emailer = Emailer(incomplete_config)
64 self.assertFalse(emailer.is_configured)
66 @patch("smtplib.SMTP")
67 def test_send_raises_smtp_exception(self, mock_smtp):
68 mock_smtp.side_effect = Exception("SMTP failure")
69 subject = "Test"
70 body = "Body"
71 to_email = "to@example.com"
73 with self.assertRaises(EmailerError):
74 self.emailer._send(subject, body, to_email)
76 def test_create_message_addresses(self):
77 message = self.emailer._create_message(
78 subject="Subject",
79 body="Body",
80 to_email=["a@test.com", "b@test.com"],
81 )
82 self.assertIn("From", message)
83 self.assertIn("To", message)
84 self.assertEqual(message["From"], "testuser@canonical.com")
86 emailer2 = Emailer(
87 SMTPConfig(
88 host="host",
89 port=587,
90 username="simpleuser",
91 password="pass",
92 domain="example.com",
93 )
94 )
95 message2 = emailer2._create_message(
96 "Sub", "Body", "someone@example.com"
97 )
98 self.assertTrue(message2["From"].startswith("noreply+"))
100 def test_send_email_no_configuration(self):
101 no_config = SMTPConfig(
102 host=None,
103 port=587,
104 username=None,
105 password=None,
106 domain="example.com",
107 )
108 emailer = Emailer(no_config)
109 emailer.send_email("subject", "body", "to@example.com")
110 self.assertFalse(emailer.is_configured)