Skip to content

Commit 8dc9a76

Browse files
committed
test: Add unit tests for mail.py
1 parent 8cc5fd5 commit 8dc9a76

File tree

3 files changed

+155
-82
lines changed

3 files changed

+155
-82
lines changed

mail_test.py

Lines changed: 0 additions & 81 deletions
This file was deleted.

metabrainz/mail_test.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
from unittest import mock
2+
import requests
3+
import requests_mock
4+
import orjson
5+
6+
from flask import current_app
7+
from metabrainz.testing import FlaskTestCase
8+
from metabrainz.mail import NotificationSender, FAILED_MAIL_HASH_KEY
9+
10+
11+
class NotificationSenderTest(FlaskTestCase):
12+
def setUp(self):
13+
super(NotificationSenderTest, self).setUp()
14+
self.notifications = [
15+
{
16+
"musicbrainz_row_id": 3,
17+
"project": "metabrainz",
18+
"recipient": "[email protected]",
19+
"sent_from": "[email protected]",
20+
"reply_to": "[email protected]",
21+
"send_email": True,
22+
"subject": "test",
23+
"body": "test-123",
24+
"important": False,
25+
"expire_age": 30,
26+
"email_id": "c7d7b431-7130-4a3c-ad8a-17cdd5ebdf2d",
27+
"id": 6,
28+
},
29+
{
30+
"musicbrainz_row_id": 1,
31+
"project": "musicbrainz",
32+
"recipient": "[email protected]",
33+
"sent_from": "[email protected]",
34+
"reply_to": "[email protected]",
35+
"send_email": True,
36+
"template_id": "verify-email",
37+
"template_params": {"reason": "verify"},
38+
"important": True,
39+
"expire_age": 30,
40+
"email_id": "c512e637-21ff-45b1-a58a-03412224b48b",
41+
"id": 4,
42+
},
43+
]
44+
self.service = NotificationSender(self.notifications)
45+
46+
@requests_mock.Mocker()
47+
def test_send_html_mail(self, mock_request):
48+
single_mail_endpoint = current_app.config["MB_MAIL_SERVER_URI"] + "/send_single"
49+
mock_request.post(single_mail_endpoint, status_code=200)
50+
expected_payload = {
51+
"from": self.notifications[1]["sent_from"],
52+
"to": self.notifications[1]["recipient"],
53+
"template_id": self.notifications[1]["template_id"],
54+
"params": self.notifications[1]["template_params"],
55+
"language": None,
56+
"in_reply_to": [],
57+
"sender": None,
58+
"references": [],
59+
"reply_to": None,
60+
"message_id": self.notifications[1]["email_id"],
61+
}
62+
63+
self.service.send_html_mail(
64+
from_addr=self.notifications[1]["sent_from"],
65+
recipient=self.notifications[1]["recipient"],
66+
template_id=self.notifications[1]["template_id"],
67+
template_params=self.notifications[1]["template_params"],
68+
message_id=self.notifications[1]["email_id"]
69+
)
70+
71+
self.assertEqual(mock_request.last_request.json(), expected_payload)
72+
73+
# Error on the mb-mail server side.
74+
mock_request.post(single_mail_endpoint, status_code=500)
75+
76+
with self.assertRaises(requests.exceptions.HTTPError) as err:
77+
self.service.send_html_mail(
78+
from_addr=self.notifications[1]["sent_from"],
79+
recipient=self.notifications[1]["recipient"],
80+
template_id=self.notifications[1]["template_id"],
81+
template_params=self.notifications[1]["template_params"],
82+
message_id=self.notifications[1]["email_id"]
83+
)
84+
85+
self.assertEqual(err.exception.response.status_code, 500)
86+
87+
@mock.patch("metabrainz.mail.cache")
88+
@mock.patch("metabrainz.mail.NotificationSender.send_html_mail")
89+
@mock.patch("metabrainz.mail.send_mail")
90+
def test_send_notifications(self, mock_send_mail, mock_send_html_mail, mock_cache):
91+
mock_send_mail.return_value = None
92+
mock_send_html_mail.return_value = None
93+
94+
self.service._send_notifications(self.notifications)
95+
96+
# Plain text mail notification.
97+
mock_send_mail.assert_called_once_with(
98+
subject=self.notifications[0]["subject"],
99+
text=self.notifications[0]["body"],
100+
recipients=[self.notifications[0]["recipient"]],
101+
from_addr=self.notifications[0]["sent_from"],
102+
)
103+
# HTML mail notification.
104+
mock_send_html_mail.assert_called_once_with(
105+
from_addr=self.notifications[1]["sent_from"],
106+
recipient=self.notifications[1]["recipient"],
107+
template_id=self.notifications[1]["template_id"],
108+
template_params=self.notifications[1]["template_params"],
109+
message_id=self.notifications[1]["email_id"]
110+
)
111+
112+
# MB-mail failure
113+
mock_send_html_mail.side_effect = Exception()
114+
mock_cache.return_value = 1
115+
116+
self.service._send_notifications(self.notifications)
117+
118+
args, _ = mock_cache.hset.call_args
119+
self.assertEqual(args[0], FAILED_MAIL_HASH_KEY)
120+
self.assertIsInstance(args[1], str)
121+
self.assertEqual(args[2], orjson.dumps(self.notifications[1]))
122+
123+
124+
125+
@mock.patch("metabrainz.mail.NotificationSender._send_notifications")
126+
@mock.patch("metabrainz.mail.mark_notifications_sent")
127+
@mock.patch("metabrainz.mail.filter_non_digest_notifications")
128+
def test_send_immediate_notifications(self, mock_filter, mock_mark_sent, mock_send):
129+
mock_filter.return_value = []
130+
mock_mark_sent.return_value = None
131+
mock_send.return_value = None
132+
133+
self.service.send_immediate_notifications()
134+
135+
# Non-important notification
136+
mock_filter.assert_called_once_with([self.notifications[0]])
137+
# Immediate notification
138+
mock_send.assert_called_once_with([self.notifications[1]])
139+
mock_mark_sent.has_called_with([self.notifications[1]])
140+
141+
@mock.patch("metabrainz.mail.mark_notifications_sent")
142+
@mock.patch("metabrainz.mail.get_digest_notifications")
143+
@mock.patch("metabrainz.mail.NotificationSender._send_notifications")
144+
def test_send_digest_notifications(self, mock_send, mock_get, mock_mark):
145+
mock_send.return_value = None
146+
mock_get.return_value = [self.notifications[0]]
147+
mock_mark.return_value = None
148+
149+
self.service.send_digest_notifications()
150+
151+
mock_get.assert_called_once()
152+
mock_send.assert_called_once_with([self.notifications[0]])
153+
mock_mark.assert_called_once_with([self.notifications[0]])
154+

metabrainz/notifications/views_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ def test_remove_notifications(self, mock_requests, mock_delete):
166166
self.assertEqual(res.json['error'], 'Cannot delete notifications right now.')
167167

168168
@requests_mock.Mocker()
169-
@mock.patch('metabrainz.notifications.views.insert_notifications')
170169
@mock.patch('metabrainz.mail.NotificationSender.send_immediate_notifications')
170+
@mock.patch('metabrainz.notifications.views.insert_notifications')
171171
def test_send_notifications(self, mock_requests, mock_insert, mock_mail):
172172
test_data = [
173173
{ "id": 102,

0 commit comments

Comments
 (0)