diff --git a/apps/core/tests/test_message_handling.py b/apps/core/tests/test_message_handling.py index 839018c..8a49177 100644 --- a/apps/core/tests/test_message_handling.py +++ b/apps/core/tests/test_message_handling.py @@ -15,7 +15,6 @@ from apps.core.middleware import AdminMessageGuardMiddleware def admin_message_test_view(request): - messages.success(request, "Page 'Test page' has been updated.") messages.success(request, "Page 'Test page' has been updated.") messages.success(request, "Page 'Test page' has been published.") return render(request, "wagtailadmin/base.html", {}) @@ -60,24 +59,6 @@ def test_admin_message_guard_preserves_admin_messages(rf): assert remaining[0].message == "Page 'Test page' has been updated." -@pytest.mark.django_db -@override_settings(ROOT_URLCONF="apps.core.tests.test_message_handling") -def test_wagtail_admin_template_deduplicates_consecutive_messages(client, django_user_model): - admin = django_user_model.objects.create_superuser( - username="admin-messages", - email="admin-messages@example.com", - password="admin-pass", - ) - client.force_login(admin) - - response = client.get("/cms/__tests__/admin-messages/") - content = response.content.decode() - - assert response.status_code == 200 - assert content.count("has been updated.") == 1 - assert content.count("has been published.") == 1 - - @pytest.mark.django_db @override_settings(ROOT_URLCONF="apps.core.tests.test_message_handling") def test_admin_messages_have_auto_clear(client, django_user_model): @@ -94,3 +75,46 @@ def test_admin_messages_have_auto_clear(client, django_user_model): assert response.status_code == 200 assert "data-w-messages-auto-clear-value" in content + + +@pytest.mark.django_db +@override_settings(ROOT_URLCONF="apps.core.tests.test_message_handling") +def test_server_rendered_messages_have_auto_dismiss_script(client, django_user_model): + """Server-rendered messages must include an inline script that removes them + after a timeout, because the w-messages Stimulus controller only auto-clears + messages added via JavaScript — not ones already in the HTML.""" + admin = django_user_model.objects.create_superuser( + username="admin-dismiss", + email="admin-dismiss@example.com", + password="admin-pass", + ) + client.force_login(admin) + + response = client.get("/cms/__tests__/admin-messages/") + content = response.content.decode() + + assert response.status_code == 200 + # Messages are rendered with the data-server-rendered marker + assert "data-server-rendered" in content + # The auto-dismiss script targets those markers + assert "querySelectorAll" in content + assert "[data-server-rendered]" in content + + +@pytest.mark.django_db +@override_settings(ROOT_URLCONF="apps.core.tests.test_message_handling") +def test_admin_messages_render_all_messages(client, django_user_model): + """All messages should be rendered (no de-duplication filtering).""" + admin = django_user_model.objects.create_superuser( + username="admin-render", + email="admin-render@example.com", + password="admin-pass", + ) + client.force_login(admin) + + response = client.get("/cms/__tests__/admin-messages/") + content = response.content.decode() + + assert response.status_code == 200 + assert "has been updated." in content + assert "has been published." in content diff --git a/templates/wagtailadmin/base.html b/templates/wagtailadmin/base.html index e413fb8..bf8b044 100644 --- a/templates/wagtailadmin/base.html +++ b/templates/wagtailadmin/base.html @@ -8,25 +8,24 @@ {% keyboard_shortcuts_dialog %}
+ {# Always show messages div so it can be appended to by JS #}
    {% if messages %} {% for message in messages %} {% message_level_tag message as level_tag %} - {% ifchanged level_tag message.extra_tags message %} -
  • - {% if level_tag == "error" %} - {% icon name="warning" classname="messages-icon" %} - {% elif message.extra_tags == "lock" %} - {% icon name="lock" classname="messages-icon" %} - {% elif message.extra_tags == "unlock" %} - {% icon name="lock-open" classname="messages-icon" %} - {% else %} - {% icon name=level_tag classname="messages-icon" %} - {% endif %} - {{ message }} -
  • - {% endifchanged %} +
  • + {% if level_tag == "error" %} + {% icon name="warning" classname="messages-icon" %} + {% elif message.extra_tags == "lock" %} + {% icon name="lock" classname="messages-icon" %} + {% elif message.extra_tags == "unlock" %} + {% icon name="lock-open" classname="messages-icon" %} + {% else %} + {% icon name=level_tag classname="messages-icon" %} + {% endif %} + {{ message }} +
  • {% endfor %} {% endif %}
@@ -41,6 +40,27 @@
+ {% comment %} + Wagtail's w-messages Stimulus controller only auto-clears messages + added dynamically via JavaScript (the add() method). Server-rendered + messages — the
  • elements above — have no connect() handler and + sit in the DOM forever. This script schedules their removal so they + auto-dismiss after the same timeout used for dynamic messages. + {% endcomment %} + + {% block content %}{% endblock %}