Files
openclaw/extensions/feishu/src/docx.account-selection.test.ts

124 lines
3.6 KiB
TypeScript

import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
import { describe, expect, test, vi } from "vitest";
import { registerFeishuDocTools } from "./docx.js";
const createFeishuClientMock = vi.fn((creds: { appId?: string } | undefined) => ({
__appId: creds?.appId,
}));
vi.mock("./client.js", () => {
return {
createFeishuClient: (creds: { appId?: string } | undefined) => createFeishuClientMock(creds),
};
});
// Patch SDK import so tool execution can run without network concerns.
vi.mock("@larksuiteoapi/node-sdk", () => {
return {
default: {},
};
});
type ToolLike = {
name: string;
execute: (toolCallId: string, params: unknown) => Promise<unknown>;
};
type ToolContextLike = {
agentAccountId?: string;
};
type ToolFactoryLike = (ctx: ToolContextLike) => ToolLike | ToolLike[] | null | undefined;
function createApi(cfg: OpenClawPluginApi["config"]) {
const registered: Array<{
tool: ToolLike | ToolFactoryLike;
opts?: { name?: string };
}> = [];
const api: Partial<OpenClawPluginApi> = {
config: cfg,
logger: {
info: () => {},
warn: () => {},
error: () => {},
debug: () => {},
},
registerTool: (tool, opts) => {
registered.push({ tool, opts });
},
};
const resolveTool = (name: string, ctx: ToolContextLike): ToolLike => {
const entry = registered.find((item) => item.opts?.name === name);
if (!entry) {
throw new Error(`Tool not registered: ${name}`);
}
if (typeof entry.tool === "function") {
const built = entry.tool(ctx);
if (!built || Array.isArray(built)) {
throw new Error(`Unexpected tool factory output for ${name}`);
}
return built as ToolLike;
}
return entry.tool as ToolLike;
};
return { api: api as OpenClawPluginApi, resolveTool };
}
describe("feishu_doc account selection", () => {
test("uses agentAccountId context when params omit accountId", async () => {
const cfg = {
channels: {
feishu: {
enabled: true,
accounts: {
a: { appId: "app-a", appSecret: "sec-a", tools: { doc: true } },
b: { appId: "app-b", appSecret: "sec-b", tools: { doc: true } },
},
},
},
} as OpenClawPluginApi["config"];
const { api, resolveTool } = createApi(cfg);
registerFeishuDocTools(api);
const docToolA = resolveTool("feishu_doc", { agentAccountId: "a" });
const docToolB = resolveTool("feishu_doc", { agentAccountId: "b" });
await docToolA.execute("call-a", { action: "list_blocks", doc_token: "d" });
await docToolB.execute("call-b", { action: "list_blocks", doc_token: "d" });
expect(createFeishuClientMock).toHaveBeenCalledTimes(2);
expect(createFeishuClientMock.mock.calls[0]?.[0]?.appId).toBe("app-a");
expect(createFeishuClientMock.mock.calls[1]?.[0]?.appId).toBe("app-b");
});
test("explicit accountId param overrides agentAccountId context", async () => {
const cfg = {
channels: {
feishu: {
enabled: true,
accounts: {
a: { appId: "app-a", appSecret: "sec-a", tools: { doc: true } },
b: { appId: "app-b", appSecret: "sec-b", tools: { doc: true } },
},
},
},
} as OpenClawPluginApi["config"];
const { api, resolveTool } = createApi(cfg);
registerFeishuDocTools(api);
const docTool = resolveTool("feishu_doc", { agentAccountId: "b" });
await docTool.execute("call-override", {
action: "list_blocks",
doc_token: "d",
accountId: "a",
});
expect(createFeishuClientMock.mock.calls.at(-1)?.[0]?.appId).toBe("app-a");
});
});