test(dashboard): serve vendored assets in the playwright route harness

The three playwright dashboard suites intercept every request with
page.route("**/*") and fall through to route.continue_() for anything they do
not recognise. While the templates pointed at unpkg.com and cdn.tailwindcss.com
those fall-throughs were absolute URLs that CI fetched over the real network,
so Alpine loaded by accident. Now that the assets are relative they resolve
against the harness's fake origin (127.0.0.1:8788, headroom.local), where
nothing is listening: Alpine never loads, every `<template x-if>` under <main>
renders nothing, and the tests that expect content fail while the ones that
expect an empty state pass vacuously.

Serve /dashboard/static/* from STATIC_DIR in the harness. The suites no longer
depend on outbound network access to a public CDN.
This commit is contained in:
Tejas Chopra 2026-08-03 05:49:03 -07:00
parent 372a4e04bc
commit c7f574caf1
3 changed files with 36 additions and 3 deletions

View file

@ -17,7 +17,11 @@ from urllib.parse import urlsplit
import pytest
from headroom.dashboard import get_dashboard_html
from tests.test_dashboard_cache_ttl_playwright import _sample_history, _sample_stats
from tests.test_dashboard_cache_ttl_playwright import (
_fulfill_static_asset,
_sample_history,
_sample_stats,
)
playwright = pytest.importorskip("playwright.sync_api")
Page = playwright.Page
@ -52,6 +56,8 @@ def _install_dashboard_routes(page: Page, stats: dict) -> None:
if path in ("/dashboard", "/"):
route.fulfill(status=200, content_type="text/html", body=dashboard_html)
return
if _fulfill_static_asset(route, path):
return
if "/stats-history" in path:
route.fulfill(status=200, content_type="application/json", body=json.dumps(history))
return

View file

@ -18,7 +18,11 @@ from urllib.parse import urlsplit
import pytest
from headroom.dashboard import get_dashboard_html
from tests.test_dashboard_cache_ttl_playwright import _sample_history, _sample_stats
from tests.test_dashboard_cache_ttl_playwright import (
_fulfill_static_asset,
_sample_history,
_sample_stats,
)
playwright = pytest.importorskip("playwright.sync_api")
Page = playwright.Page
@ -56,6 +60,8 @@ def _install_dashboard_routes(page: Page, stats: dict) -> None:
if path in ("/dashboard", "/"):
route.fulfill(status=200, content_type="text/html", body=dashboard_html)
return
if _fulfill_static_asset(route, path):
return
if "/stats-history" in path:
route.fulfill(status=200, content_type="application/json", body=json.dumps(history))
return

View file

@ -9,7 +9,7 @@ from urllib.parse import urlsplit
import pytest
from headroom.dashboard import get_dashboard_html
from headroom.dashboard import STATIC_DIR, get_dashboard_html
playwright = pytest.importorskip("playwright.sync_api")
Page = playwright.Page
@ -153,6 +153,25 @@ def _sample_history() -> dict:
}
def _fulfill_static_asset(route, path: str) -> bool: # type: ignore[no-untyped-def]
"""Serve the vendored dashboard JS from disk; True when it handled the route.
The harnesses in this file and its siblings intercept every request, so the
dashboard's relative asset URLs would otherwise fall through to a real fetch
against a fake origin with nothing listening. Alpine has to load: every
section of <main> lives inside a `<template x-if>`, which renders nothing at
all without it, so an empty <main> is the symptom to look for here.
"""
if not path.startswith("/dashboard/static/"):
return False
route.fulfill(
status=200,
content_type="text/javascript",
body=(STATIC_DIR / Path(path).name).read_bytes(),
)
return True
def _install_dashboard_routes(page: Page) -> None:
stats = _sample_stats()
history = _sample_history()
@ -167,6 +186,8 @@ def _install_dashboard_routes(page: Page) -> None:
if path in ("/dashboard", "/"):
route.fulfill(status=200, content_type="text/html", body=dashboard_html)
return
if _fulfill_static_asset(route, path):
return
if "/stats-history" in path:
route.fulfill(
status=200,