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