Skip to content

Commit ef5ec4f

Browse files
committed
chore: added tests
1 parent 710bf79 commit ef5ec4f

11 files changed

+544
-434
lines changed

api/outdated/conftest.py

+14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
from datetime import timedelta
12
from functools import partial
23

34
import pytest
5+
from django.core.management import call_command
46
from pytest_factoryboy import register
57
from rest_framework.test import APIClient
68

@@ -59,6 +61,18 @@ def client(db, settings, get_claims):
5961
return client
6062

6163

64+
@pytest.fixture
65+
def setup_notifications(transactional_db, settings):
66+
settings.NOTIFICATIONS = [
67+
("test-foo", timedelta(days=60)),
68+
("test-bar", timedelta(days=10)),
69+
("test-baz", timedelta(days=-20)),
70+
]
71+
call_command("update-notifications")
72+
settings.TEMPLATES[0]["DIRS"] = ["outdated/notifications/tests/templates"]
73+
settings.TEMPLATES[0]["APP_DIRS"] = False
74+
75+
6276
@pytest.fixture(scope="module")
6377
def vcr_config():
6478
return {

api/outdated/notifications/tests/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{% block subject %}{% endblock %}
2+
Project: {{project.name}}
3+
Repo: {{project.repo}}
4+
{% block content %}{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% extends 'base.txt' %}
2+
{% block subject %}bar{% endblock %}
3+
{% block content %}test-bar.txt contents{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% extends 'base.txt' %}
2+
{% block subject %}baz{% endblock %}
3+
{% block content %}test-baz.txt contents{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% extends 'base.txt' %}
2+
{% block subject %}foo{% endblock %}
3+
{% block content %}test-foo.txt contents{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from datetime import date, timedelta
2+
from unittest.mock import MagicMock
3+
4+
import pytest
5+
from pytest_mock import MockerFixture
6+
7+
from .. import models
8+
9+
10+
@pytest.mark.parametrize(
11+
"status,called",
12+
(["UNDEFINED", False], ["OUTDATED", True], ["WARNING", True], ["UP-TO-DATE", True]),
13+
)
14+
def test_build_notification_queue_called(
15+
transactional_db,
16+
mocker: MockerFixture,
17+
status,
18+
called,
19+
project_factory,
20+
release_version_factory,
21+
version_factory,
22+
):
23+
build_notification_queue_mock: MagicMock = mocker.patch.object(
24+
models, "build_notification_queue"
25+
)
26+
release_version = release_version_factory(
27+
undefined=status == "UNDEFINED",
28+
outdated=status == "OUTDATED",
29+
warning=status == "WARNING",
30+
up_to_date=status == "UP-TO-DATE",
31+
)
32+
version = version_factory(release_version=release_version)
33+
project = project_factory()
34+
assert build_notification_queue_mock.call_count == 0
35+
project.versioned_dependencies.add(version)
36+
37+
if called:
38+
build_notification_queue_mock.assert_called_with(project)
39+
other_project = project_factory(versioned_dependencies=[version])
40+
build_notification_queue_mock.assert_called_with(other_project)
41+
42+
release_version.end_of_life = date.today() + timedelta(days=2000)
43+
release_version.save()
44+
45+
assert build_notification_queue_mock.call_count == 4
46+
else:
47+
assert build_notification_queue_mock.call_count == 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from unittest.mock import MagicMock
2+
3+
import pytest
4+
from django.core.management import call_command
5+
from pytest_mock import MockerFixture
6+
7+
from outdated.notifications.notifier import Notifier
8+
9+
10+
def test_notify(db, project, maintainer_factory, mocker: MockerFixture):
11+
notifier_init_mock: MagicMock = mocker.patch.object(
12+
Notifier, "__init__", return_value=None
13+
)
14+
notify_mock: MagicMock = mocker.patch.object(Notifier, "notify")
15+
with pytest.raises(
16+
ValueError, match="Notify can't be used on projects without maintainers!"
17+
):
18+
call_command("notify", project.name)
19+
notifier_init_mock.assert_not_called()
20+
notify_mock.assert_not_called()
21+
maintainer_factory(project=project)
22+
call_command("notify", project.name)
23+
notifier_init_mock.assert_called_once_with(project)
24+
notify_mock.assert_called_once()
25+
26+
27+
def test_notify_all(db, project_factory, maintainer_factory, mocker: MockerFixture):
28+
notifier_init_mock: MagicMock = mocker.patch.object(
29+
Notifier, "__init__", return_value=None
30+
)
31+
notify_mock: MagicMock = mocker.patch.object(Notifier, "notify")
32+
project = project_factory(name="foo")
33+
other_project = project_factory(name="bar")
34+
project_factory(name="not-called")
35+
call_command("notify-all")
36+
notifier_init_mock.assert_not_called()
37+
notify_mock.assert_not_called()
38+
39+
maintainer_factory(project=project)
40+
maintainer_factory(project=other_project)
41+
call_command("notify-all")
42+
notifier_init_mock.assert_has_calls(
43+
[
44+
mocker.call(other_project),
45+
mocker.call(project),
46+
]
47+
)
48+
assert notify_mock.call_count == 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from datetime import date, timedelta
2+
from typing import Optional
3+
4+
import pytest
5+
6+
from outdated.notifications.notifier import Notifier
7+
from outdated.outdated.models import Maintainer
8+
9+
10+
@pytest.mark.parametrize("nonprimary_maintainers", [False, True])
11+
@pytest.mark.parametrize(
12+
"days_until_outdated,template,sent",
13+
[
14+
(200, None, False),
15+
(60, "test-foo", True),
16+
(50, "test-foo", True),
17+
(10, "test-bar", True),
18+
(-20, "test-baz", True),
19+
],
20+
)
21+
def test_send_notification(
22+
setup_notifications,
23+
days_until_outdated: int,
24+
template: Optional[str],
25+
sent: bool,
26+
nonprimary_maintainers: bool,
27+
maintainer,
28+
maintainer_factory,
29+
mailoutbox,
30+
version_factory,
31+
release_version_factory,
32+
):
33+
project = maintainer.project
34+
release_version = release_version_factory(
35+
end_of_life=date.today() + timedelta(days=days_until_outdated)
36+
)
37+
version = version_factory(release_version=release_version)
38+
project.versioned_dependencies.add(version)
39+
project.save()
40+
if nonprimary_maintainers:
41+
maintainer_factory(project=project)
42+
maintainer_factory(project=project)
43+
maintainer_factory(project=project)
44+
nonprimary_maintainers = list(Maintainer.objects.filter(is_primary=False))
45+
notification_queue = list(project.notification_queue.all())
46+
Notifier(project).notify()
47+
if sent:
48+
mail = mailoutbox[0]
49+
assert mail.subject == template.replace("test-", "")
50+
assert (
51+
mail.body
52+
== f"Project: {project.name}\nRepo: {project.repo}\n{template}.txt contents\n"
53+
)
54+
assert mail.to[0] == maintainer.user.email
55+
assert mail.cc == [m.user.email for m in nonprimary_maintainers]
56+
assert notification_queue[1:] == list(project.notification_queue.all())
57+
else:
58+
assert not mailoutbox

0 commit comments

Comments
 (0)