import pytest from django.urls import reverse from recipes.models import Comment from .recipe_helpers import make_recipe pytestmark = pytest.mark.django_db def post_comment(client, recipe, text="Sehr lecker!"): return client.post(reverse("recipes:comment_create", args=[recipe.pk]), {"text": text}) def test_user_comments_on_public_recipe(client, user, other_user): recipe = make_recipe(user) client.force_login(other_user) response = post_comment(client, recipe) comment = Comment.objects.get() assert response["Location"].endswith(f"#kommentar-{comment.pk}") assert comment.author == other_user assert "Sehr lecker!" in client.get(reverse("recipes:detail", args=[recipe.pk])).content.decode() def test_empty_comment_rejected(user_client, user): recipe = make_recipe(user) assert post_comment(user_client, recipe, "").status_code == 400 assert not Comment.objects.exists() def test_comment_too_long_rejected(user_client, user): recipe = make_recipe(user) assert post_comment(user_client, recipe, "x" * 2001).status_code == 400 def test_author_and_admin_can_delete(client, user, other_user, admin_user): recipe = make_recipe(user) first = Comment.objects.create(recipe=recipe, author=other_user, text="eins") second = Comment.objects.create(recipe=recipe, author=other_user, text="zwei") client.force_login(other_user) client.post(reverse("recipes:comment_delete", args=[recipe.pk, first.pk])) client.force_login(admin_user) client.post(reverse("recipes:comment_delete", args=[recipe.pk, second.pk])) assert not Comment.objects.exists() def test_others_cannot_delete_comment(client, user, other_user): """Not even the recipe owner may delete someone else's comment (spec: author and admin only).""" recipe = make_recipe(user) comment = Comment.objects.create(recipe=recipe, author=other_user, text="bleibt") client.force_login(user) assert client.post(reverse("recipes:comment_delete", args=[recipe.pk, comment.pk])).status_code == 404 assert Comment.objects.exists() def test_delete_button_only_where_allowed(client, user, other_user): recipe = make_recipe(user) comment = Comment.objects.create(recipe=recipe, author=other_user, text="hallo") delete_url = reverse("recipes:comment_delete", args=[recipe.pk, comment.pk]) client.force_login(user) assert delete_url not in client.get(reverse("recipes:detail", args=[recipe.pk])).content.decode() client.force_login(other_user) assert delete_url in client.get(reverse("recipes:detail", args=[recipe.pk])).content.decode() def test_comment_rate_limit(user_client, user, settings): settings.COMMENT_RATE_LIMIT_PER_HOUR = 2 recipe = make_recipe(user) for i in range(3): post_comment(user_client, recipe, f"Kommentar {i}") assert Comment.objects.count() == 2 def test_comment_text_is_escaped(user_client, user): recipe = make_recipe(user) post_comment(user_client, recipe, "") html = user_client.get(reverse("recipes:detail", args=[recipe.pk])).content.decode() assert "" not in html def test_cook_mode_scales(user_client, user): recipe = make_recipe(user, ingredients="200 g Mehl") html = user_client.get(reverse("recipes:cook", args=[recipe.pk]), {"portionen": 8}).content.decode() assert "400 g" in html and "data-wakelock" in html def test_detail_scaling(user_client, user): recipe = make_recipe(user, ingredients="600 g Kartoffeln\n1 ½ TL Salz") html = user_client.get(reverse("recipes:detail", args=[recipe.pk]), {"portionen": 8}).content.decode() assert "1,2 kg" in html and "3 TL" in html @pytest.mark.parametrize("value", ["abc", "-5", "0", "99999"]) def test_scaling_with_bad_input(user_client, user, value): recipe = make_recipe(user) assert user_client.get(reverse("recipes:detail", args=[recipe.pk]), {"portionen": value}).status_code == 200