Skip to content

Commit

Permalink
let post_create signal generate notification on topic creation, refac…
Browse files Browse the repository at this point in the history
…tor tests in pytest style
  • Loading branch information
vincentporte committed Nov 28, 2024
1 parent 5a13f7f commit 27cfd2a
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 46 deletions.
2 changes: 1 addition & 1 deletion lacommunaute/forum_conversation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def is_first_reply(self):
def save(self, *args, **kwargs):
created = not self.pk
super().save(*args, **kwargs)
if created and (self.is_topic_tail and not self.is_topic_head):
if created:
post_create.send(sender=self.__class__, instance=self)


Expand Down
7 changes: 7 additions & 0 deletions lacommunaute/notification/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ class EmailSentTrackKind(models.TextChoices):
class NotificationDelay(models.TextChoices):
ASAP = "asap", _("As soon as possible")
DAY = "day", _("The following day")


delay_of_notifications = {
EmailSentTrackKind.PENDING_TOPIC: NotificationDelay.DAY,
EmailSentTrackKind.FIRST_REPLY: NotificationDelay.ASAP,
EmailSentTrackKind.FOLLOWING_REPLIES: NotificationDelay.DAY,
}
12 changes: 9 additions & 3 deletions lacommunaute/notification/signals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from lacommunaute.notification.enums import EmailSentTrackKind, NotificationDelay
from lacommunaute.notification.enums import EmailSentTrackKind, delay_of_notifications
from lacommunaute.notification.models import Notification


Expand All @@ -11,8 +11,14 @@ def create_post_notifications(sender, instance, **kwargs):
if not instance.approved:
return

delay = NotificationDelay.ASAP if instance.is_first_reply else NotificationDelay.DAY
kind = EmailSentTrackKind.FIRST_REPLY if instance.is_first_reply else EmailSentTrackKind.FOLLOWING_REPLIES
if instance.is_topic_head:
kind = EmailSentTrackKind.PENDING_TOPIC
elif instance.is_first_reply:
kind = EmailSentTrackKind.FIRST_REPLY
else:
kind = EmailSentTrackKind.FOLLOWING_REPLIES

delay = delay_of_notifications[kind]

