Skip to content

Commit

Permalink
chore(api/notifications): added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
c0rydoras committed Aug 9, 2023
1 parent fdf0fbb commit 5fa8790
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 1 deletion.
13 changes: 13 additions & 0 deletions api/outdated/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from functools import partial

import pytest
from django.core.management import call_command
from pytest_factoryboy import register
from rest_framework.test import APIClient

Expand Down Expand Up @@ -59,6 +60,18 @@ def client(db, settings, get_claims):
return client


@pytest.fixture
def setup_notifications(transactional_db, settings):
settings.NOTIFICATIONS = [
("test-foo", 60),
("test-bar", 10),
("test-baz", -20),
]
call_command("update-notifications")
settings.TEMPLATES[0]["DIRS"] = ["outdated/notifications/tests/templates"]
settings.TEMPLATES[0]["APP_DIRS"] = False


@pytest.fixture(scope="module")
def vcr_config():
return {
Expand Down
Empty file.
8 changes: 8 additions & 0 deletions api/outdated/notifications/tests/templates/base.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% block subject -%}
{% endblock -%}

Project: {{project.name}}
Repo: {{project.repo}}

{% block content -%}
{% endblock %}
9 changes: 9 additions & 0 deletions api/outdated/notifications/tests/templates/test-bar.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends 'base.txt' %}

{% block subject %}
bar
{% endblock %}

{% block content %}
test-bar.txt contents
{% endblock %}
9 changes: 9 additions & 0 deletions api/outdated/notifications/tests/templates/test-baz.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends 'base.txt' %}

{% block subject %}
baz
{% endblock %}

{% block content %}
test-baz.txt contents
{% endblock %}
9 changes: 9 additions & 0 deletions api/outdated/notifications/tests/templates/test-foo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends 'base.txt' %}

{% block subject %}
foo
{% endblock %}

{% block content %}
test-foo.txt contents
{% endblock %}
47 changes: 47 additions & 0 deletions api/outdated/notifications/tests/test_build_notification_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from datetime import date, timedelta
from unittest.mock import MagicMock

import pytest
from pytest_mock import MockerFixture

from .. import models


@pytest.mark.parametrize(
"status,called",
(["UNDEFINED", False], ["OUTDATED", True], ["WARNING", True], ["UP-TO-DATE", True]),
)
def test_build_notification_queue_called(
transactional_db,
mocker: MockerFixture,
status,
called,
project_factory,
release_version_factory,
version_factory,
):
build_notification_queue_mock: MagicMock = mocker.patch.object(
models, "build_notification_queue"
)
release_version = release_version_factory(
undefined=status == "UNDEFINED",
outdated=status == "OUTDATED",
warning=status == "WARNING",
up_to_date=status == "UP-TO-DATE",
)
version = version_factory(release_version=release_version)
project = project_factory()
assert build_notification_queue_mock.call_count == 0
project.versioned_dependencies.add(version)

if called:
build_notification_queue_mock.assert_called_with(project)
other_project = project_factory(versioned_dependencies=[version])
build_notification_queue_mock.assert_called_with(other_project)

release_version.end_of_life = date.today() + timedelta(days=2000)
release_version.save()

assert build_notification_queue_mock.call_count == 4
else:
assert build_notification_queue_mock.call_count == 0
29 changes: 29 additions & 0 deletions api/outdated/notifications/tests/test_management_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from django.core.management import call_command

from outdated.notifications.notifier import Notifier


def test_notify(
db,
project,
maintainer_factory,
version_factory,
release_version_factory,
capsys,
mocker,
):
call_command("notify", project.name)
stdout, _ = capsys.readouterr()
assert stdout == f"Skipped {project.name} (no-maintainers)\n"
maintainer_factory(project=project)
call_command("notify", project.name)
notify_mocker = mocker.spy(Notifier, "__init__")
stdout, _ = capsys.readouterr()
assert stdout == ""
notify_mocker.assert_not_called()
project.versioned_dependencies.set(
[version_factory(release_version=release_version_factory(warning=True))]
)
project.save()
call_command("notify", project.name)
notify_mocker.assert_called_once()
58 changes: 58 additions & 0 deletions api/outdated/notifications/tests/test_notifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from datetime import date, timedelta
from typing import Optional

import pytest

from outdated.notifications.notifier import Notifier
from outdated.outdated.models import Maintainer


@pytest.mark.parametrize("nonprimary_maintainers", [False, True])
@pytest.mark.parametrize(
"days_until_outdated,template,sent",
[
(200, None, False),
(60, "test-foo", True),
(50, "test-foo", True),
(10, "test-bar", True),
(-20, "test-baz", True),
],
)
def test_send_notification(
setup_notifications,
days_until_outdated: int,
template: Optional[str],
sent: bool,
nonprimary_maintainers: bool,
maintainer,
maintainer_factory,
mailoutbox,
version_factory,
release_version_factory,
):
project = maintainer.project
release_version = release_version_factory(
end_of_life=date.today() + timedelta(days=days_until_outdated)
)
version = version_factory(release_version=release_version)
project.versioned_dependencies.add(version)
project.save()
if nonprimary_maintainers:
maintainer_factory(project=project)
maintainer_factory(project=project)
maintainer_factory(project=project)
nonprimary_maintainers = list(Maintainer.objects.filter(is_primary=False))
notification_queue = list(project.notification_queue.all())
Notifier(project).notify()
if sent:
mail = mailoutbox[0]
assert mail.subject == template.replace("test-", "")
assert (
mail.body
== f"Project: {project.name}\nRepo: {project.repo}\n\n{template}.txt contents\n"
)
assert mail.to[0] == maintainer.user.email
assert mail.cc == [m.user.email for m in nonprimary_maintainers]
assert notification_queue[1:] == list(project.notification_queue.all())
else:
assert not mailoutbox
19 changes: 18 additions & 1 deletion api/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pytest-cov = "^4.0.0"
pytest-vcr = "^1.0.2"
pdbpp = "^0.10.3"
requests-mock = "^1.10.0"
pytest-mock = "^3.11.1"


[tool.isort]
Expand Down

0 comments on commit 5fa8790

Please sign in to comment.