diff --git a/l4d2web/tests/e2e/test_files_overlay.py b/l4d2web/tests/e2e/test_files_overlay.py index adb538a..e1c9b54 100644 --- a/l4d2web/tests/e2e/test_files_overlay.py +++ b/l4d2web/tests/e2e/test_files_overlay.py @@ -73,3 +73,46 @@ def test_edit_text_file_save_round_trip(page: Page, files_overlay_server) -> Non # Modal close is async (await postJson then closeRouted()). expect(page.locator("#modal-container")).to_be_hidden(timeout=5000) assert (overlay_root / "server.cfg").read_text() == new_content + + +def test_create_new_file_routed(page: Page, files_overlay_server) -> None: + """Click `+ new file` at the overlay root, fill the routed + new-file editor, click Create, and assert the file lands on disk + AND the row appears in the tree. + + The routed new-file modal is the SAME template as the edit modal + (overlay_file_editor.html with is_new=True). The differences this + test exercises: + * textarea has data-rel-path="" — routedSaveClicked branches on + the empty value into the "compose fullPath from filename" + path, not the rename-on-save path. + * Save button reads "Create", not "Save". + * scheduleRefresh(parentOf(fullPath)) fires after POST — for a + root-level file that's refreshFolder("") which re-fetches the + whole root listing; the new row should appear without a page + reload. + """ + 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[data-action="new-file"][data-target-path=""]') + _wait_for_routed_editor(page) + # Confirm the fragment opened in is_new mode (empty rel-path). + assert page.locator('textarea[data-rel-path=""]').count() == 1 + + new_filename = "new-file.cfg" + new_content = 'sv_cheats 1\nmp_gamemode versus\n' + page.fill('input[data-editor-filename]', new_filename) + page.evaluate("(text) => window.__filesEditor.setContent(text)", new_content) + + page.click(".files-editor-save") + + expect(page.locator("#modal-container")).to_be_hidden(timeout=5000) + assert (overlay_root / new_filename).read_text() == new_content + # Tree refresh is debounced 50ms then HTMX-fetched — wait for the + # new row to appear rather than asserting synchronously. + expect( + page.locator(f'.file-tree-row-file[data-target-path="{new_filename}"]') + ).to_be_visible(timeout=5000)