Skip to content

Commit 974e4ff

Browse files
committed
Adds tests to verify that notifications are bundled in the weekly digests
1 parent bac2ce4 commit 974e4ff

File tree

3 files changed

+67
-22
lines changed

3 files changed

+67
-22
lines changed

django_nyt/management/commands/notifymail.py

+11-15
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,9 @@ def _send_with_retry(
241241
return
242242

243243
while True:
244+
notification_ids = [n.id for n in notifications]
244245
try:
245-
self.logger.info(
246-
"Sending to notification ids {notification_ids}".format(
247-
notification_ids=", ".join(str(n.id) for n in notifications)
248-
)
249-
)
246+
self.logger.info(f"Sending to notification ids {notification_ids}")
250247
self._render_and_send(
251248
template_name, subject_template_name, context, connection
252249
)
@@ -255,6 +252,9 @@ def _send_with_retry(
255252
n.save()
256253
n.subscription.last_sent = timezone.now()
257254
n.subscription.save()
255+
models.Subscription.objects.filter(
256+
notification__id__in=notification_ids
257+
).update(last_sent=timezone.now())
258258
break
259259
except smtplib.SMTPSenderRefused:
260260
self.logger.error(
@@ -372,18 +372,14 @@ def send_mails( # noqa: max-complexity=12
372372
(template_name, subject_template_name), []
373373
)
374374

375-
# If there is an interval, we use the threshold.
376-
if setting.interval:
377-
filter_kwargs = {"created__lte": threshold}
378-
else:
379-
filter_kwargs = {}
375+
# We assume that if we are sending a digest and we've missed sending it, we can
376+
# still just summarize ALL notifications that haven't been emailed.
377+
# Always, no matter what.
378+
# This also means that if we are sending out emails every 5 minutes, and several
379+
# notifications have been triggered meanwhile, they'll go into the same email.
380380
emails_per_template[(template_name, subject_template_name)] += list(
381-
subscription.notification_set.filter(
382-
is_emailed=False, **filter_kwargs
383-
),
381+
subscription.notification_set.filter(is_emailed=False),
384382
)
385-
print("found:")
386-
print(emails_per_template[(template_name, subject_template_name)])
387383

388384
# Send the prepared template names, subjects and context to the user
389385
for (

docs/release_notes.rst

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Release Notes
1717
* Documentation reorganized with Diataxis structure and more how-to guides have been added. (Benjamin Balder Bach)
1818
* New shortcut function ``utils.unsubscribe()``. #137 (Benjamin Balder Bach)
1919
* Better logging for ``notifymail`` management command #141 (Benjamin Balder Bach)
20+
* Added fields ``created`` and ``modified`` on models ``Settings`` and ``Subscription``.
2021

2122
**Changed**
2223

@@ -28,6 +29,7 @@ Release Notes
2829
* Improvements to docstrings of main methods ``notify()`` and ``subscribe()`` #129 (Benjamin Balder Bach)
2930
* Return value of ``notify()`` was changed - it no longer returns an `int` (number of created notifications), instead it returns a list of created notifications.
3031
This is very useful, see :doc:`howto/object_relations` #134 (Benjamin Balder Bach)
32+
* The field ``Notification.url`` now accepts 2,000 characters rather than 200.
3133

3234
**Fixed**
3335

tests/core/test_email.py

+54-7
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,19 @@ def test_notify_weekly_nothing_sent_first_week(self):
250250
assert len(mail.outbox) == 1
251251
assert "weekly" in mail.outbox[0].subject
252252

253+
# Ensure nothing is sent by re-running the command
254+
mail.outbox = []
255+
call_command(
256+
"notifymail",
257+
"--cron",
258+
"--no-sys-exit",
259+
now=timezone.now() + timedelta(minutes=WEEKLY + 1),
260+
)
261+
assert len(mail.outbox) == 0
262+
253263
# Now ensure that we receive an instant notification regardless of the previous weekly notification
254264
utils.subscribe(self.user1_settings, self.TEST_KEY, send_emails=True)
255-
notifications = utils.notify("This is a second test", self.TEST_KEY)
256-
print("hello")
257-
print(notifications[0].subscription.notification_type)
258-
print(notifications[0].subscription.settings.id)
259-
print(self.user1_settings.id)
265+
utils.notify("This is a second test", self.TEST_KEY)
260266
assert (
261267
models.Notification.objects.filter(
262268
subscription__notification_type__key=self.TEST_KEY,
@@ -268,5 +274,46 @@ def test_notify_weekly_nothing_sent_first_week(self):
268274
call_command("notifymail", "--cron", "--no-sys-exit")
269275
assert len(mail.outbox) == 1
270276

271-
# Now fast-forward and ensure that the notification is found in the weekly digest
272-
...
277+
# Unsubscribe the instant notification
278+
mail.outbox = []
279+
utils.unsubscribe(self.TEST_KEY, settings=self.user1_settings)
280+
281+
# Now create 2 notifications and test that it'll get sent when running again a week later
282+
notifications = utils.notify("Test is a third test", self.TEST_KEY)
283+
notifications += utils.notify("Test is a forth test", self.TEST_KEY)
284+
285+
call_command("notifymail", "--cron", "--no-sys-exit")
286+
287+
# Ensure nothing is sent, a week hasn't passed
288+
assert len(mail.outbox) == 0
289+
290+
# Emulate that it was sent ½ week ago and try again
291+
user1_weekly_setting.subscription_set.all().update(
292+
last_sent=timezone.now() - timedelta(minutes=WEEKLY * 0.5)
293+
)
294+
295+
call_command("notifymail", "--cron", "--no-sys-exit")
296+
297+
# Ensure nothing is sent, a week hasn't passed
298+
assert len(mail.outbox) == 0
299+
300+
# Emulate that it was sent 1 week ago and try again
301+
threshold = timezone.now() - timedelta(
302+
minutes=user1_weekly_setting.interval * 1 + 1
303+
)
304+
user1_weekly_setting.subscription_set.all().update(last_sent=threshold)
305+
306+
assert user1_weekly_setting.subscription_set.all().exists()
307+
assert models.Notification.objects.filter(
308+
subscription__settings=user1_weekly_setting,
309+
is_emailed=False,
310+
subscription__latest__is_emailed=False,
311+
subscription__last_sent__lte=threshold,
312+
).exists()
313+
314+
call_command("notifymail", "--cron", "--no-sys-exit")
315+
316+
# Ensure that exactly 1 digest is sent
317+
assert len(mail.outbox) == 1
318+
assert "weekly" in mail.outbox[0].subject
319+
assert all(n.message in mail.outbox[0].body for n in notifications)

0 commit comments

Comments
 (0)