Playwright E2E
Four specs inapp/e2e/ drive the production bundle in headless Chromium and prove the three heavy client subsystems boot and produce output.
The signal. The observability layer keeps an always-on in-memory ring of timing marks (
duckdb_init / first_query / onnx_warmup), recorded regardless of whether a RUM backend is configured, mirrored read-only to window.__OTP_PERF__. The E2E waits on those marks (app/e2e/_helpers.ts) rather than scraping fragile DOM, so a green run means the subsystem actually executed.
Run modes.
Chromium only DuckDB-wasm and onnxruntime-web rely on cross-origin isolation + wasm threads, and Chromium is the reference engine prod is verified against.
vite preview serves with the required COOP/COEP headers (see the preview.headers block in vite.config.ts).Bundle-size budget (blocking)
app/scripts/check_bundle_size.mjs sums the JavaScript bytes in dist/ (raw + gzip + largest single chunk; .wasm binaries excluded) and fails if any metric exceeds app/perf-budget.json.
Current baseline: ~3.0 MB raw / ~0.9 MB gzip of JS across ~70 assets; the largest single chunk is the self-hosted DuckDB worker (~0.75 MB). The committed budget carries 8% headroom so ordinary churn doesn’t flake the gate.
Lighthouse CI (advisory)
app/lighthouserc.json collects Lighthouse on the data-engine-free shell routes (/, /roadmap) so scores reflect bundle/shell health rather than wasm-init variance. All assertions are warn and the step is continue-on-error it surfaces CWV/a11y regressions for review without flaking the build red. The bundle-size script is the hard byte gate.
Coverage thresholds
Floors set just below the current baseline they guard against losing coverage (deleting tests, landing large untested modules), not as an absolute quality bar. Raise them when coverage rises; never lower without cause.The ML floor (25%) reflects only the warehouse-free tests that always run. Data-dependent paths (
train/predict/evaluate/export_onnx) need a populated mart and are enforced locally via make cov-python, not in ml-ci.yml’s fixture-gated subset.Local quick reference
Operator setup
- Add App E2E and App Performance →
perfto branch protection required status checks once they’ve run green on a PR. - After a deliberate bundle change, run
make app-bundle-budget-updateand commit the newperf-budget.jsonin the same PR. - (Optional) Wire
E2E_BASE_URLto thepreview.ymlchannel URL to smoke the actual deployed artefact instead of a localvite preview.
Observability
The
window.__OTP_PERF__ ring the E2E tests wait on, and the SLOs the synthetic monitor enforces.Security
Required branch protection status checks including App E2E and App CI.