refactor: drawer delete-impact modal extracted to Jinja partial (T110.3)
The modal HTML was assembled via raw f-string concatenation in ``delete_preview``. Move it to a dedicated Jinja2 partial (``chat/templates/_delete_impact_modal.html``) and render via ``TEMPLATES.TemplateResponse``. Jinja2 autoescape now handles HTML safety automatically — the explicit ``html.escape()`` calls added in T110.2 (and the ``import html``) become redundant and are removed in this commit. Net behavioural change: attribute quoting style flips from single to double quotes (Jinja default) — the existing T98.4 substring-based assertions are unaffected, and the new T110.3 test pins the double-quoted shape so future regressions surface. Test: tests/test_drawer_phase4.py::test_delete_impact_modal_uses_jinja_partial.
This commit is contained in:
@@ -458,6 +458,35 @@ def test_t98_4_delete_invokes_rewind_and_drops_cascade(client, tmp_path):
|
||||
assert row is None, f"event {ev_id} should have been deleted"
|
||||
|
||||
|
||||
def test_delete_impact_modal_uses_jinja_partial(client, tmp_path):
|
||||
"""T110.3: the modal HTML is rendered from a Jinja partial
|
||||
(`_delete_impact_modal.html`) rather than f-string concatenation in
|
||||
Python. Verify the partial-rendered shape: the wrapping
|
||||
``delete-impact-modal`` div, the cascade list, and the confirm form.
|
||||
|
||||
The partial inherits Jinja2 autoescape so HTML safety follows
|
||||
automatically — the explicit ``html.escape()`` calls from T110.2
|
||||
become redundant once this lands.
|
||||
"""
|
||||
db = tmp_path / "test.db"
|
||||
_seed_chat(db)
|
||||
user_id, _bot_id = _seed_turns(db)
|
||||
|
||||
response = client.get(
|
||||
f"/chats/chat_bot_a/drawer/turn/delete-preview/{user_id}"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
body = response.text
|
||||
|
||||
# Markup shape that the partial produces. Double-quoted attributes
|
||||
# signal Jinja rendering (the prior f-string used single quotes).
|
||||
assert '<div class="delete-impact-modal">' in body
|
||||
assert '<ul class="delete-impact-cascade">' in body
|
||||
# The confirm form still posts to the same delete route.
|
||||
assert f"/chats/chat_bot_a/drawer/turn/delete/{user_id}" in body
|
||||
assert "Confirm delete" in body
|
||||
|
||||
|
||||
def test_delete_impact_modal_escapes_user_controllable_strings(client, tmp_path):
|
||||
"""T110.2: defense-in-depth — fields embedded in the modal HTML come
|
||||
from event payloads (turn prose, scene timestamps, etc.) which are
|
||||
|
||||
Reference in New Issue
Block a user