Skip to main content
Version: Next

Testing & CI

Test suites

CommandScope
pnpm typechecktsc --noEmit over src/.
pnpm testVitest - 162 passing tests across 22 default suites, plus 6 env-gated live integration tests (skipped by default).
SUPABASE_RUN_LIVE_TESTS=true pnpm testVitest - full 168 tests including live integration against Supabase Cloud.
npx vite buildProduction build (two chunks: main + observability).
cargo test --workspaceRust unit tests in both crates.

TypeScript typecheck

pnpm typecheck runs tsc --noEmit with the strict settings from tsconfig.json (strict, noImplicitAny, strictNullChecks, etc.). It does not emit output: it only checks types.

Vitest

pnpm test runs Vitest (environment: 'node', includes src/**/*.{test,spec}.ts).

The current suite covers:

SuiteTestsCovering
telemetry-contract.test.ts4TelemetrySnapshot shape contract
cost.test.ts21Price book, regex priority, cost backfill, rollup
auth-session.test.ts8Supabase Auth session + graceful offline degradation
evaluator-dal.test.ts7Evaluator + annotation config DAL offline paths
session-compare.test.ts7Project state, session rollup, region activity
typesense-client.test.ts7Typesense client offline degradation
search-schema.test.ts8TRACE_SPANS_SCHEMA + DOCS_SCHEMA validation
search-indexer.test.ts19Pure mapping helpers (rowToTraceDoc, markdownToDocs, etc.)
search.test.ts15debounced multi_search, normalizeHits, buildSearchRequest
search-box.test.ts4Search box offline degradation
search-sync.test.ts10SyncQueue throttle, bulkUpsert REST client, JSONL formatter
chat-client.test.ts2EXEPERT Brain Chat request shaping, selected model IDs, and SSE parsing
chat-models.test.ts4Chat model normalization, provider inference, and local icon mapping
chat-diagnostics.test.ts2Chat diagnostics redaction and payload bounding
vercel-analytics.test.ts2Vercel Web Analytics and Speed Insights injector boot guards
trace-to-brain.test.ts13Trace → brain mapping
openinference-parser.test.ts7OpenInference attribute parsing
live-brain.test.ts4Realtime live-brain bridge
waterfall.test.ts4Waterfall node builder
tracer.test.ts4SDK tracer flush + span builder
error-reporting.test.ts3reportError routing
dal-smoke.test.ts7DAL graceful offline degradation
dal-live.test.ts4Live Supabase integration (env-gated, skipped by default)
realtime-live.test.ts2Live Realtime end-to-end (env-gated, skipped by default)

All DAL functions return Result<T>: the offline tests assert that every function degrades to a typed supabase.not_configured error rather than throwing.

Live integration tests (env-gated)

src/__tests__/dal-live.test.ts hits the real Supabase Cloud project to verify seeded data shape. src/__tests__/realtime-live.test.ts verifies the Realtime channel can deliver postgres_changes INSERT events end-to-end (writes a test span, waits for delivery, then cleans up). Both suites are gated by SUPABASE_RUN_LIVE_TESTS=true and skipped by default; in a normal pnpm test run the 6 tests report as skipped (not failures), keeping the suite green.

Config prerequisite for Realtime test: the spans table must be in the Supabase Realtime publication (supabase_realtime). This is already configured via ALTER PUBLICATION supabase_realtime ADD TABLE spans;. If the test fails with a FK/constraint error, verify publication membership with SELECT * FROM pg_publication_tables WHERE pubname = 'supabase_realtime';.

warning

Live tests use SUPABASE_SERVICE_ROLE_KEY (bypasses RLS) rather than the anon key because the seeded demo project has owner_id = NULL and RLS policies require is_project_owner(). This is appropriate for data-verification tests and is never the client path.

Environment variables in tests

vitest.config.ts uses loadEnv(mode, process.cwd(), '') (from Vite) to expose all .env variables into process.env.* via Vite's define transform. This is required for live tests to access SUPABASE_SERVICE_ROLE_KEY, which is not a VITE_-prefixed variable. The config reads .env, .env.local, .env.test, and .env.test.local. Confirm secrets are appropriate before running in CI.

loadEnv with empty prefix intentionally broadens the scope from the previous config that passed no env vars. This is by design for the live test path: the test harness only runs when explicitly opted in via the gate flag.

.env.test: a committed file that overrides VITE_TYPESENSE_* to empty strings during Vitest runs. This ensures the offline degradation tests (typesense-client, search-box, search) see "Typesense unconfigured" regardless of the real .env credentials. vi.stubEnv cannot override Vite's compile-time import.meta.env replacement, so .env.test is the idiomatic Vite solution: Vite loads .env.test automatically in test mode, applying the override before the define transform bakes in the values.

Rust tests

cargo test --workspace runs the unit tests in both crates:

  • rust/brain_sim: region classification, Bezier endpoint correctness, and signal-pool acquire/release.
  • rust/brain_engine: the standalone scoring heuristics.

Continuous integration

.github/workflows/ci.yml runs on push and PR to main/master/revamp with four jobs:

JobWhat it does
typecheckRuns pnpm typecheck.
testRuns Vitest.
buildInstalls Rust + the wasm32-unknown-unknown target + wasm-pack, runs pnpm build, and uploads dist.
cargoRuns cargo build and cargo test --workspace --locked.

The build job mirrors a clean local build: it provisions the Rust toolchain before building because pnpm build compiles the WASM module first.

Before opening a PR, run all four locally:

pnpm typecheck
pnpm test
npx vite build
cargo test --workspace

When live credentials are set, also run the gated integration tests:

SUPABASE_RUN_LIVE_TESTS=true pnpm test

For a full end-to-end check that also exercises the WASM and Vite pipeline, run pnpm build (compiles Rust → WASM, then runs Vite).