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.

FileWhat it covers
src/core/mock.test.tsMock engine: echo, fixed, error, empty, slow modes
src/core/config.test.tsConfig loading, merging, validation
src/core/config-schema.test.tsZod ConfigFile / PolicyConfig schemas (types, field injection)
src/core/tool-registry.test.tsGlob matching, tool registration, resolution, policy filtering
src/core/tool-approval.test.tsShared validator: disabled / auto_approve / require_approval / default ask
src/daemon/mcp-server.test.tsMCP authorizeAndExecute honors tool_policy (no bypass)
src/state.test.tsDaemonState: provider listing, model listing, chat flow
src/daemon/chat-prompt.test.tsparseApprovalInput case-sensitive routing
src/daemon/web/openai-compat.test.tsOpenAI format mapping: models, finish reasons, stream chunks, complete responses
src/daemon/web/validate-body.test.tsHTTP body parse helpers + workspace path allowlist / traversal
src/core/session-store.test.tsSessionStore: CRUD, appendMessage, updateTitle, updateSummary, index consistency
src/core/session-summarizer.test.tsgenerateSessionSummary, maybeSummarize interval logic, error handling

Layer 2: Integration Tests

Tests that start real servers, make real HTTP/gRPC calls.

FileWhat it covers
tests/integration/grpc-streaming.test.tsgRPC unary RPCs + streaming + cancellation + concurrency
tests/integration/grpc-tls.test.tsgRPC TLS bind policy + SetSecret/GetSecret over TLS
tests/integration/grpc-bind-e2e.test.tsSubprocess E2E: localhost OK, 0.0.0.0 refuse, TLS/insecure + consumers/open-auth
tests/integration/consumer-auth.test.tsConsumer capability gating on sensitive RPCs
src/daemon/server/consumer-auth.test.tsUnit: timing-safe tokens, fail-closed bind, capability matrix
tests/integration/web-sse.test.tsWeb API endpoints + SSE chat + config Zod validation / workspace allowlist
tests/integration/openai-compat.test.tsOpenAI-compatible API: /v1/models, streaming, non-streaming, errors, tool calls
tests/integration/sessions.test.tsSession 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.tsHTTP auth, CORS, bind defaults, dashboard login
tests/integration/discover-models-auth.test.tsdiscover-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

TestWhat it covers
extension.test.tsExtension 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.

TestWhat it covers
getNonce.test.tsNonce format (32 hex chars), uniqueness
getWebviewContent.test.tsHTML structure, CSP headers, nonce injection, panel-specific assets
providerHandler.test.tsReady message routing, engine listing, model discovery with credentials, config forwarding, error handling
chatHandler.test.tsReady message routing, model listing, session create/delete, stream cancellation, error handling

Mock Helpers

  • mockDaemonClient.ts — Creates a stub DaemonClient with empty default return values. Override individual methods per test.
  • mockWebview.ts — Creates a stub vscode.Webview that records all postMessage() calls in a .messages array 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/.