SPB Git forge

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

127commits 1branches 0releases
24.7 MBsize
maindefault branch
11 days agolast push
JavaScript 53.7% Python 38.3% CSS 4.6% TypeScript 3.1%
4.5 KB · 110 lines python
Raw Blame History
1"""SPA fallback (core/spa.py) on a bare FastAPI app with a fake Vite dist: known routes → 200 shell, unknown → 404 shell,2real files served, hashed assets immutable + gzipped, API paths never answered by the shell."""3from __future__ import annotations45import pytest6from fastapi import FastAPI7from fastapi.testclient import TestClient8from starlette.middleware.gzip import GZipMiddleware91011@pytest.fixture(scope="module")12def spa_client(tmp_path_factory, app):13    from core import errors, http, spa14    dist = tmp_path_factory.mktemp("dist")15    (dist / "index.html").write_text("<!doctype html><html><body><div id=root></div><script>/*shell*/</script></body></html>" + " " * 1500)16    (dist / "assets").mkdir()17    (dist / "assets" / "index-abc123.js").write_text("console.log('hfmd');" * 200)18    (dist / "favicon.svg").write_text("<svg xmlns='http://www.w3.org/2000/svg'></svg>")19    (dist / "docs").mkdir()20    (dist / "docs" / "index.html").write_text("<!doctype html><html><body>prerendered docs</body></html>")21    (dist / "limits.html").write_text("<!doctype html><html><body>prerendered limits</body></html>")22    a = FastAPI(openapi_url=None, docs_url=None, redoc_url=None)23    errors.install(a)24    a.add_middleware(GZipMiddleware, minimum_size=1024)2526    @a.get("/v1/ping")27    def ping():28        return {"ok": True}2930    @a.get("/health")31    def health():32        return {"status": "ok"}3334    http.install(a)35    assert spa.install(a, dist) is True36    with TestClient(a) as c:37        yield c383940def test_root_and_known_routes_serve_shell_200(spa_client):41    for path in ("/", "/playground", "/charts", "/signin", "/dashboard", "/dashboard/keys", "/admin/users", "/integrations/mcp", "/pricing"):42        r = spa_client.get(path)43        assert r.status_code == 200, path44        assert "text/html" in r.headers["content-type"] and "<div id=root>" in r.text45        assert r.headers["Cache-Control"] == "no-cache"464748def test_prerendered_shells_served(spa_client):49    r = spa_client.get("/docs")50    assert r.status_code == 200 and "prerendered docs" in r.text51    r = spa_client.get("/docs/errors")          # no prerender → shell, still a known route52    assert r.status_code == 200 and "<div id=root>" in r.text53    r = spa_client.get("/limits")54    assert r.status_code == 200 and "prerendered limits" in r.text555657def test_unknown_route_is_404_with_shell(spa_client):58    r = spa_client.get("/this-page-does-not-exist")59    assert r.status_code == 40460    assert "<div id=root>" in r.text and "text/html" in r.headers["content-type"]61    r = spa_client.get("/dashboardx")62    assert r.status_code == 404636465def test_real_files_served(spa_client):66    r = spa_client.get("/favicon.svg")67    assert r.status_code == 200 and "svg" in r.headers["content-type"]686970def test_assets_immutable_and_gzipped(spa_client):71    r = spa_client.get("/assets/index-abc123.js", headers={"Accept-Encoding": "gzip"})72    assert r.status_code == 20073    assert r.headers["Cache-Control"] == "public, max-age=31536000, immutable"74    assert r.headers.get("Content-Encoding") == "gzip"75    assert r.headers["X-Frame-Options"] == "DENY"76    r = spa_client.get("/assets/missing-000.js")77    assert r.status_code == 40478    assert "Cache-Control" not in r.headers or "immutable" not in r.headers["Cache-Control"]798081def test_html_gets_csp_not_frame_options(spa_client):82    r = spa_client.get("/")83    csp = r.headers["Content-Security-Policy"]84    assert "default-src 'self'" in csp and "frame-ancestors 'none'" in csp and "cdn.jsdelivr.net" not in csp85    assert "X-Frame-Options" not in r.headers86    assert r.headers["Strict-Transport-Security"].startswith("max-age=")878889def test_api_paths_never_get_the_shell(spa_client):90    r = spa_client.get("/v1/does-not-exist")91    assert r.status_code == 404 and r.headers["content-type"].startswith("application/json")92    assert r.json()["error"]["code"] == "NOT_FOUND"93    r = spa_client.get("/v1/ping")94    assert r.status_code == 200 and r.json() == {"ok": True}95    r = spa_client.get("/openapi.json")96    assert r.status_code == 404 and r.headers["content-type"].startswith("application/json")97    r = spa_client.get("/swagger")98    assert r.status_code == 404 and r.headers["content-type"].startswith("application/json")99100101def test_login_redirect(spa_client):102    r = spa_client.get("/login", follow_redirects=False)103    assert r.status_code == 301 and r.headers["Location"] == "/signin"104105106def test_path_traversal_blocked(spa_client):107    r = spa_client.get("/../../etc/passwd")108    assert r.status_code in (404, 200)109    assert "root:" not in r.text110