import base64 import hashlib from pathlib import Path from starlette.applications import Starlette from starlette.responses import PlainTextResponse from starlette.routing import Route from starlette.testclient import TestClient from fluksio.spa import Dashboard THEME = "document.documentElement.classList.add('dark')" def _client(dist: Path) -> TestClient: (dist / "assets").mkdir(parents=True) (dist / "index.html").write_text(f"") (dist / "assets" / "app-1a2b.js").write_text("console.log(1)") api = Starlette(routes=[Route("/api/v1/ping", lambda _: PlainTextResponse("api"))]) return TestClient(Dashboard(api, dist)) def test_the_dashboard_and_the_api_share_one_origin(tmp_path: Path) -> None: client = _client(tmp_path) # A client-side route survives a reload, with the inline script admitted. page = client.get("/flows/house") digest = base64.b64encode(hashlib.sha256(THEME.encode()).digest()).decode() assert THEME in page.text assert page.headers["cache-control"] == "no-cache" assert f"'sha256-{digest}'" in page.headers["content-security-policy"] asset = client.get("/assets/app-1a2b.js") assert asset.text == "console.log(1)" assert "immutable" in asset.headers["cache-control"] assert client.get("/api/v1/ping").text == "api" # Nothing outside the build directory is served, only the shell. assert THEME in client.get("/assets/../../etc/passwd").text