teilchensammler/collector/tests.py

104 lines
3.1 KiB
Python

from typing import Callable
import pytest
from django.test import Client
from django.urls import reverse
from hypothesis import given
from hypothesis import strategies as st
from structlog.testing import capture_logs
from .models import Teil
names = st.text(alphabet=st.characters(exclude_categories=["C"]), min_size=1)
@given(data=names)
def test_submitted_data_ends_up_in_database(data, session: Client):
with pytest.raises(Teil.DoesNotExist):
Teil.objects.get(name=data)
response = session.post(reverse("collector:enter"), data={"new_name": data})
assert response.status_code == 302
assert Teil.objects.get(name=data)
@given(data=names)
def test_entering_same_name_twice_does_not_change_database_entry(data, session: Client):
assert not Teil.objects.filter(name=data).exists()
response = session.post(reverse("collector:enter"), data={"new_name": data})
assert response.status_code == 302
assert Teil.objects.filter(name=data).count() == 1
response = session.post(reverse("collector:enter"), data={"new_name": data})
assert response.status_code == 302
assert Teil.objects.filter(name=data).count() == 1
@pytest.mark.parametrize(
"http_method,expected_status",
[
("GET", 405),
("PATCH", 405),
("POST", 302),
("PUT", 405),
],
)
def test_enter_endpoint_accepts_only_post_requests(
client: Client,
http_method: str,
expected_status: int,
random_name: Callable[[int], str],
):
client_method = getattr(client, http_method.lower())
response = client_method(
reverse("collector:enter"), data={"new_name": random_name(8)}
)
assert response.status_code == expected_status
def test_enter_endpoints_emits_expected_logs(
client: Client, random_name: Callable[[int], str]
):
"""
note: capture_logs() yields a list of dicts, not a list of logfmt lines
that we configured for the app
"""
same_name = random_name(10)
with capture_logs() as logs:
response = client.post(reverse("collector:enter"), data={"new_name": same_name})
assert response.status_code == 302
assert any(
(
le["event"].lower() == "New Teil entered".lower()
and le["log_level"].lower() == "info"
and "teil_id" in le
for le in logs
)
)
with capture_logs() as logs:
response = client.post(reverse("collector:enter"), data={"new_name": same_name})
assert response.status_code == 302
assert any(
(
le["event"].lower() == "Teil already existed".lower()
and le["log_level"].lower() == "warning"
and "teil_id" not in le
for le in logs
)
)
def test_model_manager_lists_newest_teil_first():
t1 = Teil.objects.create(name="Teil 1")
t2 = Teil.objects.create(name="Teil 2")
t3 = Teil.objects.create(name="Teil 3")
assert t1.modified < t2.modified < t3.modified
t = Teil.objects.all()
assert t[2].modified < t[1].modified < t[0].modified