diff --git a/l4d2web/tests/e2e/test_files_overlay.py b/l4d2web/tests/e2e/test_files_overlay.py index f7a42b7..60c76e5 100644 --- a/l4d2web/tests/e2e/test_files_overlay.py +++ b/l4d2web/tests/e2e/test_files_overlay.py @@ -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