Files
Claude-Code-Monitor/mcp/__tests__/tool-collector.test.ts
T
nntrivi2001 57dc91585d feat: Claude Code Monitor — lanes, pipelines and a merged workspace
Internal SmartGift build of a Claude Code monitoring dashboard.

Lanes: a durable unit of parallel agent work, one per working directory,
tracked across session restarts. Managed lanes are git worktrees the
dashboard provisions and can reset or remove behind a three-check destroy
guard and a counted preflight; adopted lanes are directories you already
own and are never destroyable.

Pipelines: a lane moves through pipeline stages. A stage the agent declares
with evidence renders green; a stage inferred from the tool-event stream
renders dashed amber and never counts as done. Detection is forward-only
within a 30-minute window, and never writes the declared stage.

Workspace: one page at /run with a lane grid, the selected lane's pipeline,
and a full Claude console behind a disclosure.
2026-07-30 14:39:03 +07:00

165 lines
6.2 KiB
TypeScript

/**
* @file tool-collector.test.ts
* @description Unit tests for the tool-collector module, which is responsible for collecting and registering all tools available in the application. The tests cover the presence of expected tools, their properties, uniqueness of tool names, adherence to naming conventions, inclusion of tools from all domains, and proper handling of mutation and destructive tools based on configuration. The tests use Node's built-in test runner and assert module for assertions.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { collectAllTools } from "../src/transports/tool-collector.js";
import { Logger } from "../src/core/logger.js";
import type { AppConfig } from "../src/config/app-config.js";
import { DashboardApiClient } from "../src/clients/dashboard-api-client.js";
function fakeConfig(overrides: Partial<AppConfig> = {}): AppConfig {
return {
serverName: "test",
serverVersion: "1.0.0",
dashboardBaseUrl: new URL("http://127.0.0.1:4820"),
requestTimeoutMs: 10_000,
retryCount: 0,
retryBackoffMs: 250,
allowMutations: false,
allowDestructive: false,
logLevel: "error",
transport: "stdio",
httpPort: 8819,
httpHost: "127.0.0.1",
...overrides,
};
}
describe("collectAllTools", () => {
const config = fakeConfig();
const logger = new Logger("error");
const api = new DashboardApiClient(config, logger);
it("registers all expected tools", () => {
const tools = collectAllTools(config, api, logger);
assert.ok(tools.length >= 25, `Expected at least 25 tools, got ${tools.length}`);
});
it("every tool has name, description, and handler", () => {
const tools = collectAllTools(config, api, logger);
for (const tool of tools) {
assert.ok(tool.name, `Tool missing name`);
assert.ok(tool.description, `Tool ${tool.name} missing description`);
assert.equal(typeof tool.handler, "function", `Tool ${tool.name} handler is not a function`);
}
});
it("tool names are unique", () => {
const tools = collectAllTools(config, api, logger);
const names = tools.map((t) => t.name);
const unique = new Set(names);
assert.equal(names.length, unique.size, "Duplicate tool names found");
});
it("tool names follow naming convention", () => {
const tools = collectAllTools(config, api, logger);
for (const tool of tools) {
assert.ok(
tool.name.startsWith("dashboard_"),
`Tool ${tool.name} should start with 'dashboard_'`
);
assert.ok(/^[a-z_]+$/.test(tool.name), `Tool ${tool.name} should be lowercase snake_case`);
}
});
it("includes tools from all domains", () => {
const tools = collectAllTools(config, api, logger);
const names = new Set(tools.map((t) => t.name));
// Observability
assert.ok(names.has("dashboard_health_check"));
assert.ok(names.has("dashboard_get_stats"));
assert.ok(names.has("dashboard_get_analytics"));
assert.ok(names.has("dashboard_get_system_info"));
assert.ok(names.has("dashboard_export_data"));
assert.ok(names.has("dashboard_get_operational_snapshot"));
// Sessions
assert.ok(names.has("dashboard_list_sessions"));
assert.ok(names.has("dashboard_get_session"));
assert.ok(names.has("dashboard_create_session"));
assert.ok(names.has("dashboard_update_session"));
// Agents
assert.ok(names.has("dashboard_list_agents"));
assert.ok(names.has("dashboard_get_agent"));
assert.ok(names.has("dashboard_create_agent"));
assert.ok(names.has("dashboard_update_agent"));
// Events
assert.ok(names.has("dashboard_list_events"));
assert.ok(names.has("dashboard_ingest_hook_event"));
// Pricing
assert.ok(names.has("dashboard_get_pricing_rules"));
assert.ok(names.has("dashboard_get_total_cost"));
assert.ok(names.has("dashboard_get_session_cost"));
assert.ok(names.has("dashboard_upsert_pricing_rule"));
assert.ok(names.has("dashboard_delete_pricing_rule"));
assert.ok(names.has("dashboard_reset_pricing_defaults"));
// Maintenance
assert.ok(names.has("dashboard_cleanup_data"));
assert.ok(names.has("dashboard_reimport_history"));
assert.ok(names.has("dashboard_reinstall_hooks"));
assert.ok(names.has("dashboard_clear_all_data"));
// Remote Data Sources
assert.ok(names.has("dashboard_list_remote_sources"));
assert.ok(names.has("dashboard_sync_remote_source"));
assert.ok(names.has("dashboard_sync_all_remote_sources"));
});
it("mutation tools throw when mutations disabled", async () => {
const mutConfig = fakeConfig({ allowMutations: false });
const tools = collectAllTools(mutConfig, api, logger);
const createSession = tools.find((t) => t.name === "dashboard_create_session");
assert.ok(createSession);
await assert.rejects(
() => createSession.handler({ id: "x", name: "y" }),
/Mutating tools are disabled/
);
});
it("destructive tool throws when destructive disabled", async () => {
const destConfig = fakeConfig({ allowMutations: true, allowDestructive: false });
const tools = collectAllTools(destConfig, api, logger);
const clearAll = tools.find((t) => t.name === "dashboard_clear_all_data");
assert.ok(clearAll);
await assert.rejects(
() => clearAll.handler({ confirmation_token: "CLEAR_ALL_DATA" }),
/Destructive tools are disabled/
);
});
it("destructive tool throws on wrong token", async () => {
const destConfig = fakeConfig({ allowMutations: true, allowDestructive: true });
const tools = collectAllTools(destConfig, api, logger);
const clearAll = tools.find((t) => t.name === "dashboard_clear_all_data");
assert.ok(clearAll);
await assert.rejects(
() => clearAll.handler({ confirmation_token: "WRONG" }),
/Invalid confirmation_token/
);
});
it("cleanup tool requires at least one parameter", async () => {
const mutConfig = fakeConfig({ allowMutations: true });
const tools = collectAllTools(mutConfig, api, logger);
const cleanup = tools.find((t) => t.name === "dashboard_cleanup_data");
assert.ok(cleanup);
await assert.rejects(
() => cleanup.handler({}),
/At least one of abandon_hours or purge_days is required/
);
});
});