Testing
Simmetric Chat usa Jest 30 con trasformazione @swc/jest (unit + integration) e Playwright (E2E), orchestrati da Turborepo. La root jest.config.cjs aggrega i 5 progetti (shared, server, frontend, collector, widget).
Simmetric Chat usa Jest 30 con trasformazione @swc/jest (unit + integration) e Playwright (E2E), orchestrati da Turborepo. La root jest.config.cjs aggrega i 5 progetti (shared, server, frontend, collector, widget).
Livelli
| Livello | Runner | DB | Scope |
|---|---|---|---|
| Unit | Jest 30 + @swc/jest | mock Prisma (no DB) | servizi, utility, validazione |
| Integration | Jest 30 + supertest 7 | PostgreSQL worker reale | route, middleware, flussi DB |
| E2E | Playwright | app completa | UI user-facing (13 spec) |
Unit test
Mock di Prisma via jest.mock (no DB reale). Test di: servizi (RAG, backup, encryption, DLP, agent budget), utility (RBAC, license, chunker), schema Zod, webhook dispatch. Server unit: mock moduleNameMapper per le dipendenze pesanti (uuid, jsdom, pdfjs-dist, pg-boss...) e mapping @simmetric-chat/shared → shared/dist (ribuilda shared dopo edit - gotcha turbo ^build; frontend/widget mappano la source).
pnpm test # tutti i 5 package via turbo (Postgres-free)
pnpm test:all # stesse suite via jest.config.cjs (Jest puro)
pnpm --filter server test
pnpm --filter shared testConvenzioni: file *.test.ts in __tests__/ accanto al sorgente (frontend *.test.tsx in ambiente jsdom). Snapshot solo per output deterministici (non per LLM). Usa jest.mock('../prisma') per isolare DB; un file server unit inizia con import "./helpers/setupEnv".
Integration test
Worker DB PostgreSQL reale su localhost:5434 (per .env.test). Template simmetricchat_test_template clonato per-test-file (SHA-256 del path) per isolamento. Test di route Express (supertest 7), middleware (auth, RBAC, license, rate limit), flussi DB completi (workspace, chat, documenti, backup restore). Il collector ha una suite integration dedicata su pgvector_test porta 5433 (jest.config.integration.cjs).
Setup:
- Variabili env di test (DB test,
JWT_SECRETtest, secret shared - tracciate inpackages/server/.env.test). - Migrazioni applicate al template (
jest.globalSetup.js: migrate deploy + seed); ogni test file clona in DB fresh; teardown droppa il template. - Run sequenziali (le suite possono leggere il
DATABASE_URLcacheato - debito noto).
pnpm --filter server test:integration # --forceExit incluso
pnpm --filter collector test:integrationE2E (Playwright)
13 spec in e2e/. Coprono flussi user-facing: 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.
pnpm test:e2e
# con UI: pnpm exec playwright test --uiPrerequisiti: app up (pnpm dev o compose), DB migrated, @simmetric-chat/shared + frontend build, browser installati (pnpm exec playwright install). La .env del root deve anche portare WIDGET_API_KEY e API_KEY_HMAC_SECRET: il webServer widget fallisce loud al boot senza (Zod .min(1)), e il plaintext deve matchare la row api_keys che e2e/globalSetup.ts semina. Playwright avvia da solo i 3 web server (backend tsx, frontend vite preview, widget - tutti reuseExistingServer); globalSetup è idempotente (setup wizard → admin/admin123, widget E2E + E2E_WIDGET_ID, reset mustChangePassword). Config in playwright.config.ts (30s timeout, retries 2). Le spec enterprise-gated self-skip senza LICENSE_KEY.
Coverage
Nessuna soglia di coverage configurata nei config Jest e la coverage non è un gate CI; il gate di qualità più vicino è il test-count guard (cap 3900 dichiarazioni per la suite community). Report locali:
pnpm test:all -- --coverage
pnpm --filter server test -- --coverageFocus di battitura sui servizi critici: agent orchestrator, hybridSearch, backup, encryption, license, RBAC.
Test di flussi critici (checklist)
- RAG ibrido: vector + FTS + RRF fusion + fallback archive (D-07) + guard embedding mismatch (D-01) + metadata filtering (pre-filter + SQL predicate + backstop server-side).
- Agent ReAct: loop detection, circuit breaker unknown-tool (BOT-03), budget wallclock/token/context, per-user concurrency, fallback provider.
- Widget: sessione anonima + scadenza, rate limit doppio layer (burst per-widget + daily per-widget+IP), lead capture, IDOR prevention (whitelist
WidgetWorkspace), proxy SSE trasparente. - Backup: dump → archive → checksum → upload retry → restore atomicity (psql single-transaction) + retention.
- MCP: transport fallback (D-09), install/uninstall, pin resolution (union strict), health check (pg-boss cron, staleness a 3 livelli).
- License: graceful degradation Enterprise→Community, gating 402, limiti numerici.
Debug test
pnpm --filter server test -- src/__tests__/auth.test.ts # per file (posizionale)
pnpm --filter server test -- -t "nome test" # per nome
pnpm --filter server test:integration -- --runInBand # seriale per DB
DEBUG=1 pnpm test:e2e -- --headedCI
Turborepo cachea test; pipeline tipica: lint → typecheck → test → test:integration → build → test:e2e. Worker DB per integration richiede service PostgreSQL in CI (pgvector/pgvector:pg16). Job test-relevant: test-unit (+ air-gap grep gate + FTS locale gate + test-count guard), test-airgap (NETWORK_EGRESS_BLOCKED=1), test-e2e, build (+ freshness check).
Provenienza v0.28.1
| Affermazione | Fonte |
|---|---|
E2E: WIDGET_API_KEY + API_KEY_HMAC_SECRET obbligatori (widget webServer loud-fail; match alla row api_keys seedata) | docs/DEVELOPMENT.md (§ E2E, row-time) |
Riferimento operativo - Simmetric Chat v0.28.1 (docs aggiornate 2026-10-02, census SHA `aca5b8ff`).
Cross-link
- Convenzioni: 10 - Development
- Internals testati: 05 - Feature Guide