name: testing-workflow description: Use when adding or changing tests, or before considering a change done, in ChatbotX. Documents the real verification gate sequence (lint → types → test → coverage), where tests live, the Vitest setup, and the coverage threshold that must not be silently bypassed. Read before writing tests or claiming a task is verified.
Testing Workflow (ChatbotX)
The verification gate every change passes before it is "done". CI currently does not run these (it builds Docker images only), so they are enforced locally — run them yourself, do not assume CI catches regressions.
The gate sequence (run in order, fix before advancing)
- Lint —
pnpm lint(Ultracite/Biome). Usepnpm fixto auto-fix, never hand-format. - Types —
pnpm --filter <app|package> check-typesfor every workspace you touched. - Test — run the affected package's Vitest suite.
- Coverage — keep the 80% threshold (
packages/vitest-config/src/node.ts). Do not setVITEST_SKIP_COVERAGE_THRESHOLDSto dodge it — that silently nulls all thresholds and hides under-coverage.
Where tests live
- App/package/integration-level tests (actions, routes, API behavior, cache, worker behavior, cross-boundary):
<workspace>/__tests__/— e.g.apps/builder/__tests__,apps/worker/__tests__,packages/sdk/__tests__,integrations/messenger/__tests__. - Narrow unit/component tests owned by one module: colocated
src/**/__tests__.
Test design (AAA + behavior names)
- Arrange–Act–Assert structure.
- Name by behavior:
test('throws ChannelError when sourceConversationId is missing'), nottest('works'). - Test the boundary that matters: actions, routes, repositories, worker handlers, channel send/receive.
- Mock the database client for unit tests; use the repository/service layer, never
dbdirectly.
What to test first (highest signal in this repo)
- New oRPC route / server action → its happy path + auth-scoping + one failure path.
- New repository method → query correctness incl.
workspaceIdscoping. - New worker consumer → success / error / retry / idempotency on re-run.
- New channel integration → webhook receive parse + outgoing send mapping.
Stop condition
A change is verified only when lint + the touched packages' check-types + the affected tests all pass, with coverage at/above threshold (not skipped). If you cannot run a gate, say which and why — do not report "verified" on an unrun gate.