Skip to content

Commit

Permalink
Improve tests
Browse files Browse the repository at this point in the history
  • Loading branch information
AlvaroLQueiroz committed Apr 20, 2024
1 parent ca63550 commit 06fe6b0
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 224 deletions.
13 changes: 13 additions & 0 deletions notifications/tests/test_admin.py
@@ -0,0 +1,13 @@
from django.urls import reverse

from notifications.tests.factories.notifications import NotificationFullFactory


def test_admin(admin_user, client):
app_name = "notifications"
NotificationFullFactory.create_batch(10)

client.force_login(admin_user)

response = client.get(reverse(f"admin:{app_name}_notification_changelist"))
assert response.status_code == 200
25 changes: 24 additions & 1 deletion notifications/tests/test_models.py
Expand Up @@ -111,9 +111,32 @@ def test_build_url():
),
)
@pytest.mark.django_db
def test_natural_day(increase, expected_result):
def test_naturalday(increase, expected_result):
initial_date = datetime(2023, 1, 1, 0, 0, 0)
with freeze_time(initial_date):
notification = NotificationShortFactory()
with freeze_time(initial_date + timedelta(**increase)):
assert notification.naturalday() == expected_result


@pytest.mark.parametrize(
"increase,expected_result",
(
({"minutes": 10}, "10\xa0minutes ago"),
({"days": 1}, "1\xa0day ago"),
),
)
@pytest.mark.django_db
def test_naturaltime(increase, expected_result):
initial_date = datetime(2023, 1, 1, 0, 0, 0)
with freeze_time(initial_date):
notification = NotificationShortFactory()
with freeze_time(initial_date + timedelta(**increase)):
assert notification.naturaltime() == expected_result


@pytest.mark.django_db
def test_extra_data():
data = {"url": "/learn/ask-a-pro/q/test-question-9/299/", "other_content": "Hello my 'world'"}
notification = NotificationFullFactory(data=data)
assert notification.data == data
74 changes: 38 additions & 36 deletions notifications/tests/test_template_tags.py
@@ -1,16 +1,13 @@
from unittest.mock import Mock, patch

import pytest
from django.template import Context, Template
from django.urls import reverse_lazy
from freezegun import freeze_time
from swapper import load_model

from notifications.templatetags.notifications_tags import (
has_notification,
live_notify_badge,
live_notify_list,
notifications_unread,
register_notify_callbacks,
user_context,
)
from notifications.tests.factories.notifications import NotificationFullFactory
Expand All @@ -19,27 +16,38 @@
Notification = load_model("notifications", "Notification")


def render_tag(template, context):
template = Template("{% load notifications_tags %}" + template)
return template.render(Context(context))


@pytest.mark.django_db
def test_notifications_unread():
with patch("notifications.templatetags.notifications_tags.user_context") as user_context_mock:
user_context_mock.return_value = None
assert notifications_unread({}) == ""
assert render_tag("{% notifications_unread %}", {}) == ""

notification = NotificationFullFactory()
user_context_mock.return_value = notification.recipient
assert notifications_unread({}) == 1
assert (
render_tag("{% notifications_unread %}", {"user": Mock(), "request": Mock(user=Mock(is_anonymous=True))}) == ""
)

notification = NotificationFullFactory()
assert (
render_tag(
"{% notifications_unread %}", {"user": notification.recipient, "request": Mock(user=notification.recipient)}
)
== "1"
)


@pytest.mark.django_db
def test_has_notification():
user = RecipientFactory()
assert has_notification(user) is False
assert render_tag("{{ user|has_notification }}", {"user": user}) == "False"

notification = NotificationFullFactory(recipient=user)
assert has_notification(user) is True
assert render_tag("{{ user|has_notification }}", {"user": user}) == "True"

notification.mark_as_read()
assert has_notification(user) is False
assert render_tag("{{ user|has_notification }}", {"user": user}) == "False"


@pytest.mark.parametrize(
Expand All @@ -50,26 +58,19 @@ def test_has_notification():
),
)
def test_register_notify_callbacks(_type, url):
callback = register_notify_callbacks(
badge_class="badge1",
menu_class="menu2",
refresh_period=10,
callbacks="cb1,cb2",
api_name=_type,
fetch=50,
nonce="123",
mark_as_read=True,
)
tag = f"{{% register_notify_callbacks badge_class='badge1' menu_class='menu2' refresh_period=10 callbacks='cb1,cb2' api_name='{_type}' fetch=50 nonce='123' mark_as_read=True %}}" # pylint: disable=line-too-long

render = render_tag(tag, {})

assert "notify_badge_class='badge1'" in callback
assert "notify_menu_class='menu2'" in callback
assert "notify_refresh_period=10" in callback
assert "register_notifier(cb1);" in callback
assert "register_notifier(cb2);" in callback
assert "notify_fetch_count='50'" in callback
assert 'nonce="123"' in callback
assert "true" in callback
assert str(url) in callback
assert "notify_badge_class='badge1'" in render
assert "notify_menu_class='menu2'" in render
assert "notify_refresh_period=10" in render
assert "register_notifier(cb1);" in render
assert "register_notifier(cb2);" in render
assert "notify_fetch_count='50'" in render
assert 'nonce="123"' in render
assert "true" in render
assert str(url) in render


