Files
Claude-Code-Monitor/server/__tests__/server-info.test.js
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

128 lines
4.0 KiB
JavaScript

/**
* @file Tests for multi-server discovery and hook-ingest deduplication by
* SQLite data directory (`server/lib/server-info.js`).
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
const { describe, it, beforeEach, afterEach } = require("node:test");
const assert = require("node:assert/strict");
const fs = require("fs");
const path = require("path");
const os = require("os");
const STAMP = `server-info-${Date.now()}-${process.pid}`;
const TMP = path.join(os.tmpdir(), STAMP);
const CLAUDE_HOME = path.join(TMP, "home");
const DATA_DIR_A = path.join(TMP, "data-a");
const DATA_DIR_B = path.join(TMP, "data-b");
function freshModule(dataDir) {
delete require.cache[require.resolve("../lib/server-info")];
delete require.cache[require.resolve("../lib/claude-home")];
process.env.CLAUDE_HOME = CLAUDE_HOME;
process.env.DASHBOARD_DATA_DIR = dataDir;
return require("../lib/server-info");
}
function writeDiscovery(servers) {
const infoPath = path.join(CLAUDE_HOME, ".agent-dashboard.json");
fs.mkdirSync(CLAUDE_HOME, { recursive: true });
const recent = servers.reduce((a, b) =>
Date.parse(b.startedAt) > Date.parse(a.startedAt) ? b : a
);
fs.writeFileSync(
infoPath,
JSON.stringify(
{ port: recent.port, pid: recent.pid, startedAt: recent.startedAt, servers },
null,
2
)
);
}
describe("server-info hook ingest deduplication", () => {
beforeEach(() => {
fs.rmSync(TMP, { recursive: true, force: true });
fs.mkdirSync(DATA_DIR_A, { recursive: true });
fs.mkdirSync(DATA_DIR_B, { recursive: true });
});
afterEach(() => {
delete process.env.CLAUDE_DASHBOARD_PORT;
fs.rmSync(TMP, { recursive: true, force: true });
delete require.cache[require.resolve("../lib/server-info")];
delete require.cache[require.resolve("../lib/claude-home")];
});
it("dedupes hook targets when two live servers share one dataDir", () => {
const mod = freshModule(DATA_DIR_A);
writeDiscovery([
{
port: 4820,
pid: process.pid,
startedAt: "2026-01-01T00:00:00.000Z",
dataDir: DATA_DIR_A,
},
{
port: 4821,
pid: process.pid,
startedAt: "2026-01-02T00:00:00.000Z",
dataDir: DATA_DIR_A,
},
]);
assert.deepEqual(mod.resolveHookIngestPorts(), [4820]);
assert.deepEqual(mod.resolveAllDashboardPorts(), [4820, 4821]);
});
it("fans out when live servers use different data directories", () => {
const mod = freshModule(DATA_DIR_A);
writeDiscovery([
{
port: 4820,
pid: process.pid,
startedAt: "2026-01-01T00:00:00.000Z",
dataDir: DATA_DIR_A,
},
{
port: 4900,
pid: process.pid,
startedAt: "2026-01-02T00:00:00.000Z",
dataDir: DATA_DIR_B,
},
]);
assert.deepEqual(mod.resolveHookIngestPorts(), [4820, 4900]);
});
it("treats legacy entries without dataDir as unique per port", () => {
const mod = freshModule(DATA_DIR_A);
writeDiscovery([
{ port: 4820, pid: process.pid, startedAt: "2026-01-01T00:00:00.000Z" },
{ port: 4821, pid: process.pid, startedAt: "2026-01-02T00:00:00.000Z" },
]);
assert.deepEqual(mod.resolveHookIngestPorts(), [4820, 4821]);
});
it("records dataDir when writing server info", () => {
const mod = freshModule(DATA_DIR_A);
mod.writeServerInfo(4999);
const raw = JSON.parse(fs.readFileSync(mod.getServerInfoPath(), "utf8"));
const entry = raw.servers.find((s) => s.port === 4999);
assert.ok(entry);
assert.equal(mod.normalizeDataDir(entry.dataDir), mod.normalizeDataDir(DATA_DIR_A));
});
it("honors CLAUDE_DASHBOARD_PORT for hook ingest", () => {
const mod = freshModule(DATA_DIR_A);
process.env.CLAUDE_DASHBOARD_PORT = "7777";
writeDiscovery([
{
port: 4820,
pid: process.pid,
startedAt: "2026-01-01T00:00:00.000Z",
dataDir: DATA_DIR_A,
},
]);
assert.deepEqual(mod.resolveHookIngestPorts(), [7777]);
});
});