from __future__ import annotations from pathlib import Path from fastapi import FastAPI from fastapi.testclient import TestClient from k1link.web.frontend_assets import ( HASHED_ASSET_IMMUTABLE, HTML_NO_STORE, ControlStationStaticFiles, frontend_build_id, ) def _frontend(tmp_path: Path) -> Path: frontend = tmp_path / "dist" assets = frontend / "assets" assets.mkdir(parents=True) (frontend / "index.html").write_text( """ """, encoding="utf-8", ) (assets / "index-dT7dN-y4.js").write_text("export {};", encoding="utf-8") (assets / "runtime.js").write_text("export {};", encoding="utf-8") return frontend def test_frontend_build_id_is_exact_hashed_entry_module(tmp_path: Path) -> None: frontend = _frontend(tmp_path) assert frontend_build_id(frontend) == "/assets/index-dT7dN-y4.js" (frontend / "index.html").write_text( '', encoding="utf-8", ) assert frontend_build_id(frontend) is None def test_spa_shell_is_no_store_and_only_hashed_assets_are_immutable( tmp_path: Path, ) -> None: frontend = _frontend(tmp_path) app = FastAPI() app.mount("/", ControlStationStaticFiles(directory=frontend, html=True)) client = TestClient(app) shell = client.get("/") hashed = client.get("/assets/index-dT7dN-y4.js") unhashed = client.get("/assets/runtime.js") assert shell.status_code == 200 assert shell.headers["cache-control"] == HTML_NO_STORE assert hashed.status_code == 200 assert hashed.headers["cache-control"] == HASHED_ASSET_IMMUTABLE assert unhashed.status_code == 200 assert "immutable" not in unhashed.headers.get("cache-control", "")