import assert from "node:assert/strict"; import test from "node:test"; import { createMemoryConfigStore } from "../src/dashboard/config-store.js"; import { runConfigCommand, type CliContext } from "../src/cli.js"; function createTestContext(initial: Record = {}) { const store = createMemoryConfigStore(initial); const logs: string[] = []; const errors: string[] = []; const ctx: CliContext = { configStore: store, log: (msg) => logs.push(msg), error: (msg) => errors.push(msg), }; return { store, logs, errors, ctx }; } test("runConfigCommand returns false for non-config commands", () => { const { ctx } = createTestContext(); assert.equal(runConfigCommand([], ctx), false); assert.equal(runConfigCommand(["start"], ctx), false); assert.equal(runConfigCommand(["run"], ctx), false); }); test("config set writes a string value at a nested path", () => { const { store, logs, ctx } = createTestContext({ channels: { feishu: { appId: "old" } } }); runConfigCommand(["config", "set", "channels.feishu.appId", "cli_new"], ctx); const snapshot = store.snapshot(); assert.equal((snapshot.channels as Record>).feishu.appId, "cli_new"); assert.ok(logs[0]?.includes("cli_new")); }); test("config set coerces boolean values", () => { const { store, ctx } = createTestContext({ channels: { feishu: { enabled: false } } }); runConfigCommand(["config", "set", "channels.feishu.enabled", "true"], ctx); const snapshot = store.snapshot(); assert.equal((snapshot.channels as Record>).feishu.enabled, true); }); test("config set coerces numeric values", () => { const { store, ctx } = createTestContext({ models: { maxTokens: 8192 } }); runConfigCommand(["config", "set", "models.maxTokens", "16384"], ctx); const snapshot = store.snapshot(); assert.equal((snapshot.models as Record).maxTokens, 16384); }); test("config set creates intermediate objects for missing paths", () => { const { store, ctx } = createTestContext({}); runConfigCommand(["config", "set", "channels.feishu.appId", "new-id"], ctx); const snapshot = store.snapshot(); assert.equal( (snapshot.channels as Record>).feishu.appId, "new-id", ); }); test("config set handles array index paths", () => { const { store, ctx } = createTestContext({ items: [{ name: "a" }, { name: "b" }] }); runConfigCommand(["config", "set", "items.1.name", "updated"], ctx); const snapshot = store.snapshot(); assert.equal((snapshot.items as Array>)[1]!.name, "updated"); }); test("config get returns a string value", () => { const { logs, ctx } = createTestContext({ channels: { feishu: { appId: "test-id" } } }); runConfigCommand(["config", "get", "channels.feishu.appId"], ctx); assert.equal(logs[0], "test-id"); }); test("config get returns a formatted object", () => { const { logs, ctx } = createTestContext({ channels: { feishu: { appId: "x", enabled: true } } }); runConfigCommand(["config", "get", "channels.feishu"], ctx); const parsed = JSON.parse(logs[0]!) as Record; assert.equal(parsed.appId, "x"); assert.equal(parsed.enabled, true); }); test("config get reports error for missing key", () => { const { errors, ctx } = createTestContext({}); runConfigCommand(["config", "get", "missing.key"], ctx); assert.ok(errors[0]?.includes("not found")); }); test("config list outputs the full config", () => { const original = { channels: { feishu: { enabled: true } } }; const { logs, ctx } = createTestContext(original); runConfigCommand(["config", "list"], ctx); const parsed = JSON.parse(logs[0]!) as Record; assert.deepEqual(parsed, original); }); test("config delete removes a key", () => { const { store, logs, ctx } = createTestContext({ channels: { feishu: { appId: "x", enabled: true } }, }); runConfigCommand(["config", "delete", "channels.feishu.appId"], ctx); const snapshot = store.snapshot(); const feishu = (snapshot.channels as Record>).feishu; assert.equal("appId" in feishu, false); assert.equal(feishu.enabled, true); assert.ok(logs[0]?.includes("Deleted")); }); test("config delete reports error for missing key", () => { const { errors, ctx } = createTestContext({}); runConfigCommand(["config", "delete", "missing.key"], ctx); assert.ok(errors[0]?.includes("not found")); }); test("config with no subcommand prints usage", () => { const { logs, ctx } = createTestContext(); const handled = runConfigCommand(["config"], ctx); assert.equal(handled, true); assert.ok(logs.some((l) => l.includes("Usage"))); }); test("config with unknown subcommand prints error and usage", () => { const { errors, logs, ctx } = createTestContext(); const handled = runConfigCommand(["config", "badcmd"], ctx); assert.equal(handled, true); assert.ok(errors[0]?.includes("Unknown")); assert.ok(logs.some((l) => l.includes("Usage"))); }); test("config set with missing arguments prints usage", () => { const { errors, ctx } = createTestContext(); runConfigCommand(["config", "set", "key"], ctx); assert.ok(errors[0]?.includes("Usage")); }); test("config set coerces null value", () => { const { store, ctx } = createTestContext({ key: "value" }); runConfigCommand(["config", "set", "key", "null"], ctx); const snapshot = store.snapshot(); assert.equal(snapshot.key, null); });