dnscms: upgrade to wagtail 8 and django 6.1, test upgrade-sensitive admin surfaces
dnscms / ci (push) Successful in 59s
dnscms / ci (push) Successful in 59s
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"""Admin view tests: the choose-parent redirect and a smoke test over the
|
||||
admin URLs served by our viewsets."""
|
||||
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
import pytest
|
||||
from django.urls import reverse
|
||||
|
||||
from tests.conftest import EventIndexFactory, GenericPageFactory
|
||||
|
||||
|
||||
def _parsed(response):
|
||||
url = urlparse(response["Location"])
|
||||
return url.path, parse_qs(url.query)
|
||||
|
||||
|
||||
def test_choose_parent_no_valid_parent_renders_form(admin_client, db):
|
||||
response = admin_client.get(reverse("events:choose_parent"))
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_choose_parent_single_parent_redirects_with_next(admin_client, event_index):
|
||||
response = admin_client.get(reverse("events:choose_parent"))
|
||||
|
||||
assert response.status_code == 302
|
||||
path, query = _parsed(response)
|
||||
assert path == reverse("wagtailadmin_pages:add", args=["events", "eventpage", event_index.pk])
|
||||
assert query["next"] == [reverse("events:index")]
|
||||
|
||||
|
||||
def test_choose_parent_multiple_parents_shows_form_then_redirects(admin_client, event_index):
|
||||
# max_count=1 stops a second EventIndex being created through the admin,
|
||||
# but the view logic only cares how many instances exist.
|
||||
second_index = EventIndexFactory(parent=event_index.get_parent(), slug="events-2")
|
||||
|
||||
response = admin_client.get(reverse("events:choose_parent"))
|
||||
assert response.status_code == 200
|
||||
|
||||
response = admin_client.post(reverse("events:choose_parent"), {"parent_page": second_index.pk})
|
||||
assert response.status_code == 302
|
||||
path, query = _parsed(response)
|
||||
assert path == reverse("wagtailadmin_pages:add", args=["events", "eventpage", second_index.pk])
|
||||
assert query["next"] == [reverse("events:index")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"url_name",
|
||||
[
|
||||
"wagtailadmin_home",
|
||||
"events:index",
|
||||
"events:choose_parent",
|
||||
"associations:index",
|
||||
"news:index",
|
||||
"venues:index",
|
||||
"wagtailimages:index",
|
||||
"wagtailsnippets_events_eventorganizer:list",
|
||||
"association_chooser:choose",
|
||||
"event_organizer_chooser:choose",
|
||||
],
|
||||
)
|
||||
def test_admin_views_render(admin_client, db, url_name):
|
||||
response = admin_client.get(reverse(url_name))
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_page_edit_view_renders_with_custom_editor_assets(admin_client, home_page):
|
||||
"""The page editor must load with our Draftail feature and editor JS wired in."""
|
||||
page = GenericPageFactory(parent=home_page, slug="edit-me")
|
||||
|
||||
response = admin_client.get(reverse("wagtailadmin_pages:edit", args=[page.pk]))
|
||||
|
||||
assert response.status_code == 200
|
||||
content = response.content.decode()
|
||||
assert "button-link" in content # dnscms.rich_text feature on the editor
|
||||
assert "js/page-editor.js" in content # insert_editor_js hook output
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Tests for the custom "button" rich text link feature (dnscms/rich_text.py).
|
||||
|
||||
- DB HTML -> front-end HTML (expand_db_html)
|
||||
- DB HTML -> ContentState (editor load)
|
||||
- ContentState -> DB HTML (editor save)
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from wagtail.admin.rich_text.converters.contentstate import ContentstateConverter
|
||||
from wagtail.rich_text import expand_db_html
|
||||
|
||||
DB_HTML = '<a linktype="button" data-href="/billetter/">Kjøp billett</a>'
|
||||
|
||||
|
||||
def test_expand_db_html_rewrites_button_link():
|
||||
assert expand_db_html(DB_HTML) == '<a class="button" href="/billetter/">Kjøp billett</a>'
|
||||
|
||||
|
||||
def test_expand_db_html_escapes_href():
|
||||
html = expand_db_html('<a linktype="button" data-href="/x/?a=1&b=2">B</a>')
|
||||
assert html == '<a class="button" href="/x/?a=1&b=2">B</a>'
|
||||
|
||||
|
||||
def test_expand_db_html_missing_href_falls_back_to_empty():
|
||||
assert expand_db_html('<a linktype="button">B</a>') == '<a class="button" href="">B</a>'
|
||||
|
||||
|
||||
def test_db_html_to_contentstate():
|
||||
"""Editor load: the linktype anchor becomes a MUTABLE BUTTON entity."""
|
||||
converter = ContentstateConverter(features=["button-link"])
|
||||
contentstate = json.loads(converter.from_database_format(DB_HTML))
|
||||
|
||||
entities = list(contentstate["entityMap"].values())
|
||||
assert len(entities) == 1
|
||||
entity = entities[0]
|
||||
assert entity["type"] == "BUTTON"
|
||||
assert entity["mutability"] == "MUTABLE"
|
||||
assert entity["data"] == {"url": "/billetter/"}
|
||||
|
||||
block = contentstate["blocks"][0]
|
||||
assert block["text"] == "Kjøp billett"
|
||||
assert len(block["entityRanges"]) == 1
|
||||
|
||||
|
||||
def test_contentstate_roundtrip_preserves_button_link():
|
||||
"""Editor load + save must not lose or mangle the stored linktype anchor."""
|
||||
stored = f'<p data-block-key="abc12">{DB_HTML}</p>'
|
||||
converter = ContentstateConverter(features=["button-link"])
|
||||
roundtripped = converter.to_database_format(converter.from_database_format(stored))
|
||||
assert roundtripped == stored
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Tests for the admin-UI hooks in dnscms/wagtail_hooks.py.
|
||||
|
||||
Both hooks run against Wagtail admin internals (the page action menu, editor
|
||||
JS injection) — the surface most likely to churn silently across Wagtail
|
||||
upgrades.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from dnscms.wagtail_hooks import editor_js, make_publish_default_action
|
||||
|
||||
|
||||
@dataclass
|
||||
class FakeMenuItem:
|
||||
name: str
|
||||
|
||||
|
||||
def _names(items):
|
||||
return [item.name for item in items]
|
||||
|
||||
|
||||
def test_make_publish_default_action_moves_publish_first():
|
||||
menu_items = [
|
||||
FakeMenuItem("action-save-draft"),
|
||||
FakeMenuItem("action-submit"),
|
||||
FakeMenuItem("action-publish"),
|
||||
FakeMenuItem("action-unpublish"),
|
||||
]
|
||||
|
||||
make_publish_default_action(menu_items, request=None, context={})
|
||||
|
||||
assert _names(menu_items) == [
|
||||
"action-publish",
|
||||
"action-save-draft",
|
||||
"action-submit",
|
||||
"action-unpublish",
|
||||
]
|
||||
|
||||
|
||||
def test_make_publish_default_action_without_publish_is_a_noop():
|
||||
menu_items = [FakeMenuItem("action-save-draft"), FakeMenuItem("action-submit")]
|
||||
|
||||
make_publish_default_action(menu_items, request=None, context={})
|
||||
|
||||
assert _names(menu_items) == ["action-save-draft", "action-submit"]
|
||||
|
||||
|
||||
def test_editor_js_returns_script_tag():
|
||||
html = editor_js()
|
||||
assert html.startswith("<script src=")
|
||||
assert "js/page-editor.js" in html
|
||||
Reference in New Issue
Block a user