Quellcode durchsuchen

fix(tests): make SPA cache-header tests work without a built frontend

  backend/tests/integration/test_static_html_cache_headers.py asserted
  that "/", "/spoolbuddy/", and "/printers" return text/html with
  Cache-Control: no-cache, must-revalidate. The Dockerfile.test
  backend-test target intentionally doesn't bake in the built frontend
  (saves ~30s of build time per test run), so static/index.html doesn't
  exist inside the container. The route handlers correctly fall through
  to their "frontend not built" JSON branches, and the test fails with
  "non-HTML content-type: application/json" — latent since the test was
  added in e9200449 (Apr 26).

  Add a fake_static_index fixture that creates a tmp dir with a one-line
  <!doctype html> stub and monkeypatches app_settings.static_dir to it.
  Both call sites are patched (config.settings and main.app_settings) in
  case a future refactor splits the singleton. The test continues to hit
  the real serve_frontend / serve_spa route handlers and validates the
  real cache-header contract — just doesn't depend on a built bundle
  being present.

  Verified passing both with and without static/index.html present.
maziggy vor 3 Wochen
Ursprung
Commit
0b92172322
1 geänderte Dateien mit 30 neuen und 1 gelöschten Zeilen
  1. 30 1
      backend/tests/integration/test_static_html_cache_headers.py

+ 30 - 1
backend/tests/integration/test_static_html_cache_headers.py

@@ -42,9 +42,38 @@ HTML_ROUTES = [
 ]
 ]
 
 
 
 
+@pytest.fixture
+def fake_static_index(monkeypatch, tmp_path):
+    """Provide a minimal ``static/index.html`` so the route handlers don't
+    fall through to their "frontend not built" JSON branch.
+
+    The ``backend-test`` Dockerfile.test target intentionally doesn't bake
+    in the built frontend (saves ~30 s of build time per test run), and
+    contributors running ``pytest backend/tests/`` from a checkout without
+    a prior ``npm run build`` would also miss it.  The test asserts the
+    cache-header contract on the index.html serve path, not the bundle
+    contents — so a one-line stub is enough to exercise the real route
+    handlers in ``main.py:serve_frontend`` / ``main.py:serve_spa`` against
+    a real ``index.html`` on disk.
+    """
+    from backend.app import main as main_mod
+    from backend.app.core import config as config_mod
+
+    static_dir = tmp_path / "static"
+    static_dir.mkdir()
+    (static_dir / "index.html").write_text("<!doctype html><title>stub</title>")
+
+    monkeypatch.setattr(config_mod.settings, "static_dir", static_dir)
+    # main.py imports `settings as app_settings`, so the route handlers
+    # resolve `app_settings.static_dir` per request. Patch the import-site
+    # binding too in case future refactors stop sharing the singleton.
+    monkeypatch.setattr(main_mod.app_settings, "static_dir", static_dir)
+    return static_dir
+
+
 @pytest.mark.asyncio
 @pytest.mark.asyncio
 @pytest.mark.parametrize(("path",), HTML_ROUTES)
 @pytest.mark.parametrize(("path",), HTML_ROUTES)
-async def test_index_html_emits_no_cache_directive(async_client: AsyncClient, path: str):
+async def test_index_html_emits_no_cache_directive(async_client: AsyncClient, fake_static_index, path: str):
     """Every index.html serve must emit ``Cache-Control: no-cache,
     """Every index.html serve must emit ``Cache-Control: no-cache,
     must-revalidate`` — kiosks rely on this to pick up new builds without
     must-revalidate`` — kiosks rely on this to pick up new builds without
     operator intervention."""
     operator intervention."""