test: dedupe extension channel fixtures

This commit is contained in:
Peter Steinberger
2026-03-26 17:59:05 +00:00
parent 48167a69b9
commit f29c1206cd
6 changed files with 269 additions and 354 deletions

View File

@@ -60,6 +60,51 @@ describe("broadcast dispatch", () => {
contentType: "video/mp4",
});
function createBroadcastConfig(): ClawdbotConfig {
return {
broadcast: { "oc-broadcast-group": ["susan", "main"] },
agents: { list: [{ id: "main" }, { id: "susan" }] },
channels: {
feishu: {
groups: {
"oc-broadcast-group": {
requireMention: true,
},
},
},
},
} as unknown as ClawdbotConfig;
}
function createBroadcastEvent(options: {
messageId: string;
text: string;
botMentioned?: boolean;
}): FeishuMessageEvent {
return {
sender: { sender_id: { open_id: "ou-sender" } },
message: {
message_id: options.messageId,
chat_id: "oc-broadcast-group",
chat_type: "group",
message_type: "text",
content: JSON.stringify({ text: options.text }),
...(options.botMentioned
? {
mentions: [
{
key: "@_user_1",
id: { open_id: "bot-open-id" },
name: "Bot",
tenant_key: "",
},
],
}
: {}),
},
};
}
beforeEach(() => {
vi.clearAllMocks();
mockResolveAgentRoute.mockReturnValue({
@@ -112,33 +157,12 @@ describe("broadcast dispatch", () => {
});
it("dispatches to all broadcast agents when bot is mentioned", async () => {
const cfg: ClawdbotConfig = {
broadcast: { "oc-broadcast-group": ["susan", "main"] },
agents: { list: [{ id: "main" }, { id: "susan" }] },
channels: {
feishu: {
groups: {
"oc-broadcast-group": {
requireMention: true,
},
},
},
},
} as unknown as ClawdbotConfig;
const event: FeishuMessageEvent = {
sender: { sender_id: { open_id: "ou-sender" } },
message: {
message_id: "msg-broadcast-mentioned",
chat_id: "oc-broadcast-group",
chat_type: "group",
message_type: "text",
content: JSON.stringify({ text: "hello @bot" }),
mentions: [
{ key: "@_user_1", id: { open_id: "bot-open-id" }, name: "Bot", tenant_key: "" },
],
},
};
const cfg = createBroadcastConfig();
const event = createBroadcastEvent({
messageId: "msg-broadcast-mentioned",
text: "hello @bot",
botMentioned: true,
});
await handleFeishuMessage({
cfg,
@@ -160,30 +184,11 @@ describe("broadcast dispatch", () => {
});
it("skips broadcast dispatch when bot is NOT mentioned (requireMention=true)", async () => {
const cfg: ClawdbotConfig = {
broadcast: { "oc-broadcast-group": ["susan", "main"] },
agents: { list: [{ id: "main" }, { id: "susan" }] },
channels: {
feishu: {
groups: {
"oc-broadcast-group": {
requireMention: true,
},
},
},
},
} as unknown as ClawdbotConfig;
const event: FeishuMessageEvent = {
sender: { sender_id: { open_id: "ou-sender" } },
message: {
message_id: "msg-broadcast-not-mentioned",
chat_id: "oc-broadcast-group",
chat_type: "group",
message_type: "text",
content: JSON.stringify({ text: "hello everyone" }),
},
};
const cfg = createBroadcastConfig();
const event = createBroadcastEvent({
messageId: "msg-broadcast-not-mentioned",
text: "hello everyone",
});
await handleFeishuMessage({
cfg,
@@ -197,30 +202,11 @@ describe("broadcast dispatch", () => {
});
it("skips broadcast dispatch when bot identity is unknown (requireMention=true)", async () => {
const cfg: ClawdbotConfig = {
broadcast: { "oc-broadcast-group": ["susan", "main"] },
agents: { list: [{ id: "main" }, { id: "susan" }] },
channels: {
feishu: {
groups: {
"oc-broadcast-group": {
requireMention: true,
},
},
},
},
} as unknown as ClawdbotConfig;
const event: FeishuMessageEvent = {
sender: { sender_id: { open_id: "ou-sender" } },
message: {
message_id: "msg-broadcast-unknown-bot-id",
chat_id: "oc-broadcast-group",
chat_type: "group",
message_type: "text",
content: JSON.stringify({ text: "hello everyone" }),
},
};
const cfg = createBroadcastConfig();
const event = createBroadcastEvent({
messageId: "msg-broadcast-unknown-bot-id",
text: "hello everyone",
});
await handleFeishuMessage({
cfg,

View File

@@ -61,6 +61,41 @@ function getDescribedActions(cfg: OpenClawConfig): string[] {
return [...(feishuPlugin.actions?.describeMessageTool?.({ cfg })?.actions ?? [])];
}
function createLegacyFeishuButtonCard(value: { command?: string; text?: string }) {
return {
schema: "2.0",
body: {
elements: [
{
tag: "action",
actions: [
{
tag: "button",
text: { tag: "plain_text", content: "Run /new" },
value,
},
],
},
],
},
};
}
async function expectLegacyFeishuCardPayloadRejected(cfg: OpenClawConfig, card: unknown) {
await expect(
feishuPlugin.actions?.handleAction?.({
action: "send",
params: { to: "chat:oc_group_1", card },
cfg,
accountId: undefined,
toolContext: {},
} as never),
).rejects.toThrow(
"Feishu card buttons that trigger text or commands must use structured interaction envelopes.",
);
expect(sendCardFeishuMock).not.toHaveBeenCalled();
}
describe("feishuPlugin.status.probeAccount", () => {
it("uses current account credentials for multi-account config", async () => {
const cfg = {
@@ -248,69 +283,17 @@ describe("feishuPlugin actions", () => {
});
it("rejects raw legacy card command payloads", async () => {
const legacyCard = {
schema: "2.0",
body: {
elements: [
{
tag: "action",
actions: [
{
tag: "button",
text: { tag: "plain_text", content: "Run /new" },
value: { command: "/new" },
},
],
},
],
},
};
await expect(
feishuPlugin.actions?.handleAction?.({
action: "send",
params: { to: "chat:oc_group_1", card: legacyCard },
cfg,
accountId: undefined,
toolContext: {},
} as never),
).rejects.toThrow(
"Feishu card buttons that trigger text or commands must use structured interaction envelopes.",
await expectLegacyFeishuCardPayloadRejected(
cfg,
createLegacyFeishuButtonCard({ command: "/new" }),
);
expect(sendCardFeishuMock).not.toHaveBeenCalled();
});
it("rejects raw legacy card text payloads", async () => {
const legacyCard = {
schema: "2.0",
body: {
elements: [
{
tag: "action",
actions: [
{
tag: "button",
text: { tag: "plain_text", content: "Run /new" },
value: { text: "/new" },
},
],
},
],
},
};
await expect(
feishuPlugin.actions?.handleAction?.({
action: "send",
params: { to: "chat:oc_group_1", card: legacyCard },
cfg,
accountId: undefined,
toolContext: {},
} as never),
).rejects.toThrow(
"Feishu card buttons that trigger text or commands must use structured interaction envelopes.",
await expectLegacyFeishuCardPayloadRejected(
cfg,
createLegacyFeishuButtonCard({ text: "/new" }),
);
expect(sendCardFeishuMock).not.toHaveBeenCalled();
});
it("allows non-button controls to carry text metadata values", async () => {