test(files): cover binary editor UI

Opens icon.png and asserts the routed editor renders the binary
branch of overlay_file_editor.html: replace-zone present, save
button labelled "Replace" and disabled on open, download link
pointing back at /files/download.

The same /files/edit route serves both text and binary modes — the
server picks the template branch from is_editable() + a magic-byte
check. Without this test, a regression that flipped a binary file
into the text branch would mean rendering raw PNG bytes inside an
editable textarea (and a misleadingly working save button).

Also asserts no textarea[data-rel-path] is in the DOM, so a future
regression that left both branches enabled fails loudly.

Per docs/superpowers/plans/2026-05-17-files-overlay-e2e-handoff.md.

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

View file

@ -175,3 +175,60 @@ def test_create_new_file_409_askConflict_keep_both(page: Page, files_overlay_ser
expect( expect(
page.locator('.file-tree-row-file[data-target-path="cfg (1)"]') page.locator('.file-tree-row-file[data-target-path="cfg (1)"]')
).to_be_visible(timeout=5000) ).to_be_visible(timeout=5000)
def test_open_binary_file_renders_replace_ui(page: Page, files_overlay_server) -> None:
"""Open icon.png and assert the routed editor renders the binary
branch of overlay_file_editor.html replace-zone present, save
button labelled "Replace" and disabled until a file is queued or
the filename is edited.
The same `/files/edit?path=...` route serves both text and binary
modes; the server picks the template branch based on is_editable +
a magic-byte check. This test pins the binary contract: the user
cannot save by accident on a fresh open, and the queue UI is wired
correctly.
Pins:
* .files-editor-binary[data-rel-path="icon.png"] exists (the
data-rel-path stable hook for save logic).
* Save button has visible text "Replace" + the `disabled`
attribute is set on open.
* .files-editor-replace-zone + .files-editor-replace-browse +
the hidden file <input> exist.
* Download link points back at /files/download?path=icon.png.
"""
base = files_overlay_server["base_url"]
overlay_id = files_overlay_server["overlay_id"]
_open_overlay(page, base, overlay_id)
page.click('button.file-tree-name-button[data-target-path="icon.png"]')
fragment = page.locator("#files-editor-fragment")
expect(fragment).to_be_visible(timeout=5000)
binary_panel = page.locator('.files-editor-binary[data-rel-path="icon.png"]')
expect(binary_panel).to_be_visible(timeout=5000)
save_btn = page.locator(".files-editor-save")
expect(save_btn).to_have_text("Replace")
expect(save_btn).to_be_disabled()
expect(page.locator(".files-editor-replace-zone")).to_be_visible()
expect(page.locator(".files-editor-replace-browse")).to_be_visible()
# The file input is type=file hidden — Playwright's "visible"
# assertions treat hidden inputs as not visible, so check
# attached + the type instead.
expect(page.locator(".files-editor-replace-input")).to_have_attribute(
"type", "file"
)
# Download link points back at the overlay's /files/download.
download = page.locator("a.files-editor-download")
expect(download).to_have_attribute(
"href", f"/overlays/{overlay_id}/files/download?path=icon.png"
)
# In binary mode there's no <textarea data-rel-path> — only the
# binary panel carries the rel-path. Catches a regression where
# the server accidentally rendered the text branch for a binary
# file (which would mean an editable textarea full of PNG bytes).
assert page.locator("textarea[data-rel-path]").count() == 0