test(files): cover binary replace via browse

Opens icon.png, attaches new bytes via Playwright's file chooser
(intercepting the click → hidden-input.click() → OS picker chain),
clicks Replace, and asserts the new bytes land on disk under the
unchanged filename. Covers the multipart /files/replace endpoint and
the click → setRoutedReplacement → save-enabled UI wiring.

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:42:13 +02:00
parent c1ea5eb11e
commit 6b0fbb75bf
No known key found for this signature in database

View file

@ -232,3 +232,48 @@ def test_open_binary_file_renders_replace_ui(page: Page, files_overlay_server) -
# 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
def test_binary_replace_via_browse_writes_new_bytes(page: Page, files_overlay_server) -> None:
"""Open icon.png, click "browse" to attach a new file buffer via
Playwright's file chooser, click Replace, and assert disk reflects
the new bytes. Exercises:
* .files-editor-replace-browse triggers the hidden file input's
click() (line ~140 in files-overlay/editor.js).
* `change` event on the input flows into setRoutedReplacement,
which enables the save button + paints the queued-state UI.
* routedReplaceClicked posts FormData (multipart) to
/files/replace with the original rel-path NOT a rename
and the server streams the upload into place.
"""
base = files_overlay_server["base_url"]
overlay_id = files_overlay_server["overlay_id"]
overlay_root = files_overlay_server["overlay_root"]
_open_overlay(page, base, overlay_id)
page.click('button.file-tree-name-button[data-target-path="icon.png"]')
expect(page.locator('.files-editor-binary[data-rel-path="icon.png"]')).to_be_visible(timeout=5000)
save_btn = page.locator(".files-editor-save")
expect(save_btn).to_be_disabled()
# The browse button calls fileInput.click() in the JS handler —
# Playwright's expect_file_chooser intercepts the resulting OS
# picker so we can hand back a buffer instead of an OS path.
new_bytes = b"\x89PNG\r\n\x1a\nE2E_REPLACED" + b"\x00" * 20
with page.expect_file_chooser() as fc_info:
page.click(".files-editor-replace-browse")
fc_info.value.set_files({
"name": "new-icon.png",
"mimeType": "image/png",
"buffer": new_bytes,
})
# Queueing a file flips the save button enabled.
expect(save_btn).to_be_enabled(timeout=2000)
save_btn.click()
expect(page.locator("#modal-container")).to_be_hidden(timeout=5000)
# The filename on disk stays the same (no rename) — only the bytes
# changed.
assert (overlay_root / "icon.png").read_bytes() == new_bytes