Skip to content

Commit

Permalink
update email notification recipient, refactor tests in pytest style (…
Browse files Browse the repository at this point in the history
…WIP)
  • Loading branch information
vincentporte committed Nov 28, 2024
1 parent 6587d62 commit 948e184
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 100 deletions.
7 changes: 3 additions & 4 deletions lacommunaute/notification/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.urls import reverse
from django.utils import timezone

from config.settings.base import DEFAULT_FROM_EMAIL, NEW_MESSAGES_EMAIL_MAX_PREVIEW, SIB_NEW_MESSAGES_TEMPLATE
from config.settings.base import NEW_MESSAGES_EMAIL_MAX_PREVIEW, SIB_NEW_MESSAGES_TEMPLATE
from lacommunaute.forum_conversation.models import Topic
from lacommunaute.notification.emails import bulk_send_user_to_list, collect_users_from_list, send_email
from lacommunaute.notification.enums import EmailSentTrackKind, NotificationDelay
Expand Down Expand Up @@ -33,10 +33,9 @@ def get_grouped_notifications():
"messages": get_serialized_messages(recipient_notifications[:NEW_MESSAGES_EMAIL_MAX_PREVIEW]),
}
send_email(
to=[{"email": DEFAULT_FROM_EMAIL}],
to=[{"email": recipient}],
params=params,
bcc=[{"email": recipient}],
kind=EmailSentTrackKind.FOLLOWING_REPLIES,
kind=EmailSentTrackKind.BULK_NOTIFS,
template_id=SIB_NEW_MESSAGES_TEMPLATE,
)

Expand Down
158 changes: 62 additions & 96 deletions lacommunaute/notification/tests/tests_tasks.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import json

import httpx
import pytest
import respx
from django.conf import settings
from django.template.defaultfilters import pluralize
from django.test import TestCase
from django.urls import reverse
from faker import Faker