@patch("notifications.templatetags.notifications_tags.user_context")
Expand All @@ -80,26 +81,27 @@ def test_live_notify_badge(cache_mock, user_context_mock):

user_context_mock.return_value = None
assert live_notify_badge({}) == ""
assert render_tag("{% live_notify_badge %}", {}) == ""

user_context_mock.return_value = user
badge = live_notify_badge({}, badge_class="blafoo")
badge = render_tag("{% live_notify_badge badge_class='blafoo' %}", {})
assert "blafoo" in badge
assert "0" in badge

with freeze_time("2024-01-01 00:00:00"):
NotificationFullFactory(recipient=user)
badge = live_notify_badge({}, badge_class="blafoo")
badge = render_tag("{% live_notify_badge badge_class='blafoo' %}", {})
assert "blafoo" in badge
assert "0" in badge # Because of cache

cache_mock.side_effect = lambda user: user.notifications.unread().count()
badge = live_notify_badge({}, badge_class="blafoo")
badge = render_tag("{% live_notify_badge badge_class='blafoo' %}", {})
assert "blafoo" in badge
assert "1" in badge


def test_live_notify_list():
resp = live_notify_list("blafoo")
resp = render_tag("{% live_notify_list list_class='blafoo' %}", {})
assert "<ul" in resp
assert "class='blafoo'" in resp

Expand Down
187 changes: 1 addition & 186 deletions notifications/tests/tests.py
Expand Up @@ -8,19 +8,14 @@
from datetime import datetime, timezone

from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.core.exceptions import ImproperlyConfigured
from django.db import connection
from django.shortcuts import render
from django.template import Context, Template
from django.test import override_settings # noqa
from django.test import RequestFactory, TestCase
from django.test.utils import CaptureQueriesContext
from django.urls import reverse
from django.utils.timezone import localtime
from swapper import load_model

from notifications.signals import notify, notify_handler
from notifications.signals import notify

Notification = load_model("notifications", "Notification")
User = get_user_model()
Expand Down Expand Up @@ -60,127 +55,6 @@ def test_disable_timezone(self):
delta = datetime.now() - notification.timestamp
self.assertTrue(delta.seconds < 60)

def test_humanize_naturalday_timestamp(self):
from_user = User.objects.create(username="from2", password="pwd", email="example@example.com")
to_user = User.objects.create(username="to2", password="pwd", email="example@example.com")
notify.send(from_user, recipient=to_user, verb="commented", action_object=from_user)
notification = Notification.objects.get(recipient=to_user)
self.assertEqual(notification.naturalday(), "today")

def test_humanize_naturaltime_timestamp(self):
from_user = User.objects.create(username="from2", password="pwd", email="example@example.com")
to_user = User.objects.create(username="to2", password="pwd", email="example@example.com")
notify.send(from_user, recipient=to_user, verb="commented", action_object=from_user)
notification = Notification.objects.get(recipient=to_user)
self.assertEqual(notification.naturaltime(), "now")


class NotificationManagersTest(TestCase):
"""Django notifications Manager automated tests"""

def setUp(self):
self.message_count = 10
self.other_user = User.objects.create(username="other1", password="pwd", email="example@example.com")

self.from_user = User.objects.create(username="from2", password="pwd", email="example@example.com")
self.to_user = User.objects.create(username="to2", password="pwd", email="example@example.com")
self.to_group = Group.objects.create(name="to2_g")
self.to_user_list = User.objects.all()
self.to_group.user_set.add(self.to_user)
self.to_group.user_set.add(self.other_user)

for _ in range(self.message_count):
notify.send(self.from_user, recipient=self.to_user, verb="commented", action_object=self.from_user)
# Send notification to group
notify.send(self.from_user, recipient=self.to_group, verb="commented", action_object=self.from_user)
self.message_count += self.to_group.user_set.count()
# Send notification to user list
notify.send(self.from_user, recipient=self.to_user_list, verb="commented", action_object=self.from_user)
self.message_count += len(self.to_user_list)

def test_notify_send_return_val(self):
results = notify.send(self.from_user, recipient=self.to_user, verb="commented", action_object=self.from_user)
for result in results:
if result[0] is notify_handler:
self.assertEqual(len(result[1]), 1)
# only check types for now
self.assertEqual(type(result[1][0]), Notification)

def test_notify_send_return_val_group(self):
results = notify.send(self.from_user, recipient=self.to_group, verb="commented", action_object=self.from_user)
for result in results:
if result[0] is notify_handler:
self.assertEqual(len(result[1]), self.to_group.user_set.count())
for notification in result[1]:
# only check types for now
self.assertEqual(type(notification), Notification)

def test_unread_manager(self):
self.assertEqual(Notification.objects.unread().count(), self.message_count)
notification = Notification.objects.filter(recipient=self.to_user).first()
notification.mark_as_read()
self.assertEqual(Notification.objects.unread().count(), self.message_count - 1)
for notification in Notification.objects.unread():
self.assertTrue(notification.unread)