notifications = [
Notification(recipient=email_address, post=instance, kind=kind, delay=delay)
Expand Down
134 changes: 92 additions & 42 deletions lacommunaute/notification/tests/tests_signals.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,109 @@
from django.test import TestCase
import pytest

from lacommunaute.forum.factories import ForumFactory
from lacommunaute.forum_conversation.factories import (
AnonymousPostFactory,
AnonymousTopicFactory,
PostFactory,
TopicFactory,
)
from lacommunaute.forum_upvote.models import UpVote
from lacommunaute.notification.enums import EmailSentTrackKind, NotificationDelay
from lacommunaute.notification.enums import EmailSentTrackKind, NotificationDelay, delay_of_notifications
from lacommunaute.notification.models import Notification
from lacommunaute.users.factories import UserFactory


class PostCreatedTest(TestCase):
def test_notifications_on_post_creation(self):
topic = TopicFactory(with_post=True)
assert Notification.objects.count() == 0
@pytest.fixture(name="upvoter")
def fixture_upvoter():
return UserFactory()

first_post = PostFactory(topic=topic)

@pytest.fixture(name="topic_in_forum_with_upvoter")
def fixture_topic_in_forum_with_upvoter(upvoter):
return TopicFactory(forum=ForumFactory(upvoted_by=[upvoter]), with_post=True)


class TestCreatePostNotifications:
def test_pending_topic(self, db, topic_in_forum_with_upvoter, upvoter):
notification = Notification.objects.get()

for key, expected in [
("recipient", upvoter.email),
("post", topic_in_forum_with_upvoter.first_post),
("kind", EmailSentTrackKind.PENDING_TOPIC),
("delay", NotificationDelay.DAY),
]:
assert getattr(notification, key) == expected

def test_first_reply(self, db, topic_in_forum_with_upvoter):
Notification.objects.all().delete()

PostFactory(topic=topic_in_forum_with_upvoter)
notification = Notification.objects.get()
assert notification.recipient == topic.poster.email
assert notification.post == first_post
assert notification.kind == EmailSentTrackKind.FIRST_REPLY
assert notification.delay == NotificationDelay.ASAP

for key, expected in [
("recipient", topic_in_forum_with_upvoter.first_post.poster.email),
("post", topic_in_forum_with_upvoter.last_post),
("kind", EmailSentTrackKind.FIRST_REPLY),
("delay", NotificationDelay.ASAP),
]:
assert getattr(notification, key) == expected

def test_first_reply_on_anonymous_topic(self, db):
topic = AnonymousTopicFactory(with_post=True)
Notification.objects.all().delete()

PostFactory(topic=topic)
notifs = Notification.objects.exclude(id=notification.id)
assert notifs.count() == 2
assert notifs.exclude(post=first_post).count() == 2
assert notifs.exclude(kind=EmailSentTrackKind.FOLLOWING_REPLIES).count() == 0
assert notifs.exclude(delay=NotificationDelay.DAY).count() == 0
anticipated_recipients = set({topic.poster.email, first_post.poster.email})
assert set(notifs.values_list("recipient", flat=True)) == anticipated_recipients

def test_notifications_on_post_creation_upvote_follower(self):
topic = TopicFactory(with_post=True)

upvoter = UserFactory()
UpVote.objects.create(content_object=topic.first_post, voter=upvoter)

post = PostFactory(topic=topic)
notification = Notification.objects.get(recipient=upvoter.email)
assert notification.post == post
assert notification.kind == EmailSentTrackKind.FIRST_REPLY
assert notification.delay == NotificationDelay.ASAP

def test_notifications_on_post_creation_anonymous_poster(self):
notification = Notification.objects.get()

for key, expected in [
("recipient", topic.first_post.username),
("post", topic.last_post),
("kind", EmailSentTrackKind.FIRST_REPLY),
("delay", NotificationDelay.ASAP),
]:
assert getattr(notification, key) == expected

def test_following_replies(self, db, topic_in_forum_with_upvoter):
first_reply_poster = UserFactory()
PostFactory(topic=topic_in_forum_with_upvoter, poster=first_reply_poster)
Notification.objects.all().delete()

PostFactory(topic=topic_in_forum_with_upvoter)

assert Notification.objects.count() == 2

for notification in Notification.objects.all():
assert notification.recipient in [
topic_in_forum_with_upvoter.first_post.poster.email,
first_reply_poster.email,
]
for key, expected in [
("post", topic_in_forum_with_upvoter.last_post),
("kind", EmailSentTrackKind.FOLLOWING_REPLIES),
("delay", NotificationDelay.DAY),
]:
assert getattr(notification, key) == expected

def test_following_replies_on_anonymous_topic(self, db):
topic = AnonymousTopicFactory(with_post=True)
post = AnonymousPostFactory(topic=topic)
Notification.objects.all().delete()

PostFactory(topic=topic)
assert Notification.objects.count() == 2

for notification in Notification.objects.all():
assert notification.recipient in [topic.first_post.username, post.username]
for key, expected in [
("post", topic.last_post),
("kind", EmailSentTrackKind.FOLLOWING_REPLIES),
("delay", NotificationDelay.DAY),
]:
assert getattr(notification, key) == expected

post = PostFactory(topic=topic)
notification = Notification.objects.get(recipient=topic.first_post.username)
assert notification.post == post
assert notification.kind == EmailSentTrackKind.FIRST_REPLY
assert notification.delay == NotificationDelay.ASAP
def test_no_notifications_on_unapproved_post(self, db, upvoter):
topic = TopicFactory(forum=ForumFactory(upvoted_by=[upvoter]))

def test_notifications_no_approved_post(self):
topic = TopicFactory(with_post=True)
PostFactory(topic=topic, approved=False)
assert Notification.objects.count() == 0
for _ in delay_of_notifications:
PostFactory(topic=topic, approved=False)
assert Notification.objects.count() == 0

0 comments on commit 27cfd2a

Please sign in to comment.