from config.settings.base import (
DEFAULT_FROM_EMAIL,
NEW_MESSAGES_EMAIL_MAX_PREVIEW,
SIB_CONTACT_LIST_URL,
SIB_CONTACTS_URL,
SIB_NEW_MESSAGES_TEMPLATE,
SIB_ONBOARDING_LIST,
SIB_SMTP_URL,
SIB_UNANSWERED_QUESTION_TEMPLATE,
)
from lacommunaute.forum.factories import ForumFactory
from lacommunaute.forum_conversation.factories import TopicFactory
from lacommunaute.notification.enums import EmailSentTrackKind, NotificationDelay
from lacommunaute.forum_conversation.factories import (
AnonymousPostFactory,
PostFactory,
TopicFactory,
)
from lacommunaute.notification.enums import NotificationDelay
from lacommunaute.notification.factories import NotificationFactory
from lacommunaute.notification.models import EmailSentTrack, Notification
from lacommunaute.notification.models import EmailSentTrack
from lacommunaute.notification.tasks import (
add_user_to_list_when_register,
send_messages_notifications,
Expand All @@ -35,108 +37,72 @@
faker = Faker()


class SendMessageNotificationsTestCase(TestCase):
def setUp(self):
super().setUp()
@pytest.fixture(name="mock_respx_post_to_sib_smtp_url")
def mock_respx_post_to_sib_smtp_url_fixture():
with respx.mock:
respx.post(SIB_SMTP_URL).mock(return_value=httpx.Response(200, json={"message": "OK"}))

def get_expected_email_payload(self, notifications):
grouped_notifications = notifications.select_related(
"post", "post__topic", "post__poster"
).group_by_recipient()

assert (
len(grouped_notifications.keys()) == 1
), "get_expected_email_payload requires notifications with only one recipient"

recipient = list(grouped_notifications.keys())[0]
recipient_notifications = grouped_notifications[recipient]
message_count = len(recipient_notifications)
message_count_text = f"{message_count} message{pluralize(message_count, 's')}"

params = {
"email_object": "Bonne nouvelle, ça bouge pour vous dans la communauté !",
"email_thumbnail": (f"Vous avez {message_count_text} à découvrir sur la communauté de l'inclusion"),
"messages": get_serialized_messages(recipient_notifications[:NEW_MESSAGES_EMAIL_MAX_PREVIEW]),
}

return {
"to": [{"email": DEFAULT_FROM_EMAIL}],
"bcc": [{"email": recipient}],
"params": params,
"sender": {"name": "La Communauté", "email": DEFAULT_FROM_EMAIL},
"templateId": SIB_NEW_MESSAGES_TEMPLATE,
}

@respx.mock
def test_send_messages_notifications_asap(self):
topic = TopicFactory(with_post=True)
notification = NotificationFactory(post=topic.first_post, delay=NotificationDelay.ASAP)
yield


class TestSendMessagesNotifications:
def test_generic_payload(self, email, payload):
assert payload["to"] == [{"email": email}]
assert payload["sender"] == {"name": "La Communauté", "email": settings.DEFAULT_FROM_EMAIL}
assert payload["templateId"] == settings.SIB_NEW_MESSAGES_TEMPLATE

def test_grouped_asap_notifications(self, db, mock_respx_post_to_sib_smtp_url):
user = UserFactory()
notifications = [
NotificationFactory(
recipient=user.email, delay=NotificationDelay.ASAP, post=PostFactory(topic=TopicFactory())
),
NotificationFactory(
recipient=user.email, delay=NotificationDelay.ASAP, post=AnonymousPostFactory(topic=TopicFactory())
),
]
NotificationFactory(recipient=user.email, delay=NotificationDelay.DAY)

send_messages_notifications(NotificationDelay.ASAP)

email_sent_track = EmailSentTrack.objects.get()
self.assertEqual(email_sent_track.status_code, 200)
self.assertJSONEqual(email_sent_track.response, {"message": "OK"})
self.assertEqual(
email_sent_track.datas, self.get_expected_email_payload(Notification.objects.filter(id=notification.id))
)

self.assertIsNone(Notification.objects.filter(sent_at__isnull=True).first())
self.assertEqual(Notification.objects.all().values("sent_at").distinct().count(), 1)

@respx.mock
def test_send_messages_notifications_day(self):
topic = TopicFactory(with_post=True)
notification = NotificationFactory(post=topic.first_post, delay=NotificationDelay.DAY)
self.test_generic_payload(user.email, email_sent_track.datas)

for attr, expected in [
("messages", get_serialized_messages(notifications)),
("email_object", "Bonne nouvelle, ça bouge pour vous dans la communauté !"),
("email_thumbnail", "Vous avez 2 messages à découvrir sur la communauté de l'inclusion"),
]:
assert email_sent_track.datas["params"][attr] == expected

def test_grouped_day_notifications(self, db, mock_respx_post_to_sib_smtp_url):
user = UserFactory()
notifications = [
NotificationFactory(
recipient=user.email, delay=NotificationDelay.DAY, post=PostFactory(topic=TopicFactory())
),
NotificationFactory(
recipient=user.email, delay=NotificationDelay.DAY, post=AnonymousPostFactory(topic=TopicFactory())
),
]
NotificationFactory(recipient=user.email, delay=NotificationDelay.ASAP)

send_messages_notifications(NotificationDelay.DAY)

email_sent_track = EmailSentTrack.objects.get()
self.assertEqual(email_sent_track.status_code, 200)
self.assertJSONEqual(email_sent_track.response, {"message": "OK"})
self.assertEqual(
email_sent_track.datas, self.get_expected_email_payload(Notification.objects.filter(id=notification.id))
)

self.assertIsNone(Notification.objects.filter(sent_at__isnull=True).first())
self.assertEqual(Notification.objects.all().values("sent_at").distinct().count(), 1)

@respx.mock
def test_send_messages_notifications_max_messages_preview(self):
topic = TopicFactory(with_post=True)
notif_count_to_generate = NEW_MESSAGES_EMAIL_MAX_PREVIEW + 1

NotificationFactory.create_batch(
notif_count_to_generate,
recipient="[email protected]",
delay=NotificationDelay.ASAP,
kind=EmailSentTrackKind.FIRST_REPLY,
post=topic.first_post,
)

send_messages_notifications(NotificationDelay.ASAP)

email_sent_track = EmailSentTrack.objects.get()
self.assertEqual(len(email_sent_track.datas["params"]["messages"]), NEW_MESSAGES_EMAIL_MAX_PREVIEW)
self.assertEqual(
email_sent_track.datas["params"]["email_thumbnail"],
(f"Vous avez {notif_count_to_generate } messages à découvrir sur la communauté de l'inclusion"),
)

@respx.mock
def test_send_messages_notifications_num_queries(self):
expected_queries = 2

NotificationFactory(delay=NotificationDelay.ASAP)
self.test_generic_payload(user.email, email_sent_track.datas)

with self.assertNumQueries(expected_queries):
send_messages_notifications(NotificationDelay.ASAP)
for attr, expected in [
("messages", get_serialized_messages(notifications)),
("email_object", "Bonne nouvelle, ça bouge pour vous dans la communauté !"),
("email_thumbnail", "Vous avez 2 messages à découvrir sur la communauté de l'inclusion"),
]:
assert email_sent_track.datas["params"][attr] == expected

NotificationFactory.create_batch(10, delay=NotificationDelay.ASAP)
def test_grouped_max_messages_preview(self, db, mock_respx_post_to_sib_smtp_url):
pass

with self.assertNumQueries(expected_queries):
send_messages_notifications(NotificationDelay.ASAP)
def test_num_queries(self, db, mock_respx_post_to_sib_smtp_url):
pass


class AddUserToListWhenRegister(TestCase):
Expand Down

0 comments on commit 948e184

Please sign in to comment.