SNA

Testing Mock API

Usage for Anthropic/OpenAI mock APIs, runOneshot, and mock server types.

Testing Mock API

startMockAnthropicServer()

declare function startMockAnthropicServer(): Promise<MockServer>;
type MockServer = {
  port: number;
  server: http.Server;
  close: () => void;
  requests: Array<{ model: string; messages: unknown[]; stream: boolean; timestamp: string }>;
  onLog: (handler: (line: string) => void) => void;
};
type MockLogEntry = {
  ts: string;
  type: "request" | "response" | "error" | "info";
  method?: string;
  url?: string;
  model?: string;
  stream?: boolean;
  messageCount?: number;
  userText?: string;
  systemPromptLength?: number;
  replyText?: string;
  requestBody?: unknown;
  error?: string;
  message?: string;
};
import { startMockAnthropicServer } from "@sna-sdk/testing";

const mock = await startMockAnthropicServer();
process.env.ANTHROPIC_BASE_URL = `http://localhost:${mock.port}`;
process.env.ANTHROPIC_API_KEY = "sk-test";

mock.onLog((line) => {
  process.stdout.write(`${line}\n`);
});

try {
  // Run code that expects an Anthropic-compatible API.
} finally {
  mock.close();
}

Behavior:

  • Starts on an available port chosen by the OS. The current implementation does not accept a fixed port option.
  • Provides an Anthropic-compatible POST /v1/messages endpoint.
  • Supports CORS preflight requests.
  • Records parsed requests in mock.requests.
  • Emits JSONL log lines through mock.onLog.
  • For normal text, replies with the last user text reversed. This makes responses deterministic without looking realistic.
  • If tools are declared and the latest user text contains [tool:Name], returns or streams a tool_use block for that tool.
  • Supports streaming SSE and non-streaming JSON responses.

startMockOpenAIServer(options?)

declare function startMockOpenAIServer(options?: MockOpenAIOptions): Promise<MockOpenAIServer>;
type MockOpenAIOptions = {
  models?: Array<{ id: string; owned_by?: string }>;
  responseText?: string | ((ctx: MockOpenAIResponseContext) => string);
  chunkSize?: number;
};
import { startMockOpenAIServer } from "@sna-sdk/testing";

const mock = await startMockOpenAIServer({
  models: [{ id: "gpt-5.4", owned_by: "openai" }],
  responseText: ({ endpoint, userText }) => `${endpoint}: ${userText}`,
});

try {
  const res = await fetch(`${mock.url}/v1/responses`, {
    method: "POST",
    headers: { "Content-Type": "application/json", Authorization: "Bearer sk-test" },
    body: JSON.stringify({ model: "gpt-5.4", input: "hello" }),
  });
  console.log(await res.json());
  console.log(mock.requests[0]);
} finally {
  await mock.close();
}

Behavior:

  • Starts on an available local port and exposes mock.url.
  • Provides GET /v1/models, POST /v1/chat/completions, and POST /v1/responses.
  • Records parsed requests, including authorization, model, stream flag, user text, system prompt length, and the raw request body.
  • Emits JSONL log lines through mock.onLog.
  • Supports non-streaming JSON and streaming SSE for chat completions and responses.
  • By default, replies with the last user text reversed. Use responseText for fixed or per-request output.

runOneshot(cliArgs?)

declare function runOneshot(cliArgs?: string[]): Promise<void>;

Use this when a test should exercise Claude against the mock Anthropic API without starting the full interactive CLI harness.

runOneshot starts the mock server, points ANTHROPIC_BASE_URL at it, runs claude with the provided CLI arguments, captures stdout/stderr, and exits the process with Claude's exit code. It also uses .sna/mock-claude-oneshot as CLAUDE_CONFIG_DIR.

Written files:

FileContents
.sna/mock-claude-stdout.logCaptured Claude stdout.
.sna/mock-claude-stderr.logCaptured Claude stderr.
.sna/mock-claude-oneshot/Temporary Claude config directory.

Instance helpers

generateInstanceName()

Creates a unique test instance name. Use it to avoid log/config directory collisions in parallel tests.

getInstancesDir() / getInstanceDir(name)

Resolve the storage path used by the testing CLI. Prefer these helpers over hard-coded .sna/instances paths.

listInstances()

Returns test instance metadata stored on disk. Useful for debug UIs and cleanup scripts.

readInstanceMeta(name) / writeInstanceMeta(name, meta)

Read and write test instance metadata. Use them when extra state must be attached to an isolated CLI run.

removeInstance(name)

Removes an instance directory and its logs. Use it during test cleanup.

On this page