"""The app served from a subpath, driven by a real browser. The ASGI tests (`test_base_path_app.py`) prove the SERVER routes under a prefix. They cannot prove the half that runs in the browser: that the rewritten shell's bundle actually loads, that React Router's `basename` resolves a deep link, and that every request the SPA makes carries the prefix. Get any of those wrong and the symptom is a blank page in a deployment no other test runs in — which is precisely how this class of bug reaches someone's server. No fake Plex here on purpose: an unconfigured app still serves the shell, mounts React, routes, and calls the API, which is the whole surface under test. Adding a seeded server would test the wizard. """ from __future__ import annotations from collections.abc import Iterator import pytest from playwright.sync_api import Browser from shortlist.server.main import create_app from tests.e2e.conftest import _free_port from tests.uvicorn_thread import UvicornThread pytestmark = pytest.mark.e2e BASE = "/shortlist" @pytest.fixture def prefixed_url(tmp_path, monkeypatch) -> Iterator[str]: """A real server that believes it lives at `/shortlist`, as a forwarding proxy would present it.""" monkeypatch.setenv("APP_BASE_PATH", BASE) server = UvicornThread(create_app(config_dir=tmp_path), _free_port()) server.start() server.wait_until_up(f"{BASE}/api/system/health") yield f"http://127.0.0.1:{server.port}" server.stop() def _watched_page(browser: Browser, url: str): """A page that records everything that would show up as "it just doesn't work".""" page = browser.new_context().new_page() page.set_default_timeout(60_000) console_errors: list[str] = [] failed: list[str] = [] requested: list[str] = [] page.on("console", lambda m: console_errors.append(m.text) if m.type == "error" else None) page.on("requestfailed", lambda r: failed.append(r.url)) page.on("request", lambda r: requested.append(r.url)) return page, console_errors, failed, requested def test_the_app_boots_and_talks_to_itself_under_the_prefix(browser: Browser, prefixed_url: str) -> None: page, console_errors, failed, requested = _watched_page(browser, prefixed_url) page.goto(f"{prefixed_url}{BASE}/", wait_until="networkidle") # The shell alone renders an empty