import { beforeEach, describe, expect, it, vi } from "vitest" ;
import type { ClawdbotConfig } from "../runtime-api.js" ;
const createFeishuClientMock = vi.hoisted(() => vi.fn());
vi.mock("./client.js" , () => ({
createFeishuClient: createFeishuClientMock,
}));
const freshDirectoryModulePath = "./directory.js?directory-test" ;
const {
listFeishuDirectoryGroups,
listFeishuDirectoryGroupsLive,
listFeishuDirectoryPeers,
listFeishuDirectoryPeersLive,
} = await import (freshDirectoryModulePath);
function makeStaticCfg(): ClawdbotConfig {
return {
channels: {
feishu: {
allowFrom: ["user:alice" , "user:bob" ],
dms: {
"user:carla" : {},
},
groups: {
"chat-1" : {},
},
groupAllowFrom: ["chat-2" ],
},
},
} as ClawdbotConfig;
}
function makeConfiguredCfg(): ClawdbotConfig {
return {
channels: {
feishu: {
...makeStaticCfg().channels?.feishu,
appId: "cli_test_app_id" ,
appSecret: "cli_test_app_secret" ,
},
},
} as ClawdbotConfig;
}
describe("feishu directory (config-backed)" , () => {
beforeEach(() => {
createFeishuClientMock.mockReset();
});
it("merges allowFrom + dms into peer entries" , async () => {
const peers = await listFeishuDirectoryPeers({ cfg: makeStaticCfg(), query: "a" });
expect(peers).toEqual([
{ kind: "user" , id: "alice" },
{ kind: "user" , id: "carla" },
]);
});
it("normalizes spaced provider-prefixed peer entries" , async () => {
const cfg = {
channels: {
feishu: {
allowFrom: [" feishu:user:ou_alice " ],
dms: {
" lark:dm:ou_carla " : {},
},
groups: {},
groupAllowFrom: [],
},
},
} as ClawdbotConfig;
const peers = await listFeishuDirectoryPeers({ cfg });
expect(peers).toEqual([
{ kind: "user" , id: "ou_alice" },
{ kind: "user" , id: "ou_carla" },
]);
});
it("merges groups map + groupAllowFrom into group entries" , async () => {
const groups = await listFeishuDirectoryGroups({ cfg: makeStaticCfg() });
expect(groups).toEqual([
{ kind: "group" , id: "chat-1" },
{ kind: "group" , id: "chat-2" },
]);
});
it("falls back to static peers on live lookup failure by default" , async () => {
createFeishuClientMock.mockReturnValueOnce({
contact: {
user: {
list: vi.fn(async () => {
throw new Error("token expired" );
}),
},
},
});
const peers = await listFeishuDirectoryPeersLive({ cfg: makeConfiguredCfg(), query: "a" });
expect(peers).toEqual([
{ kind: "user" , id: "alice" },
{ kind: "user" , id: "carla" },
]);
});
it("surfaces live peer lookup failures when fallback is disabled" , async () => {
createFeishuClientMock.mockReturnValueOnce({
contact: {
user: {
list: vi.fn(async () => {
throw new Error("token expired" );
}),
},
},
});
await expect(
listFeishuDirectoryPeersLive({ cfg: makeConfiguredCfg(), fallbackToStatic: false }),
).rejects.toThrow("token expired" );
});
it("surfaces live group lookup failures when fallback is disabled" , async () => {
createFeishuClientMock.mockReturnValueOnce({
im: {
chat: {
list: vi.fn(async () => ({ code: 999 , msg: "forbidden" })),
},
},
});
await expect(
listFeishuDirectoryGroupsLive({ cfg: makeConfiguredCfg(), fallbackToStatic: false }),
).rejects.toThrow("forbidden" );
});
});
Messung V0.5 in Prozent C=100 H=100 G=100
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland