Back to docs
Guide 11

Testing

Simmetric Chat uses Jest 30 with the @swc/jest transform (unit + integration) and Playwright (E2E), orchestrated by Turborepo. The root jest.config.cjs aggregates the 5 projects (shared, server, frontend, collector, widget).

4 min read

Simmetric Chat uses Jest 30 with the @swc/jest transform (unit + integration) and Playwright (E2E), orchestrated by Turborepo. The root jest.config.cjs aggregates the 5 projects (shared, server, frontend, collector, widget).

Levels

LevelRunnerDBScope
UnitJest 30 + @swc/jestmock Prisma (no DB)services, utilities, validation
IntegrationJest 30 + supertest 7real PostgreSQL workerroutes, middleware, DB flows
E2EPlaywrightcomplete appuser-facing UI (13 specs)

Unit tests

Prisma mocked via jest.mock (no real DB). Covers: services (RAG, backup, encryption, DLP, agent budget), utilities (RBAC, license, chunker), Zod schemas, webhook dispatch. Server unit: moduleNameMapper mocks for the heavy deps (uuid, jsdom, pdfjs-dist, pg-boss...) and @simmetric-chat/shared mapped to shared/dist (rebuild shared after edits - the turbo ^build gotcha; frontend/widget map the source).

bash
pnpm test               # all 5 packages via turbo (Postgres-free)
pnpm test:all           # same suites via jest.config.cjs (plain Jest)
pnpm --filter server test
pnpm --filter shared test

Conventions: *.test.ts files in __tests__/ next to the source (frontend *.test.tsx in a jsdom environment). Snapshots only for deterministic outputs (never LLM). Use jest.mock('../prisma') to isolate the DB; a server unit file starts with import "./helpers/setupEnv".

Integration tests

Real PostgreSQL worker DB on localhost:5434 (per .env.test). The simmetricchat_test_template template is cloned per test file (path SHA-256) for isolation. Covers Express routes (supertest 7), middleware (auth, RBAC, license, rate limit), complete DB flows (workspaces, chats, documents, backup restore). The collector has a dedicated integration suite on the pgvector_test DB, port 5433 (jest.config.integration.cjs).

Setup:

  • Test env variables (test DB, test JWT_SECRET, shared secrets - tracked in packages/server/.env.test).
  • Migrations applied to the template (jest.globalSetup.js: migrate deploy + seed); each test file clones a fresh DB; teardown drops the template.
  • Sequential runs (suites may read the cached DATABASE_URL - known debt).
bash
pnpm --filter server test:integration          # --forceExit included
pnpm --filter collector test:integration

E2E (Playwright)

13 specs in e2e/. They cover user-facing flows: auth/admin, chat streaming, chat edit/regenerate, document upload → RAG, unified upload destinations, widget embed, MCP install (marketplace lifecycle), MCP pin/use, admin settings nav, synthesis run, RBAC UI (project sidebar), theme switch.

bash
pnpm test:e2e
# with UI: pnpm exec playwright test --ui

Prerequisites: app up (pnpm dev or compose), migrated DB, built @simmetric-chat/shared + frontend, browsers installed (pnpm exec playwright install). The root .env must also carry WIDGET_API_KEY and API_KEY_HMAC_SECRET: the widget webServer fails loud at boot without them (Zod .min(1)), and the plaintext must match the api_keys row e2e/globalSetup.ts seeds. Playwright boots the 3 web servers itself (backend tsx, frontend vite preview, widget - all reuseExistingServer); globalSetup is idempotent (setup wizard → admin/admin123, E2E widget + E2E_WIDGET_ID, mustChangePassword reset). Config in playwright.config.ts (30s timeout, 2 retries). Enterprise-gated specs self-skip without LICENSE_KEY.

Coverage

No coverage thresholds are configured in any Jest config and coverage is not a CI gate; the closest quality gate is the test-count guard (3900-declaration cap for the community suite). Local reports:

bash
pnpm test:all -- --coverage
pnpm --filter server test -- --coverage

Manual testing focus on the critical services: agent orchestrator, hybridSearch, backup, encryption, license, RBAC.

Critical-flow tests (checklist)

  • Hybrid RAG: vector + FTS + RRF fusion + archive fallback (D-07) + embedding-mismatch guard (D-01) + metadata filtering (pre-filters + SQL predicates + server-side backstop).
  • ReAct agent: loop detection, unknown-tool circuit breaker (BOT-03), budget wallclock/token/context, per-user concurrency, provider fallback.
  • Widget: anonymous session + expiry, double-layer rate limit (per-widget burst + per-widget+IP daily), lead capture, IDOR prevention (WidgetWorkspace whitelist), transparent SSE proxy.
  • Backup: dump → archive → checksum → upload retry → restore atomicity (psql single-transaction) + retention.
  • MCP: transport fallback (D-09), install/uninstall, pin resolution (strict union), health check (pg-boss cron, 3-level staleness).
  • License: graceful Enterprise→Community degradation, 402 gating, numeric limits.

Debugging tests

bash
pnpm --filter server test -- src/__tests__/auth.test.ts      # by file (positional)
pnpm --filter server test -- -t "test name"                  # by name
pnpm --filter server test:integration -- --runInBand         # serial for DB
DEBUG=1 pnpm test:e2e -- --headed

CI

Turborepo caches tests; typical pipeline: lint → typecheck → test → test:integration → build → test:e2e. The integration worker DB requires a PostgreSQL service in CI (pgvector/pgvector:pg16). Test-relevant jobs: test-unit (+ air-gap grep gate + FTS locale gate + test-count guard), test-airgap (NETWORK_EGRESS_BLOCKED=1), test-e2e, build (+ freshness check).

v0.28.1 Provenance

StatementSource
E2E: WIDGET_API_KEY + API_KEY_HMAC_SECRET required (widget webServer loud-fail; match to the seeded api_keys row)docs/DEVELOPMENT.md (E2E, row-time)

Operational reference - Simmetric Chat v0.28.1 (docs updated 2026-10-02, census SHA `aca5b8ff`).