From b222fdc918b3d0bb4bb012b1eaa106efb89101bc Mon Sep 17 00:00:00 2001 From: mwiegand Date: Sun, 17 May 2026 19:16:51 +0200 Subject: [PATCH] test(files): cover share-URL deep link reopens editor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Navigates directly to /overlays/?modal= and asserts the routed editor auto-opens on the right file. This is the central guarantee of the URL-addressable modals spec — copy the URL, share it, and the recipient lands on the same modal state. A regression in modals.js's DOMContentLoaded bootstrap (the URLSearchParams.get("modal") → fetchAndShowRouted chain) would silently dead-link every shared URL; this test fails loudly instead. Per docs/superpowers/plans/2026-05-17-files-overlay-e2e-handoff.md (Tier 2, highest-value case). Co-Authored-By: Claude Opus 4.7 (1M context) --- l4d2web/tests/e2e/test_files_overlay.py | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/l4d2web/tests/e2e/test_files_overlay.py b/l4d2web/tests/e2e/test_files_overlay.py index e9752df..a1ee693 100644 --- a/l4d2web/tests/e2e/test_files_overlay.py +++ b/l4d2web/tests/e2e/test_files_overlay.py @@ -14,6 +14,8 @@ docs/superpowers/plans/2026-05-17-files-overlay-e2e-handoff.md. """ from __future__ import annotations +import urllib.parse + import pytest from playwright.sync_api import Page, expect @@ -383,3 +385,30 @@ def test_filename_rename_on_save(page: Page, files_overlay_server) -> None: expect( page.locator('.file-tree-row-file[data-target-path="server.cfg"]') ).to_have_count(0) + + +def test_share_url_deep_link_reopens_editor(page: Page, files_overlay_server) -> None: + """Navigate directly to /overlays/?modal= + and assert the routed editor auto-opens for the right file. This + is the central guarantee of the URL-addressable modals spec — copy + the current URL, paste it in a new tab (or share it), and the + modal reopens. Without this test, a regression in modals.js's + DOMContentLoaded bootstrap (the `URLSearchParams.get("modal") → + fetchAndShowRouted` chain) would silently make every shared link + dead. + + The `?modal=` param holds the UNENCODED routed path; URLSearchParams + decodes it for us. We pass the URL-encoded version through quote() + so the surrounding URL stays valid. + """ + base = files_overlay_server["base_url"] + overlay_id = files_overlay_server["overlay_id"] + + login(page, base) + modal_path = f"/overlays/{overlay_id}/files/edit?path=server.cfg" + page.goto( + f"{base}/overlays/{overlay_id}?modal={urllib.parse.quote(modal_path)}" + ) + + _wait_for_routed_editor(page) + assert page.locator('textarea[data-rel-path="server.cfg"]').count() == 1