Skip to content

Commit c6c5e50

Browse files
committed
chore(api/notifications): added tests
1 parent db6fc1d commit c6c5e50

11 files changed

+201
-1
lines changed

api/outdated/conftest.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from functools import partial
22

33
import pytest
4+
from django.core.management import call_command
45
from pytest_factoryboy import register
56
from rest_framework.test import APIClient
67

@@ -59,6 +60,18 @@ def client(db, settings, get_claims):
5960
return client
6061

6162

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

api/outdated/notifications/tests/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{% block subject -%}
2+
{% endblock -%}
3+
4+
Project: {{project.name}}
5+
Repo: {{project.repo}}
6+
7+
{% block content -%}
8+
{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% extends 'base.txt' %}
2+
3+
{% block subject %}
4+
bar
5+
{% endblock %}
6+
7+
{% block content %}
8+
test-bar.txt contents
9+
{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% extends 'base.txt' %}
2+
3+
{% block subject %}
4+
baz
5+
{% endblock %}
6+
7+
{% block content %}
8+
test-baz.txt contents
9+
{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% extends 'base.txt' %}
2+
3+
{% block subject %}
4+
foo
5+
{% endblock %}
6+
7+
{% block content %}
8+
test-foo.txt contents
9+
{% 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,29 @@
1+
from django.core.management import call_command
2+
3+
from outdated.notifications.notifier import Notifier
4+
5+
6+
def test_notify(
7+
db,
8+
project,
9+
maintainer_factory,
10+
version_factory,
11+
release_version_factory,
12+
capsys,
13+
mocker,
14+
):
15+
call_command("notify", project.name)
16+
stdout, _ = capsys.readouterr()
17+
assert stdout == f"Skipped {project.name} (no-maintainers)\n"
18+
maintainer_factory(project=project)
19+
call_command("notify", project.name)
20+
notify_mocker = mocker.spy(Notifier, "__init__")
21+
stdout, _ = capsys.readouterr()
22+
assert stdout == ""
23+
notify_mocker.assert_not_called()
24+
project.versioned_dependencies.set(
25+
[version_factory(release_version=release_version_factory(warning=True))]
26+
)
27+
project.save()
28+
call_command("notify", project.name)
29+
notify_mocker.assert_called_once()
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\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

api/poetry.lock

+18-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pytest-cov = "^4.0.0"
3939
pytest-vcr = "^1.0.2"
4040
pdbpp = "^0.10.3"
4141
requests-mock = "^1.10.0"
42+
pytest-mock = "^3.11.1"
4243

4344

4445
[tool.isort]

0 commit comments

Comments
 (0)