Tests: cover interactive handler validation and dedupe
This commit is contained in:
parent
8ffa9769f7
commit
35ae37ccc1
@ -89,6 +89,30 @@ describe("plugin interactive handlers", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects unsupported interactive channels and malformed handlers", () => {
|
||||
expect(
|
||||
registerPluginInteractiveHandler("plugin-a", {
|
||||
channel: "slack",
|
||||
namespace: "codex",
|
||||
handler: async () => ({ handled: true }),
|
||||
} as unknown as Parameters<typeof registerPluginInteractiveHandler>[1]),
|
||||
).toEqual({
|
||||
ok: false,
|
||||
error: 'Interactive handler channel must be either "telegram" or "discord"',
|
||||
});
|
||||
|
||||
expect(
|
||||
registerPluginInteractiveHandler("plugin-a", {
|
||||
channel: "telegram",
|
||||
namespace: "codex",
|
||||
handler: "not-a-function",
|
||||
} as unknown as Parameters<typeof registerPluginInteractiveHandler>[1]),
|
||||
).toEqual({
|
||||
ok: false,
|
||||
error: "Interactive handler must be a function",
|
||||
});
|
||||
});
|
||||
|
||||
it("routes Discord interactions by namespace and dedupes interaction ids", async () => {
|
||||
const handler = vi.fn(async () => ({ handled: true }));
|
||||
expect(
|
||||
@ -198,4 +222,128 @@ describe("plugin interactive handlers", () => {
|
||||
});
|
||||
expect(handler).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("does not share dedupe keys across channels", async () => {
|
||||
const telegramHandler = vi.fn(async () => ({ handled: true }));
|
||||
const discordHandler = vi.fn(async () => ({ handled: true }));
|
||||
expect(
|
||||
registerPluginInteractiveHandler("codex-plugin", {
|
||||
channel: "telegram",
|
||||
namespace: "codex",
|
||||
handler: telegramHandler,
|
||||
}),
|
||||
).toEqual({ ok: true });
|
||||
expect(
|
||||
registerPluginInteractiveHandler("codex-plugin", {
|
||||
channel: "discord",
|
||||
namespace: "codex",
|
||||
handler: discordHandler,
|
||||
}),
|
||||
).toEqual({ ok: true });
|
||||
|
||||
const telegramResult = await dispatchPluginInteractiveHandler({
|
||||
channel: "telegram",
|
||||
data: "codex:resume",
|
||||
callbackId: "same-id",
|
||||
ctx: {
|
||||
accountId: "default",
|
||||
callbackId: "same-id",
|
||||
conversationId: "chat-1",
|
||||
senderId: "user-1",
|
||||
senderUsername: "ada",
|
||||
isGroup: false,
|
||||
isForum: false,
|
||||
auth: { isAuthorizedSender: true },
|
||||
callbackMessage: {
|
||||
messageId: 1,
|
||||
chatId: "chat-1",
|
||||
},
|
||||
},
|
||||
respond: {
|
||||
reply: vi.fn(async () => {}),
|
||||
editMessage: vi.fn(async () => {}),
|
||||
editButtons: vi.fn(async () => {}),
|
||||
clearButtons: vi.fn(async () => {}),
|
||||
deleteMessage: vi.fn(async () => {}),
|
||||
},
|
||||
});
|
||||
const discordResult = await dispatchPluginInteractiveHandler({
|
||||
channel: "discord",
|
||||
data: "codex:resume",
|
||||
interactionId: "same-id",
|
||||
ctx: {
|
||||
accountId: "default",
|
||||
interactionId: "same-id",
|
||||
conversationId: "channel-1",
|
||||
senderId: "user-1",
|
||||
senderUsername: "ada",
|
||||
auth: { isAuthorizedSender: true },
|
||||
interaction: {
|
||||
kind: "button",
|
||||
},
|
||||
},
|
||||
respond: {
|
||||
acknowledge: vi.fn(async () => {}),
|
||||
reply: vi.fn(async () => {}),
|
||||
followUp: vi.fn(async () => {}),
|
||||
editMessage: vi.fn(async () => {}),
|
||||
clearComponents: vi.fn(async () => {}),
|
||||
},
|
||||
});
|
||||
|
||||
expect(telegramResult).toEqual({ matched: true, handled: true, duplicate: false });
|
||||
expect(discordResult).toEqual({ matched: true, handled: true, duplicate: false });
|
||||
expect(telegramHandler).toHaveBeenCalledTimes(1);
|
||||
expect(discordHandler).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("does not consume dedupe keys when a handler declines", async () => {
|
||||
const handler = vi
|
||||
.fn(async () => ({ handled: false }))
|
||||
.mockResolvedValueOnce({ handled: false })
|
||||
.mockResolvedValueOnce({ handled: true });
|
||||
expect(
|
||||
registerPluginInteractiveHandler("codex-plugin", {
|
||||
channel: "discord",
|
||||
namespace: "codex",
|
||||
handler,
|
||||
}),
|
||||
).toEqual({ ok: true });
|
||||
|
||||
const baseParams = {
|
||||
channel: "discord" as const,
|
||||
data: "codex:approve:thread-1",
|
||||
interactionId: "ix-decline",
|
||||
ctx: {
|
||||
accountId: "default",
|
||||
interactionId: "ix-decline",
|
||||
conversationId: "channel-1",
|
||||
senderId: "user-1",
|
||||
senderUsername: "ada",
|
||||
auth: { isAuthorizedSender: true },
|
||||
interaction: {
|
||||
kind: "button" as const,
|
||||
},
|
||||
},
|
||||
respond: {
|
||||
acknowledge: vi.fn(async () => {}),
|
||||
reply: vi.fn(async () => {}),
|
||||
followUp: vi.fn(async () => {}),
|
||||
editMessage: vi.fn(async () => {}),
|
||||
clearComponents: vi.fn(async () => {}),
|
||||
},
|
||||
};
|
||||
|
||||
await expect(dispatchPluginInteractiveHandler(baseParams)).resolves.toEqual({
|
||||
matched: true,
|
||||
handled: false,
|
||||
duplicate: false,
|
||||
});
|
||||
await expect(dispatchPluginInteractiveHandler(baseParams)).resolves.toEqual({
|
||||
matched: true,
|
||||
handled: true,
|
||||
duplicate: false,
|
||||
});
|
||||
expect(handler).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user