Testing
Running Tests
pnpm test # all 151 tests, 15 suites
pnpm test:watch # watch mode with re-run on change
Test Suites
| Suite | Tests | What It Covers |
|---|---|---|
config.test.ts | 22 | Config loading, validation, env var resolution, .codex path walk-up, fail_mode, readFailMode |
airs-client.test.ts | 9 | SDK wrapper, prompt/response scanning, block verdicts |
scanner.test.ts | 22 | Observe/enforce/bypass modes, UX messages, separator width, fail-open/fail-closed, correlation pass-through |
code-extractor.test.ts | 10 | Fenced, indented, heuristic extraction, mixed content |
codex-adapter.test.ts | 6 | Exact Codex stdout shapes per event (block/deny/stop) |
tool-name-parser.test.ts | 11 | mcp__server__tool parsing, isMcpToolName |
hooks-config.test.ts | 13 | hooks.json build/merge/remove, idempotency, foreign-hook preservation, absolute-node commands |
circuit-breaker.test.ts | 7 | State transitions, cooldown, probe success/failure |
content-limits.test.ts | 6 | Skip/truncate thresholds |
dlp-masking.test.ts | 8 | Enforcement priority, content masking |
logger.test.ts | 5 | JSON Lines output, content stripping, directory creation |
log-rotation.test.ts | 3 | Size threshold, rotation, missing file handling |
hooks-integration.test.ts | 21 | End-to-end Codex JSON contract (tsx + compiled JS) |
bundles.test.ts | 5 | Standalone bundle runs from a temp dir, size budget |
cli.test.ts | 3 | CLI dispatch, usage, invoking-cwd behavior |
Integration Tests
The hooks-integration.test.ts suite runs actual hook scripts with piped JSON:
// Runs: echo '{"prompt":"..."}' | npx tsx src/hooks/user-prompt-submit.ts
// And: echo '{"prompt":"..."}' | node dist/hooks/user-prompt-submit.js
These verify the real Codex contract end-to-end, including JSON parsing, config loading, fail-open and fail-closed behavior, the PreToolUse silent-allow rule, and the Stop JSON-only stdout rule.
The bundles.test.ts suite goes one step further: it spawns each minified dist/hooks/*.mjs bundle from an OS temp directory with no node_modules or NODE_PATH available, proving the bundles are genuinely self-contained.
Mocking
- AIRS API: Not mocked in integration tests -- hooks fail-open when the API is unreachable, which validates the fail-mode design
- SDK: Mocked via
vi.mock("@cdot65/prisma-airs-sdk")in unit tests (airs-client.test.ts); the scanner suite mockssrc/airs-client.ts - File system: Tests use temporary directories (
test/.tmp-*) cleaned up inafterEach
Adding Tests
- Create
test/<module>.test.tsmatching the source file - Use vitest's
describe/it/expectAPI - Clean up any temp files in
afterEach - For integration tests, use
spawnSyncto run hooks with piped JSON