test(files): cover Escape closes editor with no stale state

Opens server.cfg, drives the CM6 controller to a dirty buffer,
presses Escape to close without saving, then reopens the same file
and asserts the editor shows the original disk content — not the
discarded buffer.

Pins two invariants: native <dialog>'s cancel→close path stays
intact (no JS shortcut around Escape), and the reopened editor
fetches a FRESH fragment via htmx.ajax with CM6 re-mounting on
the new textarea. A regression that cached buffer state to "feel
snappy" would fail this test loudly.

Per docs/superpowers/plans/2026-05-17-files-overlay-e2e-handoff.md
(Tier 2 case B).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-17 19:17:21 +02:00
parent b222fdc918
commit a6be29c6d2
No known key found for this signature in database

View file

@ -412,3 +412,44 @@ def test_share_url_deep_link_reopens_editor(page: Page, files_overlay_server) ->
_wait_for_routed_editor(page)
assert page.locator('textarea[data-rel-path="server.cfg"]').count() == 1
def test_modal_close_on_escape_preserves_no_state(page: Page, files_overlay_server) -> None:
"""Open server.cfg, drive the CM6 controller to a dirty buffer,
press Escape to close the modal without saving, then reopen the
same file and assert the editor shows the original disk content
not the dirty buffer the user just discarded.
Pins two invariants:
* modals.js's `cancel` → preventDefault → close() path on
`<dialog id="modal-container">` actually closes the modal on
Escape (no JS shortcuts away from the native behavior).
* The reopened editor fetches a fresh fragment via htmx.ajax;
the CM6 controller re-mounts on the FRESH textarea (seeded
from disk content), not a stale cache of the prior session.
A regression that survived the close event e.g., a future commit
that cached buffer state in a module-scope variable to "feel
snappy" — would surface here as the dirty content reappearing.
"""
base = files_overlay_server["base_url"]
overlay_id = files_overlay_server["overlay_id"]
overlay_root = files_overlay_server["overlay_root"]
original_content = (overlay_root / "server.cfg").read_text()
_open_overlay(page, base, overlay_id)
# --- First open: type something but don't save ----------------------
page.click('button.file-tree-name-button[data-target-path="server.cfg"]')
_wait_for_routed_editor(page)
dirty = "DIRTY UNSAVED BUFFER " + "x" * 40
page.evaluate("(t) => window.__filesEditor.setContent(t)", dirty)
page.keyboard.press("Escape")
expect(page.locator("#modal-container")).to_be_hidden(timeout=5000)
# Disk must still hold the original — never saved.
assert (overlay_root / "server.cfg").read_text() == original_content
# --- Reopen and confirm CM6 starts fresh from disk ------------------
page.click('button.file-tree-name-button[data-target-path="server.cfg"]')
_wait_for_routed_editor(page)
reopened = page.evaluate("() => window.__filesEditor.getValue()")
assert reopened == original_content