Abbenay Tests
July 17, 2026 · View on GitHub
Test Structure
This project follows the "hybrid" test layout:
- Unit tests live co-located with the source code (
src/**/*.test.ts) - Integration tests live in a separate
tests/folder inside each package
packages/daemon/
├── src/
│ ├── core/
│ │ ├── mock.ts
│ │ ├── mock.test.ts <- Unit test (co-located)
│ │ ├── config.ts
│ │ ├── config.test.ts <- Unit test (co-located)
│ │ ├── tool-registry.test.ts <- Unit test (glob matching, registry)
│ │ ├── tool-approval.test.ts <- Unit test (3-tier approval logic)
│ │ ├── session-store.test.ts <- Unit test (session CRUD, index)
│ │ └── session-summarizer.test.ts <- Unit test (periodic summary logic)
│ ├── daemon/
│ │ ├── chat-prompt.test.ts <- Unit test (parseApprovalInput)
│ │ └── web/
│ │ └── openai-compat.test.ts <- Unit test (OpenAI format mapping)
│ └── state.test.ts <- Unit test (DaemonState)
├── tests/
│ └── integration/
│ ├── grpc-streaming.test.ts <- Integration (real gRPC server/client)
│ ├── grpc-tls.test.ts <- TLS bind policy + SetSecret over TLS
│ ├── grpc-real-service.test.ts <- Real service RPCs
│ ├── web-sse.test.ts <- Integration (real Express + HTTP)
│ ├── openai-compat.test.ts <- Integration (OpenAI-compat API)
│ ├── sessions.test.ts <- Integration (session CRUD + chat SSE)
│ └── helpers/
│ └── mock-daemon.ts <- Shared mock gRPC server
├── vitest.config.ts
└── package.json
Running Tests
# Run all daemon tests (unit + integration)
cd packages/daemon
npm test
# Run with verbose output
npx vitest run --reporter verbose
# Run only unit tests
npx vitest run src/
# Run only integration tests
npx vitest run tests/
# Watch mode
npx vitest
Test Layers
Layer 1: Unit Tests (co-located)
Pure unit tests with no I/O, no network, no processes.
| File | What it covers |
|---|---|
src/core/mock.test.ts | Mock engine: echo, fixed, error, empty, slow modes |
src/core/config.test.ts | Config loading, merging, validation |
src/core/config-schema.test.ts | Zod ConfigFile / PolicyConfig schemas (types, field injection) |
src/core/tool-registry.test.ts | Glob matching, tool registration, resolution, policy filtering |
src/core/tool-approval.test.ts | Shared validator: disabled / auto_approve / require_approval / default ask |
src/daemon/mcp-server.test.ts | MCP authorizeAndExecute honors tool_policy (no bypass) |
src/state.test.ts | DaemonState: provider listing, model listing, chat flow |
src/daemon/chat-prompt.test.ts | parseApprovalInput case-sensitive routing |
src/daemon/web/openai-compat.test.ts | OpenAI format mapping: models, finish reasons, stream chunks, complete responses |
src/daemon/web/validate-body.test.ts | HTTP body parse helpers + workspace path allowlist / traversal |
src/core/session-store.test.ts | SessionStore: CRUD, appendMessage, updateTitle, updateSummary, index consistency |
src/core/session-summarizer.test.ts | generateSessionSummary, maybeSummarize interval logic, error handling |
Layer 2: Integration Tests
Tests that start real servers, make real HTTP/gRPC calls.
| File | What it covers |
|---|---|
tests/integration/grpc-streaming.test.ts | gRPC unary RPCs + streaming + cancellation + concurrency |
tests/integration/grpc-tls.test.ts | gRPC TLS bind policy + SetSecret/GetSecret over TLS |
tests/integration/grpc-bind-e2e.test.ts | Subprocess E2E: localhost OK, 0.0.0.0 refuse, TLS/insecure + consumers/open-auth |
tests/integration/consumer-auth.test.ts | Consumer capability gating on sensitive RPCs |
src/daemon/server/consumer-auth.test.ts | Unit: timing-safe tokens, fail-closed bind, capability matrix |
tests/integration/web-sse.test.ts | Web API endpoints + SSE chat + config Zod validation / workspace allowlist |
tests/integration/openai-compat.test.ts | OpenAI-compatible API: /v1/models, streaming, non-streaming, errors, tool calls |
tests/integration/sessions.test.ts | Session REST API: CRUD endpoints, session chat SSE streaming + persistence |
tests/integration/mcp-http-policy.test.ts | /mcp auth + connection consent + tool_policy E2E |
tests/integration/http-security.test.ts | HTTP auth, CORS, bind defaults, dashboard login |
tests/integration/discover-models-auth.test.ts | discover-models: reject ?apiKey=; accept X-Api-Key / body |
Mock Engine
The mock engine (mock/echo, mock/fixed, mock/error, etc.) is a real engine
registered in core/engines.ts. No API keys or network needed. Use it for end-to-end testing:
# Chat with the mock engine via web API
curl -X POST http://localhost:8787/api/chat \
-H 'Content-Type: application/json' \
-d '{"model":"mock/echo","messages":[{"role":"user","content":"Hello!"}]}'
VS Code Extension Tests
The extension uses @vscode/test-cli with Mocha to run tests inside a real VS Code instance.
cd packages/vscode
npm test
On headless Linux: xvfb-run -a npm test
Test Structure
packages/vscode/
├── src/test/
│ ├── extension.test.ts <- Smoke tests (activation, commands, config)
│ ├── helpers/
│ │ ├── mockDaemonClient.ts <- Stub DaemonClient with test data
│ │ └── mockWebview.ts <- Stub vscode.Webview with message recorder
│ └── webviews/
│ ├── getNonce.test.ts <- Pure function (nonce generation)
│ ├── getWebviewContent.test.ts <- HTML template generation
│ ├── providerHandler.test.ts <- Provider message handler
│ └── chatHandler.test.ts <- Chat message handler
└── .vscode-test.mjs <- Test runner config
Smoke Tests
| Test | What it covers |
|---|---|
extension.test.ts | Extension activation, command registration, chat view, config defaults |
Webview Handler Tests
Handler tests mock the DaemonClient and vscode.Webview to test message routing, data transformation, and error handling without a running daemon.
| Test | What it covers |
|---|---|
getNonce.test.ts | Nonce format (32 hex chars), uniqueness |
getWebviewContent.test.ts | HTML structure, CSP headers, nonce injection, panel-specific assets |
providerHandler.test.ts | Ready message routing, engine listing, model discovery with credentials, config forwarding, error handling |
chatHandler.test.ts | Ready message routing, model listing, session create/delete, stream cancellation, error handling |
Mock Helpers
mockDaemonClient.ts— Creates a stubDaemonClientwith empty default return values. Override individual methods per test.mockWebview.ts— Creates a stubvscode.Webviewthat records allpostMessage()calls in a.messagesarray for assertion.
Adding Tests
Daemon tests
New unit tests should be co-located with their source files (e.g., src/core/foo.test.ts).
New integration tests should go in packages/daemon/tests/integration/.
VS Code extension tests
New webview handler tests go in packages/vscode/src/test/webviews/.
New test helpers go in packages/vscode/src/test/helpers/.