import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest" ;
import { createTestPluginApi } from "../../../test/helpers/plugins/plugin-api.js" ;
import type { OpenClawPluginApi, PluginRuntime } from "../runtime-api.js" ;
const createFeishuClientMock = vi.hoisted(() => vi.fn());
const chatGetMock = vi.hoisted(() => vi.fn());
const chatMembersGetMock = vi.hoisted(() => vi.fn());
const contactUserGetMock = vi.hoisted(() => vi.fn());
vi.mock("./client.js" , () => ({
createFeishuClient: createFeishuClientMock,
}));
let registerFeishuChatTools: typeof import ("./chat.js" ).registerFeishuChatTools;
function createFeishuToolRuntime(): PluginRuntime {
return {} as PluginRuntime;
}
describe("registerFeishuChatTools" , () => {
function createChatToolApi(params: {
config: OpenClawPluginApi["config" ];
registerTool: OpenClawPluginApi["registerTool" ];
}): OpenClawPluginApi {
return createTestPluginApi({
id: "feishu-test" ,
name: "Feishu Test" ,
source: "local" ,
config: params.config,
runtime: createFeishuToolRuntime(),
logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn() },
registerTool: params.registerTool,
});
}
beforeAll(async () => {
({ registerFeishuChatTools } = await import ("./chat.js" ));
});
beforeEach(() => {
vi.clearAllMocks();
createFeishuClientMock.mockReturnValue({
im: {
chat: { get: chatGetMock },
chatMembers: { get: chatMembersGetMock },
},
contact: {
user: { get: contactUserGetMock },
},
});
});
it("registers feishu_chat and handles info/members actions" , async () => {
const registerTool = vi.fn();
registerFeishuChatTools(
createChatToolApi({
config: {
channels: {
feishu: {
enabled: true ,
appId: "app_id" ,
appSecret: "app_secret" , // pragma: allowlist secret
tools: { chat: true },
},
},
},
registerTool,
}),
);
expect(registerTool).toHaveBeenCalledTimes(1 );
const tool = registerTool.mock.calls[0 ]?.[0 ];
expect(tool?.name).toBe("feishu_chat" );
chatGetMock.mockResolvedValueOnce({
code: 0 ,
data: { name: "group name" , user_count: 3 },
});
const infoResult = await tool.execute("tc_1" , { action: "info" , chat_id: "oc_1" });
expect(infoResult.details).toEqual(
expect.objectContaining({ chat_id: "oc_1" , name: "group name" , user_count: 3 }),
);
chatMembersGetMock.mockResolvedValueOnce({
code: 0 ,
data: {
has_more: false ,
page_token: "" ,
items: [{ member_id: "ou_1" , name: "member1" , member_id_type: "open_id" }],
},
});
const membersResult = await tool.execute("tc_2" , { action: "members" , chat_id: "oc_1" });
expect(membersResult.details).toEqual(
expect.objectContaining({
chat_id: "oc_1" ,
members: [expect.objectContaining({ member_id: "ou_1" , name: "member1" })],
}),
);
contactUserGetMock.mockResolvedValueOnce({
code: 0 ,
data: {
user: {
open_id: "ou_1" ,
name: "member1" ,
email: "member1@example.com" ,
department_ids: ["od_1" ],
},
},
});
const memberInfoResult = await tool.execute("tc_3" , {
action: "member_info" ,
member_id: "ou_1" ,
});
expect(memberInfoResult.details).toEqual(
expect.objectContaining({
member_id: "ou_1" ,
open_id: "ou_1" ,
name: "member1" ,
email: "member1@example.com" ,
department_ids: ["od_1" ],
}),
);
});
it("skips registration when chat tool is disabled" , () => {
const registerTool = vi.fn();
registerFeishuChatTools(
createChatToolApi({
config: {
channels: {
feishu: {
enabled: true ,
appId: "app_id" ,
appSecret: "app_secret" , // pragma: allowlist secret
tools: { chat: false },
},
},
},
registerTool,
}),
);
expect(registerTool).not.toHaveBeenCalled();
});
});
Messung V0.5 in Prozent C=99 H=100 G=99
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland