diff --git a/src/commands/agents.bind.commands.test.ts b/src/commands/agents.bind.commands.test.ts index b87246c7026..9379ef98048 100644 --- a/src/commands/agents.bind.commands.test.ts +++ b/src/commands/agents.bind.commands.test.ts @@ -1,48 +1,43 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import { baseConfigSnapshot, createTestRuntime } from "./test-runtime-config-helpers.js"; - -const readConfigFileSnapshotMock = vi.hoisted(() => vi.fn()); -const writeConfigFileMock = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)); - -vi.mock("../config/config.js", async (importOriginal) => ({ - ...(await importOriginal()), - readConfigFileSnapshot: readConfigFileSnapshotMock, - writeConfigFile: writeConfigFileMock, -})); +import { createBindingResolverTestPlugin } from "../test-utils/channel-plugins.js"; +import { + loadFreshAgentsCommandModuleForTest, + readConfigFileSnapshotMock, + resetAgentsBindTestHarness, + runtime, + writeConfigFileMock, +} from "./agents.bind.test-support.js"; +import { baseConfigSnapshot } from "./test-runtime-config-helpers.js"; vi.mock("../channels/plugins/index.js", async (importOriginal) => { const actual = await importOriginal(); - const knownChannels = new Set(["discord", "matrix", "telegram"]); - const createPlugin = (id: "discord" | "matrix" | "telegram") => ({ - id, - meta: { - id, - label: id, - selectionLabel: id, - docsPath: `/channels/${id}`, - blurb: `${id} test plugin`, - }, - capabilities: {}, - config: { - listAccountIds: () => [], - }, - }); + const knownChannels = new Map([ + [ + "discord", + createBindingResolverTestPlugin({ id: "discord", config: { listAccountIds: () => [] } }), + ], + [ + "matrix", + createBindingResolverTestPlugin({ + id: "matrix", + config: { listAccountIds: () => [] }, + resolveBindingAccountId: ({ agentId }) => agentId.toLowerCase(), + }), + ], + [ + "telegram", + createBindingResolverTestPlugin({ id: "telegram", config: { listAccountIds: () => [] } }), + ], + ]); return { ...actual, getChannelPlugin: (channel: string) => { const normalized = channel.trim().toLowerCase(); - if (!knownChannels.has(normalized)) { - return actual.getChannelPlugin(channel); + const plugin = knownChannels.get(normalized); + if (plugin) { + return plugin; } - if (normalized === "matrix") { - return { - ...createPlugin("matrix"), - setup: { - resolveBindingAccountId: ({ agentId }: { agentId: string }) => agentId.toLowerCase(), - }, - }; - } - return createPlugin(normalized as "discord" | "telegram"); + return actual.getChannelPlugin(channel); }, normalizeChannelId: (channel: string) => { const normalized = channel.trim().toLowerCase(); @@ -58,18 +53,11 @@ let agentsBindCommand: typeof import("./agents.js").agentsBindCommand; let agentsBindingsCommand: typeof import("./agents.js").agentsBindingsCommand; let agentsUnbindCommand: typeof import("./agents.js").agentsUnbindCommand; -const runtime = createTestRuntime(); - describe("agents bind/unbind commands", () => { beforeEach(async () => { - vi.resetModules(); ({ agentsBindCommand, agentsBindingsCommand, agentsUnbindCommand } = - await import("./agents.js")); - readConfigFileSnapshotMock.mockClear(); - writeConfigFileMock.mockClear(); - runtime.log.mockClear(); - runtime.error.mockClear(); - runtime.exit.mockClear(); + await loadFreshAgentsCommandModuleForTest()); + resetAgentsBindTestHarness(); }); it("lists all bindings by default", async () => { diff --git a/src/commands/agents.bind.matrix.integration.test.ts b/src/commands/agents.bind.matrix.integration.test.ts index f4041980a31..9179febd71d 100644 --- a/src/commands/agents.bind.matrix.integration.test.ts +++ b/src/commands/agents.bind.matrix.integration.test.ts @@ -1,45 +1,37 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { setActivePluginRegistry } from "../plugins/runtime.js"; -import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js"; +import { + createBindingResolverTestPlugin, + createTestRegistry, +} from "../test-utils/channel-plugins.js"; +import { + loadFreshAgentsCommandModuleForTest, + readConfigFileSnapshotMock, + resetAgentsBindTestHarness, + runtime, + writeConfigFileMock, +} from "./agents.bind.test-support.js"; import { setDefaultChannelPluginRegistryForTests } from "./channel-test-helpers.js"; -import { baseConfigSnapshot, createTestRuntime } from "./test-runtime-config-helpers.js"; +import { baseConfigSnapshot } from "./test-runtime-config-helpers.js"; -const readConfigFileSnapshotMock = vi.hoisted(() => vi.fn()); -const writeConfigFileMock = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)); - -const matrixBindingPlugin = { - ...createChannelTestPluginBase({ id: "matrix" }), - setup: { - resolveBindingAccountId: ({ accountId, agentId }: { accountId?: string; agentId?: string }) => { - const explicit = accountId?.trim(); - if (explicit) { - return explicit; - } - const agent = agentId?.trim(); - return agent || "default"; - }, +const matrixBindingPlugin = createBindingResolverTestPlugin({ + id: "matrix", + resolveBindingAccountId: ({ accountId, agentId }) => { + const explicit = accountId?.trim(); + if (explicit) { + return explicit; + } + const agent = agentId?.trim(); + return agent || "default"; }, -}; - -vi.mock("../config/config.js", async (importOriginal) => ({ - ...(await importOriginal()), - readConfigFileSnapshot: readConfigFileSnapshotMock, - writeConfigFile: writeConfigFileMock, -})); +}); let agentsBindCommand: typeof import("./agents.js").agentsBindCommand; describe("agents bind matrix integration", () => { - const runtime = createTestRuntime(); - beforeEach(async () => { - vi.resetModules(); - ({ agentsBindCommand } = await import("./agents.js")); - readConfigFileSnapshotMock.mockClear(); - writeConfigFileMock.mockClear(); - runtime.log.mockClear(); - runtime.error.mockClear(); - runtime.exit.mockClear(); + ({ agentsBindCommand } = await loadFreshAgentsCommandModuleForTest()); + resetAgentsBindTestHarness(); setActivePluginRegistry( createTestRegistry([{ pluginId: "matrix", plugin: matrixBindingPlugin, source: "test" }]), diff --git a/src/commands/agents.bind.test-support.ts b/src/commands/agents.bind.test-support.ts new file mode 100644 index 00000000000..be8947d1e55 --- /dev/null +++ b/src/commands/agents.bind.test-support.ts @@ -0,0 +1,31 @@ +import { vi } from "vitest"; +import { mergeMockedModule } from "../test-utils/vitest-module-mocks.js"; +import { createTestRuntime } from "./test-runtime-config-helpers.js"; + +export const readConfigFileSnapshotMock = vi.fn(); +export const writeConfigFileMock = vi.fn().mockResolvedValue(undefined); + +vi.mock("../config/config.js", async (importOriginal) => { + return await mergeMockedModule( + await importOriginal(), + () => ({ + readConfigFileSnapshot: readConfigFileSnapshotMock, + writeConfigFile: writeConfigFileMock, + }), + ); +}); + +export const runtime = createTestRuntime(); + +export async function loadFreshAgentsCommandModuleForTest() { + vi.resetModules(); + return await import("./agents.js"); +} + +export function resetAgentsBindTestHarness(): void { + readConfigFileSnapshotMock.mockClear(); + writeConfigFileMock.mockClear(); + runtime.log.mockClear(); + runtime.error.mockClear(); + runtime.exit.mockClear(); +} diff --git a/src/test-utils/channel-plugins.ts b/src/test-utils/channel-plugins.ts index 713d331335a..d6b3f571f05 100644 --- a/src/test-utils/channel-plugins.ts +++ b/src/test-utils/channel-plugins.ts @@ -116,3 +116,34 @@ export const createOutboundTestPlugin = (params: { outbound: params.outbound, ...(params.messaging ? { messaging: params.messaging } : {}), }); + +export type BindingResolverTestPlugin = Pick< + ChannelPlugin, + "id" | "meta" | "capabilities" | "config" +> & { + setup?: Pick, "resolveBindingAccountId">; +}; + +export const createBindingResolverTestPlugin = (params: { + id: ChannelId; + label?: string; + docsPath?: string; + capabilities?: ChannelCapabilities; + config?: Partial; + resolveBindingAccountId?: NonNullable["resolveBindingAccountId"]; +}): BindingResolverTestPlugin => ({ + ...createChannelTestPluginBase({ + id: params.id, + label: params.label, + docsPath: params.docsPath, + capabilities: params.capabilities, + config: params.config, + }), + ...(params.resolveBindingAccountId + ? { + setup: { + resolveBindingAccountId: params.resolveBindingAccountId, + }, + } + : {}), +});