From c4fde90a9ce906310153f96f6b39c39ad6d01da1 Mon Sep 17 00:00:00 2001 From: Mark <162816078+markashton480@users.noreply.github.com> Date: Sat, 28 Feb 2026 17:36:34 +0000 Subject: [PATCH] fix(spec): enforce read-time budget and re-render invalid comment submissions --- apps/comments/tests/test_views.py | 31 ++++++++++++++++++++++++++++- apps/comments/views.py | 15 +++++++++----- apps/core/tests/test_performance.py | 1 + templates/blog/article_page.html | 14 ++++++++++--- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/apps/comments/tests/test_views.py b/apps/comments/tests/test_views.py index 189e328..d55b8ba 100644 --- a/apps/comments/tests/test_views.py +++ b/apps/comments/tests/test_views.py @@ -63,6 +63,34 @@ def test_comment_post_rejected_when_comments_disabled(client, home_page): assert Comment.objects.count() == 0 +@pytest.mark.django_db +def test_invalid_comment_post_rerenders_form_with_errors(client, home_page): + cache.clear() + index = ArticleIndexPage(title="Articles", slug="articles") + home_page.add_child(instance=index) + author = AuthorFactory() + article = ArticlePage(title="A", slug="a", author=author, summary="s", body=[("rich_text", "
body
")]) + index.add_child(instance=article) + article.save_revision().publish() + + resp = client.post( + "/comments/post/", + { + "article_id": article.id, + "author_name": "Test", + "author_email": "test@example.com", + "body": " ", + "honeypot": "", + }, + ) + + assert resp.status_code == 200 + assert b'aria-label="Comment form errors"' in resp.content + assert b'value="Test"' in resp.content + assert b"test@example.com" in resp.content + assert Comment.objects.count() == 0 + + @pytest.mark.django_db def test_comment_reply_depth_is_enforced(client, home_page): cache.clear() @@ -100,7 +128,8 @@ def test_comment_reply_depth_is_enforced(client, home_page): "honeypot": "", }, ) - assert resp.status_code == 302 + assert resp.status_code == 200 + assert b"Reply depth exceeds the allowed limit" in resp.content assert Comment.objects.count() == 2 diff --git a/apps/comments/views.py b/apps/comments/views.py index 1c9a036..5e908a2 100644 --- a/apps/comments/views.py +++ b/apps/comments/views.py @@ -5,7 +5,7 @@ from django.contrib import messages from django.core.cache import cache from django.core.exceptions import ValidationError from django.http import HttpResponse -from django.shortcuts import get_object_or_404, redirect +from django.shortcuts import get_object_or_404, redirect, render from django.views import View from apps.blog.models import ArticlePage @@ -23,6 +23,12 @@ def client_ip_from_request(request) -> str: class CommentCreateView(View): + def _render_article_with_errors(self, request, article, form): + context = article.get_context(request) + context["page"] = article + context["comment_form"] = form + return render(request, "blog/article_page.html", context, status=200) + def post(self, request): ip = client_ip_from_request(request) key = f"comment-rate:{ip}" @@ -48,11 +54,10 @@ class CommentCreateView(View): try: comment.full_clean() except ValidationError: - messages.error(request, "Reply depth exceeds the allowed limit") - return redirect(article.url) + form.add_error(None, "Reply depth exceeds the allowed limit") + return self._render_article_with_errors(request, article, form) comment.save() messages.success(request, "Your comment is awaiting moderation") return redirect(f"{article.url}?commented=1") - messages.error(request, "Please correct the form errors") - return redirect(article.url) + return self._render_article_with_errors(request, article, form) diff --git a/apps/core/tests/test_performance.py b/apps/core/tests/test_performance.py index 229a83d..00be558 100644 --- a/apps/core/tests/test_performance.py +++ b/apps/core/tests/test_performance.py @@ -72,3 +72,4 @@ def test_read_time_benchmark(benchmark): result = benchmark(article._compute_read_time) assert result >= 1 + assert benchmark.stats.stats.mean < 0.05 diff --git a/templates/blog/article_page.html b/templates/blog/article_page.html index 3500be1..76d47e3 100644 --- a/templates/blog/article_page.html +++ b/templates/blog/article_page.html @@ -69,12 +69,20 @@ {% empty %}No comments yet.
{% endfor %} + {% if comment_form and comment_form.errors %} +