mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(server): use createTestLogger in unit tests
Add createTestLogger utility to provide silent pino loggers for tests. Update test files that construct AgentRegistry, AgentManager, and agent clients to pass the required logger parameter.
This commit is contained in:
@@ -4,6 +4,7 @@ import { join } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { randomUUID } from "node:crypto";
|
||||
|
||||
import { createTestLogger } from "../../test-utils/test-logger.js";
|
||||
import { AgentManager } from "./agent-manager.js";
|
||||
import { AgentRegistry } from "./agent-registry.js";
|
||||
import type {
|
||||
@@ -101,15 +102,18 @@ class TestAgentSession implements AgentSession {
|
||||
}
|
||||
|
||||
describe("AgentManager", () => {
|
||||
const logger = createTestLogger();
|
||||
|
||||
test("normalizeConfig does not inject default model when omitted", async () => {
|
||||
const workdir = mkdtempSync(join(tmpdir(), "agent-manager-test-"));
|
||||
const registryPath = join(workdir, "agents.json");
|
||||
const registry = new AgentRegistry(registryPath);
|
||||
const registry = new AgentRegistry(registryPath, logger);
|
||||
const manager = new AgentManager({
|
||||
clients: {
|
||||
codex: new TestAgentClient(),
|
||||
},
|
||||
registry,
|
||||
logger,
|
||||
idFactory: () => "agent-without-model",
|
||||
});
|
||||
|
||||
@@ -124,12 +128,13 @@ describe("AgentManager", () => {
|
||||
test("createAgent persists provided title before returning", async () => {
|
||||
const workdir = mkdtempSync(join(tmpdir(), "agent-manager-test-"));
|
||||
const registryPath = join(workdir, "agents.json");
|
||||
const registry = new AgentRegistry(registryPath);
|
||||
const registry = new AgentRegistry(registryPath, logger);
|
||||
const manager = new AgentManager({
|
||||
clients: {
|
||||
codex: new TestAgentClient(),
|
||||
},
|
||||
registry,
|
||||
logger,
|
||||
idFactory: () => "agent-with-title",
|
||||
});
|
||||
|
||||
@@ -150,12 +155,13 @@ describe("AgentManager", () => {
|
||||
test("createAgent populates runtimeInfo after session creation", async () => {
|
||||
const workdir = mkdtempSync(join(tmpdir(), "agent-manager-test-"));
|
||||
const registryPath = join(workdir, "agents.json");
|
||||
const registry = new AgentRegistry(registryPath);
|
||||
const registry = new AgentRegistry(registryPath, logger);
|
||||
const manager = new AgentManager({
|
||||
clients: {
|
||||
codex: new TestAgentClient(),
|
||||
},
|
||||
registry,
|
||||
logger,
|
||||
idFactory: () => "agent-with-runtime-info",
|
||||
});
|
||||
|
||||
@@ -174,12 +180,13 @@ describe("AgentManager", () => {
|
||||
test("runAgent refreshes runtimeInfo after completion", async () => {
|
||||
const workdir = mkdtempSync(join(tmpdir(), "agent-manager-test-"));
|
||||
const registryPath = join(workdir, "agents.json");
|
||||
const registry = new AgentRegistry(registryPath);
|
||||
const registry = new AgentRegistry(registryPath, logger);
|
||||
const manager = new AgentManager({
|
||||
clients: {
|
||||
codex: new TestAgentClient(),
|
||||
},
|
||||
registry,
|
||||
logger,
|
||||
idFactory: () => "agent-with-run-runtime",
|
||||
});
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { mkdtempSync, rmSync, writeFileSync, readFileSync } from "node:fs";
|
||||
|
||||
import { createTestLogger } from "../../test-utils/test-logger.js";
|
||||
import { AgentRegistry } from "./agent-registry.js";
|
||||
import type { ManagedAgent } from "./agent-manager.js";
|
||||
import type {
|
||||
@@ -94,11 +95,12 @@ describe("AgentRegistry", () => {
|
||||
let tmpDir: string;
|
||||
let filePath: string;
|
||||
let registry: AgentRegistry;
|
||||
const logger = createTestLogger();
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = mkdtempSync(path.join(os.tmpdir(), "agent-registry-"));
|
||||
filePath = path.join(tmpDir, "agents.json");
|
||||
registry = new AgentRegistry(filePath);
|
||||
registry = new AgentRegistry(filePath, logger);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -129,7 +131,7 @@ describe("AgentRegistry", () => {
|
||||
expect(record.lastModeId).toBe("coding");
|
||||
expect(record.lastStatus).toBe("idle");
|
||||
|
||||
const reloaded = new AgentRegistry(filePath);
|
||||
const reloaded = new AgentRegistry(filePath, logger);
|
||||
const [persisted] = await reloaded.list();
|
||||
expect(persisted.cwd).toBe("/tmp/project");
|
||||
expect(persisted.config?.extra?.claude).toMatchObject({ maxThinkingTokens: 1024 });
|
||||
@@ -172,7 +174,7 @@ describe("AgentRegistry", () => {
|
||||
const current = await registry.get("agent-2");
|
||||
expect(current?.title).toBe("Fix Login Bug");
|
||||
|
||||
const reloaded = new AgentRegistry(filePath);
|
||||
const reloaded = new AgentRegistry(filePath, logger);
|
||||
const persisted = await reloaded.get("agent-2");
|
||||
expect(persisted?.title).toBe("Fix Login Bug");
|
||||
});
|
||||
@@ -239,7 +241,7 @@ describe("AgentRegistry", () => {
|
||||
`${JSON.stringify(payload, null, 2)}\nGARBAGE-TRAILING`
|
||||
);
|
||||
|
||||
const reloaded = new AgentRegistry(filePath);
|
||||
const reloaded = new AgentRegistry(filePath, logger);
|
||||
const result = await reloaded.list();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]?.title).toBe("Recovered agent");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createTestLogger } from "../../test-utils/test-logger.js";
|
||||
import { createAgentMcpServer } from "./mcp-server.js";
|
||||
import type { AgentManager, ManagedAgent } from "./agent-manager.js";
|
||||
import type { AgentRegistry } from "./agent-registry.js";
|
||||
@@ -45,9 +46,11 @@ function createTestDeps(): TestDeps {
|
||||
}
|
||||
|
||||
describe("create_agent MCP tool", () => {
|
||||
const logger = createTestLogger();
|
||||
|
||||
it("requires a concise title no longer than 40 characters", async () => {
|
||||
const { agentManager, agentRegistry } = createTestDeps();
|
||||
const server = await createAgentMcpServer({ agentManager, agentRegistry });
|
||||
const server = await createAgentMcpServer({ agentManager, agentRegistry, logger });
|
||||
const tool = (server as any)._registeredTools["create_agent"];
|
||||
expect(tool).toBeDefined();
|
||||
|
||||
@@ -84,7 +87,7 @@ describe("create_agent MCP tool", () => {
|
||||
availableModes: [],
|
||||
} as ManagedAgent);
|
||||
|
||||
const server = await createAgentMcpServer({ agentManager, agentRegistry });
|
||||
const server = await createAgentMcpServer({ agentManager, agentRegistry, logger });
|
||||
const tool = (server as any)._registeredTools["create_agent"];
|
||||
await tool.callback({
|
||||
cwd: "/tmp/repo",
|
||||
|
||||
@@ -15,6 +15,7 @@ import express from "express";
|
||||
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
||||
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
||||
|
||||
import { createTestLogger } from "../../../test-utils/test-logger.js";
|
||||
import { ClaudeAgentClient, convertClaudeHistoryEntry } from "./claude-agent.js";
|
||||
import { useTempClaudeConfigDir } from "../../test-utils/claude-config.js";
|
||||
import {
|
||||
@@ -106,16 +107,18 @@ type AgentMcpServerHandle = {
|
||||
};
|
||||
|
||||
async function startAgentMcpServer(): Promise<AgentMcpServerHandle> {
|
||||
const testLogger = createTestLogger();
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
const httpServer = createHTTPServer(app);
|
||||
|
||||
const registryDir = mkdtempSync(path.join(os.tmpdir(), "agent-mcp-registry-"));
|
||||
const registryPath = path.join(registryDir, "agents.json");
|
||||
const agentRegistry = new AgentRegistry(registryPath);
|
||||
const agentRegistry = new AgentRegistry(registryPath, testLogger);
|
||||
const agentManager = new AgentManager({
|
||||
clients: {},
|
||||
registry: agentRegistry,
|
||||
logger: testLogger,
|
||||
});
|
||||
|
||||
let allowedHosts: string[] | undefined;
|
||||
@@ -126,6 +129,7 @@ async function startAgentMcpServer(): Promise<AgentMcpServerHandle> {
|
||||
agentManager,
|
||||
agentRegistry,
|
||||
callerAgentId,
|
||||
logger: testLogger,
|
||||
});
|
||||
|
||||
const transport = new StreamableHTTPServerTransport({
|
||||
@@ -221,6 +225,7 @@ async function startAgentMcpServer(): Promise<AgentMcpServerHandle> {
|
||||
}
|
||||
|
||||
describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
const logger = createTestLogger();
|
||||
let agentMcpServer: AgentMcpServerHandle;
|
||||
let restoreClaudeConfigDir: (() => void) | null = null;
|
||||
const buildConfig = (
|
||||
@@ -257,7 +262,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"responds with text",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024 });
|
||||
const session = await client.createSession(config);
|
||||
|
||||
@@ -278,7 +283,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"streams reasoning chunks",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 2048 });
|
||||
const session = await client.createSession(config);
|
||||
|
||||
@@ -310,7 +315,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"emits a single assistant message in the hydrated stream",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 2048 });
|
||||
const session = await client.createSession(config);
|
||||
const updates: StreamHydrationUpdate[] = [];
|
||||
@@ -344,7 +349,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"shows the command inside pending tool calls",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 2048 });
|
||||
const session = await client.createSession(config);
|
||||
|
||||
@@ -381,7 +386,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"tracks permission + tool lifecycle when editing a file",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024 });
|
||||
const session = await client.createSession(config);
|
||||
|
||||
@@ -459,7 +464,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"permission flow parity - allows command after approval",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024, modeId: "default" });
|
||||
const session = await client.createSession(config);
|
||||
const filePath = path.join(cwd, "permission.txt");
|
||||
@@ -524,7 +529,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"permission flow parity - denies command execution",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024, modeId: "default" });
|
||||
const session = await client.createSession(config);
|
||||
const filePath = path.join(cwd, "permission.txt");
|
||||
@@ -590,7 +595,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"permission flow parity - aborts on interrupt response",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024, modeId: "default" });
|
||||
const session = await client.createSession(config);
|
||||
const filePath = path.join(cwd, "permission.txt");
|
||||
@@ -661,7 +666,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"interrupts a long-running bash command before it finishes",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 2048 });
|
||||
let session: Awaited<ReturnType<typeof client.createSession>> | null = null;
|
||||
let runStartedAt: number | null = null;
|
||||
@@ -719,7 +724,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"supports multi-turn conversations",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 2048 });
|
||||
const session = await client.createSession(config);
|
||||
|
||||
@@ -741,7 +746,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"resumes a persisted session with context preserved",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024 });
|
||||
const session = await client.createSession(config);
|
||||
|
||||
@@ -822,7 +827,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"updates session modes",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024 });
|
||||
const session = await client.createSession(config);
|
||||
|
||||
@@ -847,7 +852,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"handles plan mode approval flow",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 2048 });
|
||||
const session = await client.createSession(config);
|
||||
await session.setMode("plan");
|
||||
@@ -889,7 +894,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"hydrates persisted tool call results into the UI stream",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 4096 });
|
||||
const session = await client.createSession(config);
|
||||
const prompt = [
|
||||
@@ -1020,7 +1025,7 @@ describe("ClaudeAgentClient (SDK integration)", () => {
|
||||
"hydrates user messages from persisted history",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const config = buildConfig(cwd, { maxThinkingTokens: 1024 });
|
||||
|
||||
const promptMarker = `HYDRATED_USER_${Date.now().toString(36)}`;
|
||||
@@ -1284,10 +1289,12 @@ function rawContainsText(raw: unknown, text: string, depth = 0): boolean {
|
||||
// in daemon.e2e.test.ts which exercises the full flow through the WebSocket API.
|
||||
|
||||
describe("ClaudeAgentClient.listModels", () => {
|
||||
const logger = createTestLogger();
|
||||
|
||||
test(
|
||||
"returns models with required fields",
|
||||
async () => {
|
||||
const client = new ClaudeAgentClient();
|
||||
const client = new ClaudeAgentClient({ logger });
|
||||
const models = await client.listModels();
|
||||
|
||||
// HARD ASSERT: Returns an array
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createTestLogger } from "../../test-utils/test-logger.js";
|
||||
import { WaitForAgentTracker } from "./wait-for-agent-tracker.js";
|
||||
|
||||
describe("WaitForAgentTracker", () => {
|
||||
const logger = createTestLogger();
|
||||
|
||||
it("registers and cancels waiters per agent", () => {
|
||||
const tracker = new WaitForAgentTracker();
|
||||
const tracker = new WaitForAgentTracker(logger);
|
||||
const cancelA = vi.fn();
|
||||
const cancelB = vi.fn();
|
||||
|
||||
@@ -26,7 +29,7 @@ describe("WaitForAgentTracker", () => {
|
||||
});
|
||||
|
||||
it("supports cancelling all waiters", () => {
|
||||
const tracker = new WaitForAgentTracker();
|
||||
const tracker = new WaitForAgentTracker(logger);
|
||||
const cancelA = vi.fn();
|
||||
const cancelB = vi.fn();
|
||||
|
||||
|
||||
5
packages/server/src/test-utils/test-logger.ts
Normal file
5
packages/server/src/test-utils/test-logger.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import pino from "pino";
|
||||
|
||||
export function createTestLogger(): pino.Logger {
|
||||
return pino({ level: "silent" });
|
||||
}
|
||||
Reference in New Issue
Block a user