Skip to content

Commit 22c2c41

Browse files
committed
test(telegram): cover callback API metadata
1 parent 5f19c93 commit 22c2c41

3 files changed

Lines changed: 135 additions & 1 deletion

File tree

extensions/telegram/src/bot.create-telegram-bot.test-harness.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ const grammySpies = vi.hoisted(() => ({
304304
sendChatActionSpy: vi.fn(),
305305
editMessageTextSpy: vi.fn(async () => ({ message_id: 88 })) as AnyAsyncMock,
306306
editMessageReplyMarkupSpy: vi.fn(async () => ({ message_id: 88 })) as AnyAsyncMock,
307+
deleteMessageSpy: vi.fn(async () => true) as AnyAsyncMock,
307308
setMessageReactionSpy: vi.fn(async () => undefined) as AnyAsyncMock,
308309
setMyCommandsSpy: vi.fn(async () => undefined) as AnyAsyncMock,
309310
getMeSpy: vi.fn(async () => ({
@@ -329,6 +330,7 @@ export const answerCallbackQuerySpy: AnyAsyncMock = grammySpies.answerCallbackQu
329330
export const sendChatActionSpy: AnyMock = grammySpies.sendChatActionSpy;
330331
export const editMessageTextSpy: AnyAsyncMock = grammySpies.editMessageTextSpy;
331332
export const editMessageReplyMarkupSpy: AnyAsyncMock = grammySpies.editMessageReplyMarkupSpy;
333+
export const deleteMessageSpy: AnyAsyncMock = grammySpies.deleteMessageSpy;
332334
export const setMessageReactionSpy: AnyAsyncMock = grammySpies.setMessageReactionSpy;
333335
export const setMyCommandsSpy: AnyAsyncMock = grammySpies.setMyCommandsSpy;
334336
export const getMeSpy: AnyAsyncMock = grammySpies.getMeSpy;
@@ -358,6 +360,7 @@ export const telegramBotRuntimeForTest: TelegramBotRuntimeForTest = {
358360
sendChatAction: grammySpies.sendChatActionSpy,
359361
editMessageText: grammySpies.editMessageTextSpy,
360362
editMessageReplyMarkup: grammySpies.editMessageReplyMarkupSpy,
363+
deleteMessage: grammySpies.deleteMessageSpy,
361364
setMessageReaction: grammySpies.setMessageReactionSpy,
362365
setMyCommands: grammySpies.setMyCommandsSpy,
363366
getMe: grammySpies.getMeSpy,
@@ -577,6 +580,8 @@ beforeEach(() => {
577580
editMessageTextSpy.mockResolvedValue({ message_id: 88 });
578581
editMessageReplyMarkupSpy.mockReset();
579582
editMessageReplyMarkupSpy.mockResolvedValue({ message_id: 88 });
583+
deleteMessageSpy.mockReset();
584+
deleteMessageSpy.mockResolvedValue(true);
580585
enqueueSystemEventSpy.mockReset();
581586
wasSentByBot.mockReset();
582587
wasSentByBot.mockReturnValue(false);

extensions/telegram/src/bot.create-telegram-bot.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,7 @@ describe("createTelegramBot", () => {
10891089
data: "OC_MULTI|toggle|env|prod",
10901090
from: { id: 9, first_name: "Ada", username: "ada_bot" },
10911091
message: {
1092+
business_connection_id: "biz-multi-1",
10921093
chat: { id: 1234, type: "private" },
10931094
date: 1736380800,
10941095
message_id: 10,
@@ -1102,6 +1103,7 @@ describe("createTelegramBot", () => {
11021103
});
11031104

11041105
expect(editMessageReplyMarkupSpy).toHaveBeenCalledWith(1234, 10, {
1106+
business_connection_id: "biz-multi-1",
11051107
reply_markup: {
11061108
inline_keyboard: [[{ text: "✅ Prod", callback_data: "OC_MULTI|toggle|env|prod" }]],
11071109
},

extensions/telegram/src/bot.test.ts

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { buildTelegramOpaqueCallbackData } from "./native-command-callback-data.
1414
const {
1515
answerCallbackQuerySpy,
1616
commandSpy,
17+
deleteMessageSpy,
1718
editMessageReplyMarkupSpy,
1819
editMessageTextSpy,
1920
enqueueSystemEventSpy,
@@ -2864,6 +2865,7 @@ describe("createTelegramBot", () => {
28642865
data: "codexapp:resume:thread-1",
28652866
from: { id: 9, first_name: "Ada", username: "ada_bot" },
28662867
message: {
2868+
business_connection_id: "biz-1",
28672869
chat: { id: 1234, type: "private" },
28682870
date: 1736380800,
28692871
message_id: 11,
@@ -2874,7 +2876,132 @@ describe("createTelegramBot", () => {
28742876
getFile: async () => ({ download: async () => new Uint8Array() }),
28752877
});
28762878

2877-
expect(editMessageTextSpy).toHaveBeenCalledWith(1234, 11, "Handled resume:thread-1", undefined);
2879+
expect(editMessageTextSpy).toHaveBeenCalledWith(1234, 11, "Handled resume:thread-1", {
2880+
business_connection_id: "biz-1",
2881+
});
2882+
expect(replySpy).not.toHaveBeenCalled();
2883+
});
2884+
2885+
it("deletes plugin-owned callback messages through the bot API", async () => {
2886+
onSpy.mockClear();
2887+
replySpy.mockClear();
2888+
deleteMessageSpy.mockClear();
2889+
registerPluginInteractiveHandler("codex-plugin", {
2890+
channel: "telegram",
2891+
namespace: "codexapp",
2892+
handler: (async ({ respond }: TelegramInteractiveHandlerContext) => {
2893+
await respond.deleteMessage();
2894+
return { handled: true };
2895+
}) as never,
2896+
});
2897+
2898+
createTelegramBot({
2899+
token: "tok",
2900+
config: {
2901+
channels: {
2902+
telegram: {
2903+
dmPolicy: "open",
2904+
allowFrom: ["*"],
2905+
},
2906+
},
2907+
},
2908+
});
2909+
const callbackHandler = getOnHandler("callback_query") as (
2910+
ctx: Record<string, unknown>,
2911+
) => Promise<void>;
2912+
2913+
await callbackHandler({
2914+
callbackQuery: {
2915+
id: "cbq-codex-delete",
2916+
data: "codexapp:delete:thread-1",
2917+
from: { id: 9, first_name: "Ada", username: "ada_bot" },
2918+
message: {
2919+
chat: { id: 1234, type: "private" },
2920+
date: 1736380800,
2921+
message_id: 11,
2922+
text: "Select a thread",
2923+
},
2924+
},
2925+
me: { username: "openclaw_bot" },
2926+
getFile: async () => ({ download: async () => new Uint8Array() }),
2927+
});
2928+
2929+
expect(deleteMessageSpy).toHaveBeenCalledWith(1234, 11);
2930+
expect(replySpy).not.toHaveBeenCalled();
2931+
});
2932+
2933+
it("routes plugin-owned callback replies with Telegram topic params", async () => {
2934+
onSpy.mockClear();
2935+
replySpy.mockClear();
2936+
sendMessageSpy.mockClear();
2937+
registerPluginInteractiveHandler("codex-plugin", {
2938+
channel: "telegram",
2939+
namespace: "codexapp",
2940+
handler: (async ({ respond }: TelegramInteractiveHandlerContext) => {
2941+
await respond.reply({ text: "Handled in topic" });
2942+
return { handled: true };
2943+
}) as never,
2944+
});
2945+
2946+
createTelegramBot({
2947+
token: "tok",
2948+
config: {
2949+
channels: {
2950+
telegram: {
2951+
dmPolicy: "open",
2952+
allowFrom: ["*"],
2953+
},
2954+
},
2955+
},
2956+
});
2957+
const callbackHandler = getOnHandler("callback_query") as (
2958+
ctx: Record<string, unknown>,
2959+
) => Promise<void>;
2960+
2961+
await callbackHandler({
2962+
callbackQuery: {
2963+
id: "cbq-codex-topic-reply",
2964+
data: "codexapp:reply:thread-1",
2965+
from: { id: 9, first_name: "Ada", username: "ada_bot" },
2966+
message: {
2967+
business_connection_id: "biz-topic-1",
2968+
chat: { id: -100987654321, type: "supergroup", title: "Forum Group" },
2969+
date: 1736380800,
2970+
is_topic_message: true,
2971+
message_id: 11,
2972+
message_thread_id: 99,
2973+
text: "Select a thread",
2974+
},
2975+
},
2976+
me: { username: "openclaw_bot" },
2977+
getFile: async () => ({ download: async () => new Uint8Array() }),
2978+
});
2979+
2980+
expect(sendMessageSpy).toHaveBeenCalledWith(-100987654321, "Handled in topic", {
2981+
business_connection_id: "biz-topic-1",
2982+
message_thread_id: 99,
2983+
});
2984+
2985+
sendMessageSpy.mockClear();
2986+
await callbackHandler({
2987+
callbackQuery: {
2988+
id: "cbq-codex-general-reply",
2989+
data: "codexapp:reply:thread-1",
2990+
from: { id: 9, first_name: "Ada", username: "ada_bot" },
2991+
message: {
2992+
chat: { id: -100987654322, type: "supergroup", title: "Forum Group" },
2993+
date: 1736380800,
2994+
is_topic_message: true,
2995+
message_id: 12,
2996+
message_thread_id: 1,
2997+
text: "Select a thread",
2998+
},
2999+
},
3000+
me: { username: "openclaw_bot" },
3001+
getFile: async () => ({ download: async () => new Uint8Array() }),
3002+
});
3003+
3004+
expect(sendMessageSpy).toHaveBeenCalledWith(-100987654322, "Handled in topic", undefined);
28783005
expect(replySpy).not.toHaveBeenCalled();
28793006
});
28803007

0 commit comments

Comments
 (0)