CyberAg uses a three-layer test pyramid: **Vitest** (unit/integration), **Storybook** (visual + interaction), and **Playwright** (E2E).
Quick start
# All unit tests (Turbo fan-out)
npm test
# UI component tests only
npm run test --workspace=@cyberag/ui
# Storybook (manual + interaction stories)
npm run storybook
# E2E (requires Docker + LocalStack)
npm run test:e2e
# Everything
npm run test:all
Prerequisites
Layer
Requirements
Vitest
Node 20+, npm ci
Storybook
None beyond install
E2E
Docker, LocalStack on port 4566, seeded data
Local E2E setup
# Start LocalStack + deploy + seed
export GEMINI_API_KEY=your-key # or set a dummy key for non-AI flows
npm run local:up
npm run local:deploy
npm run local:seed
# Run E2E (starts console on :3002 automatically)
npm run test:e2e
Skip infra when already running:
E2E_SKIP_SETUP=1 npm run test:e2e
Package coverage
Workspace
Runner
Location
@cyberag/ui
Vitest + RTL + vitest-axe
packages/ui/src/**/*.test.tsx
@cyberag/sdk
Vitest
packages/sdk/src/index.test.ts
@cyberag/platform-auth
Vitest
packages/platform-auth/src/index.test.ts
@cyberag/detection-core
Vitest
packages/detection-core/test/
@cyberag/guardrail-core
Vitest
packages/guardrail-core/src/index.test.ts
@cyberag/wrapsec-adapter
Vitest
packages/wrapsec-adapter/test/
@cyberag/api
Vitest
services/api/src/router.test.ts
@cyberag/eval
Vitest
services/eval/src/parse.test.ts
@cyberag/guardrail-gateway
Vitest smoke
services/guardrail-gateway/src/handler.test.ts
@cyberag/replay
Vitest smoke
services/replay/src/handler.test.ts
@cyberag/connectors
Vitest smoke
services/connectors/src/handler.test.ts
@cyberag/e2e
Playwright
e2e/tests/
Python SDK
pytest
integrations/python/tests/
UI component conventions
Colocate tests: Button.tsx → Button.test.tsx
Use render from packages/ui/src/test/render.tsx
Assert behavior + accessibility (getByRole, vitest-axe for interactive primitives)
Mock heavy deps (recharts, @xyflow/react) in domain tests
CI matrix
Job
Command
Trigger
build
npm run build && npm run lint && npm run test
every PR
build (storybook)
npm run build-storybook --workspace=@cyberag/ui
every PR
python-tests
pytest integrations/python/tests
every PR
e2e
Playwright P0 specs + Docker
PR + main
e2e-ai
Playwright AI specs
nightly / manual
E2E spec map
Spec
Flow
p0-navigation
All 18 console routes render
p0-kill-switch
Activate/deactivate global kill switch
p0-gateway
Benign ALLOW + injection BLOCK
p0-policies
Create new policy
p0-violations
Triage open violation
ai/ask
Ask page (requires real GEMINI_API_KEY)
Out of scope (root CI)
WrapSec subtree pytest (integrations/wrapsec/tests/) — separate workflow under integrations/wrapsec/.github/