diff --git a/l4d2web/tests/e2e/test_files_overlay.py b/l4d2web/tests/e2e/test_files_overlay.py index f369e55..e9752df 100644 --- a/l4d2web/tests/e2e/test_files_overlay.py +++ b/l4d2web/tests/e2e/test_files_overlay.py @@ -336,3 +336,50 @@ def test_new_folder_then_delete(page: Page, files_overlay_server) -> None: assert not (overlay_root / folder_name).exists() # The tree refresh removes the row. expect(folder_row).to_have_count(0, timeout=5000) + + +def test_filename_rename_on_save(page: Page, files_overlay_server) -> None: + """Open server.cfg, change the filename input to server-renamed.cfg, + and click Save. The single POST /files/save call performs an atomic + rename + write; the test asserts the disk reflects both the new + name and the original content, AND that the tree row swaps over. + + This pins the rename-on-save branch in routedSaveClicked (the + non-is_new code path that diffs originalLeaf vs editedFilename + and emits `new_path`). A regression that dropped the rename + payload would silently leave the original file in place — the + "old name gone" + "new name present" assertion pair catches that. + + We do NOT call __filesEditor.setContent here: the rename should + preserve the original textarea-seeded content. If the save handler + accidentally writes an empty body, the content-equality assertion + fails. + """ + 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) + + page.click('button.file-tree-name-button[data-target-path="server.cfg"]') + _wait_for_routed_editor(page) + + new_name = "server-renamed.cfg" + page.fill("input[data-editor-filename]", new_name) + page.click(".files-editor-save") + + expect(page.locator("#modal-container")).to_be_hidden(timeout=5000) + + # Disk: old name gone, new name present with the original content. + assert not (overlay_root / "server.cfg").exists() + assert (overlay_root / new_name).read_text() == original_content + + # Tree refresh runs at parentOf(new_path) = "" (root) — both rows + # come from that same listing, so we wait for the new one and + # assert the old one is gone in the same refresh. + expect( + page.locator(f'.file-tree-row-file[data-target-path="{new_name}"]') + ).to_be_visible(timeout=5000) + expect( + page.locator('.file-tree-row-file[data-target-path="server.cfg"]') + ).to_have_count(0)