mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-20 22:40:58 +00:00
refactor(feishu-tests): share card action event builders
This commit is contained in:
@@ -35,6 +35,54 @@ describe("Feishu Card Action Handler", () => {
|
||||
const cfg = {} as any; // Minimal mock
|
||||
const runtime = { log: vi.fn(), error: vi.fn() } as any;
|
||||
|
||||
function createCardActionEvent(params: {
|
||||
token: string;
|
||||
actionValue: unknown;
|
||||
chatId?: string;
|
||||
openId?: string;
|
||||
userId?: string;
|
||||
unionId?: string;
|
||||
}): FeishuCardActionEvent {
|
||||
const openId = params.openId ?? "u123";
|
||||
const userId = params.userId ?? "uid1";
|
||||
return {
|
||||
operator: { open_id: openId, user_id: userId, union_id: params.unionId ?? "un1" },
|
||||
token: params.token,
|
||||
action: {
|
||||
value: params.actionValue,
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: openId, user_id: userId, chat_id: params.chatId ?? "chat1" },
|
||||
};
|
||||
}
|
||||
|
||||
function createStructuredQuickActionEvent(params: {
|
||||
token: string;
|
||||
action: string;
|
||||
command?: string;
|
||||
chatId?: string;
|
||||
chatType?: "group" | "p2p";
|
||||
operatorOpenId?: string;
|
||||
actionOpenId?: string;
|
||||
}): FeishuCardActionEvent {
|
||||
return createCardActionEvent({
|
||||
token: params.token,
|
||||
chatId: params.chatId,
|
||||
openId: params.operatorOpenId,
|
||||
actionValue: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: params.action,
|
||||
...(params.command ? { q: params.command } : {}),
|
||||
c: {
|
||||
u: params.actionOpenId ?? params.operatorOpenId ?? "u123",
|
||||
h: params.chatId ?? "chat1",
|
||||
t: params.chatType ?? "group",
|
||||
e: Date.now() + 60_000,
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
resetProcessedFeishuCardActionTokensForTests();
|
||||
@@ -85,20 +133,11 @@ describe("Feishu Card Action Handler", () => {
|
||||
});
|
||||
|
||||
it("routes quick command actions with operator and conversation context", async () => {
|
||||
const event: FeishuCardActionEvent = {
|
||||
operator: { open_id: "u123", user_id: "uid1", union_id: "un1" },
|
||||
const event = createStructuredQuickActionEvent({
|
||||
token: "tok3",
|
||||
action: {
|
||||
value: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: "feishu.quick_actions.help",
|
||||
q: "/help",
|
||||
c: { u: "u123", h: "chat1", t: "group", e: Date.now() + 60_000 },
|
||||
}),
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: "u123", user_id: "uid1", chat_id: "chat1" },
|
||||
};
|
||||
action: "feishu.quick_actions.help",
|
||||
command: "/help",
|
||||
});
|
||||
|
||||
await handleFeishuCardAction({ cfg, event, runtime });
|
||||
|
||||
@@ -182,20 +221,11 @@ describe("Feishu Card Action Handler", () => {
|
||||
});
|
||||
|
||||
it("runs approval confirmation through the normal message path", async () => {
|
||||
const event: FeishuCardActionEvent = {
|
||||
operator: { open_id: "u123", user_id: "uid1", union_id: "un1" },
|
||||
const event = createStructuredQuickActionEvent({
|
||||
token: "tok5",
|
||||
action: {
|
||||
value: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: FEISHU_APPROVAL_CONFIRM_ACTION,
|
||||
q: "/new",
|
||||
c: { u: "u123", h: "chat1", t: "group", e: Date.now() + 60_000 },
|
||||
}),
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: "u123", user_id: "uid1", chat_id: "chat1" },
|
||||
};
|
||||
action: FEISHU_APPROVAL_CONFIRM_ACTION,
|
||||
command: "/new",
|
||||
});
|
||||
|
||||
await handleFeishuCardAction({ cfg, event, runtime });
|
||||
|
||||
@@ -211,20 +241,15 @@ describe("Feishu Card Action Handler", () => {
|
||||
});
|
||||
|
||||
it("safely rejects stale structured actions", async () => {
|
||||
const event: FeishuCardActionEvent = {
|
||||
operator: { open_id: "u123", user_id: "uid1", union_id: "un1" },
|
||||
const event = createCardActionEvent({
|
||||
token: "tok6",
|
||||
action: {
|
||||
value: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: "feishu.quick_actions.help",
|
||||
q: "/help",
|
||||
c: { u: "u123", h: "chat1", t: "group", e: Date.now() - 1 },
|
||||
}),
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: "u123", user_id: "uid1", chat_id: "chat1" },
|
||||
};
|
||||
actionValue: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: "feishu.quick_actions.help",
|
||||
q: "/help",
|
||||
c: { u: "u123", h: "chat1", t: "group", e: Date.now() - 1 },
|
||||
}),
|
||||
});
|
||||
|
||||
await handleFeishuCardAction({ cfg, event, runtime });
|
||||
|
||||
@@ -238,20 +263,13 @@ describe("Feishu Card Action Handler", () => {
|
||||
});
|
||||
|
||||
it("safely rejects wrong-user structured actions", async () => {
|
||||
const event: FeishuCardActionEvent = {
|
||||
operator: { open_id: "u999", user_id: "uid1", union_id: "un1" },
|
||||
const event = createStructuredQuickActionEvent({
|
||||
token: "tok7",
|
||||
action: {
|
||||
value: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: "feishu.quick_actions.help",
|
||||
q: "/help",
|
||||
c: { u: "u123", h: "chat1", t: "group", e: Date.now() + 60_000 },
|
||||
}),
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: "u999", user_id: "uid1", chat_id: "chat1" },
|
||||
};
|
||||
action: "feishu.quick_actions.help",
|
||||
command: "/help",
|
||||
operatorOpenId: "u999",
|
||||
actionOpenId: "u123",
|
||||
});
|
||||
|
||||
await handleFeishuCardAction({ cfg, event, runtime });
|
||||
|
||||
@@ -289,20 +307,13 @@ describe("Feishu Card Action Handler", () => {
|
||||
});
|
||||
|
||||
it("preserves p2p callbacks for DM quick actions", async () => {
|
||||
const event: FeishuCardActionEvent = {
|
||||
operator: { open_id: "u123", user_id: "uid1", union_id: "un1" },
|
||||
const event = createStructuredQuickActionEvent({
|
||||
token: "tok9",
|
||||
action: {
|
||||
value: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: "feishu.quick_actions.help",
|
||||
q: "/help",
|
||||
c: { u: "u123", h: "p2p-chat-1", t: "p2p", e: Date.now() + 60_000 },
|
||||
}),
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: "u123", user_id: "uid1", chat_id: "p2p-chat-1" },
|
||||
};
|
||||
action: "feishu.quick_actions.help",
|
||||
command: "/help",
|
||||
chatId: "p2p-chat-1",
|
||||
chatType: "p2p",
|
||||
});
|
||||
|
||||
await handleFeishuCardAction({ cfg, event, runtime });
|
||||
|
||||
@@ -319,20 +330,11 @@ describe("Feishu Card Action Handler", () => {
|
||||
});
|
||||
|
||||
it("drops duplicate structured callback tokens", async () => {
|
||||
const event: FeishuCardActionEvent = {
|
||||
operator: { open_id: "u123", user_id: "uid1", union_id: "un1" },
|
||||
const event = createStructuredQuickActionEvent({
|
||||
token: "tok10",
|
||||
action: {
|
||||
value: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: "feishu.quick_actions.help",
|
||||
q: "/help",
|
||||
c: { u: "u123", h: "chat1", t: "group", e: Date.now() + 60_000 },
|
||||
}),
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: "u123", user_id: "uid1", chat_id: "chat1" },
|
||||
};
|
||||
action: "feishu.quick_actions.help",
|
||||
command: "/help",
|
||||
});
|
||||
|
||||
await handleFeishuCardAction({ cfg, event, runtime });
|
||||
await handleFeishuCardAction({ cfg, event, runtime });
|
||||
@@ -341,20 +343,11 @@ describe("Feishu Card Action Handler", () => {
|
||||
});
|
||||
|
||||
it("releases a claimed token when dispatch fails so retries can succeed", async () => {
|
||||
const event: FeishuCardActionEvent = {
|
||||
operator: { open_id: "u123", user_id: "uid1", union_id: "un1" },
|
||||
const event = createStructuredQuickActionEvent({
|
||||
token: "tok11",
|
||||
action: {
|
||||
value: createFeishuCardInteractionEnvelope({
|
||||
k: "quick",
|
||||
a: "feishu.quick_actions.help",
|
||||
q: "/help",
|
||||
c: { u: "u123", h: "chat1", t: "group", e: Date.now() + 60_000 },
|
||||
}),
|
||||
tag: "button",
|
||||
},
|
||||
context: { open_id: "u123", user_id: "uid1", chat_id: "chat1" },
|
||||
};
|
||||
action: "feishu.quick_actions.help",
|
||||
command: "/help",
|
||||
});
|
||||
vi.mocked(handleFeishuMessage)
|
||||
.mockRejectedValueOnce(new Error("transient"))
|
||||
.mockResolvedValueOnce(undefined as never);
|
||||
|
||||
Reference in New Issue
Block a user