def test_read_manager(self):
self.assertEqual(Notification.objects.unread().count(), self.message_count)
notification = Notification.objects.filter(recipient=self.to_user).first()
notification.mark_as_read()
self.assertEqual(Notification.objects.read().count(), 1)
for notification in Notification.objects.read():
self.assertFalse(notification.unread)

def test_mark_all_as_read_manager(self):
self.assertEqual(Notification.objects.unread().count(), self.message_count)
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
self.assertEqual(self.to_user.notifications.unread().count(), 0)

@override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True})
def test_mark_all_as_read_manager_with_soft_delete(self):
# even soft-deleted notifications should be marked as read
# refer: https://github.com/django-notifications/django-notifications/issues/126
to_delete = Notification.objects.filter(recipient=self.to_user).order_by("id")[0]
to_delete.deleted = True
to_delete.save()
self.assertTrue(Notification.objects.filter(recipient=self.to_user).order_by("id")[0].unread)
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
self.assertFalse(Notification.objects.filter(recipient=self.to_user).order_by("id")[0].unread)

def test_mark_all_as_unread_manager(self):
self.assertEqual(Notification.objects.unread().count(), self.message_count)
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
self.assertEqual(self.to_user.notifications.unread().count(), 0)
Notification.objects.filter(recipient=self.to_user).mark_all_as_unread()
self.assertEqual(Notification.objects.unread().count(), self.message_count)

def test_mark_all_deleted_manager_without_soft_delete(self):
self.assertRaises(ImproperlyConfigured, Notification.objects.active)
self.assertRaises(ImproperlyConfigured, Notification.objects.active)
self.assertRaises(ImproperlyConfigured, Notification.objects.mark_all_as_deleted)
self.assertRaises(ImproperlyConfigured, Notification.objects.mark_all_as_active)

@override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True})
def test_mark_all_deleted_manager(self):
notification = Notification.objects.filter(recipient=self.to_user).first()
notification.mark_as_read()
self.assertEqual(Notification.objects.read().count(), 1)
self.assertEqual(Notification.objects.unread().count(), self.message_count - 1)
self.assertEqual(Notification.objects.active().count(), self.message_count)
self.assertEqual(Notification.objects.deleted().count(), 0)

Notification.objects.mark_all_as_deleted()
self.assertEqual(Notification.objects.read().count(), 0)
self.assertEqual(Notification.objects.unread().count(), 0)
self.assertEqual(Notification.objects.active().count(), 0)
self.assertEqual(Notification.objects.deleted().count(), self.message_count)

Notification.objects.mark_all_as_active()
self.assertEqual(Notification.objects.read().count(), 1)
self.assertEqual(Notification.objects.unread().count(), self.message_count - 1)
self.assertEqual(Notification.objects.active().count(), self.message_count)
self.assertEqual(Notification.objects.deleted().count(), 0)


class NotificationTestPages(TestCase):
"""Django notifications automated page tests"""
Expand Down Expand Up @@ -512,62 +386,3 @@ def test_extra_data(self):
data = json.loads(response.content.decode("utf-8"))
self.assertEqual(data["unread_list"][0]["data"]["url"], "/learn/ask-a-pro/q/test-question-9/299/")
self.assertEqual(data["unread_list"][0]["data"]["other_content"], "Hello my 'world'")


class TagTest(TestCase):
"""Django notifications automated tags tests"""

def setUp(self):
self.message_count = 1
self.from_user = User.objects.create_user(username="from", password="pwd", email="example@example.com")
self.to_user = User.objects.create_user(username="to", password="pwd", email="example@example.com")
self.to_user.is_staff = True
self.to_user.save()
for _ in range(self.message_count):
notify.send(
self.from_user,
recipient=self.to_user,
verb="commented",
action_object=self.from_user,
url="/learn/ask-a-pro/q/test-question-9/299/",
other_content="Hello my 'world'",
)

def tag_test(self, template, context, output):
template = Template("{% load notifications_tags %}" + template)
context = Context(context)
self.assertEqual(template.render(context), output)

def test_has_notification(self):
template = "{{ user|has_notification }}"
context = {"user": self.to_user}
output = "True"
self.tag_test(template, context, output)


class AdminTest(TestCase):
app_name = "notifications"

def setUp(self):
self.message_count = 10
self.from_user = User.objects.create_user(username="from", password="pwd", email="example@example.com")
self.to_user = User.objects.create_user(username="to", password="pwd", email="example@example.com")
self.to_user.is_staff = True
self.to_user.is_superuser = True
self.to_user.save()
for _ in range(self.message_count):
notify.send(
self.from_user,
recipient=self.to_user,
verb="commented",
action_object=self.from_user,
)

def test_list(self):
self.client.login(username="to", password="pwd")

with CaptureQueriesContext(connection=connection) as context:
response = self.client.get(reverse(f"admin:{self.app_name}_notification_changelist"))
self.assertLessEqual(len(context), 6)

self.assertEqual(response.status_code, 200, response.content)

0 comments on commit 06fe6b0

Please sign in to comment.