Skip to content

Commit 0586da7

Browse files
committed
test: guard telegram bot core mock calls
1 parent 4ea089b commit 0586da7

1 file changed

Lines changed: 51 additions & 31 deletions

File tree

extensions/telegram/src/bot.test.ts

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
clearPluginInteractiveHandlers,
55
registerPluginInteractiveHandler,
66
} from "openclaw/plugin-sdk/plugin-runtime";
7+
import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime";
78
import { loadSessionStore } from "openclaw/plugin-sdk/session-store-runtime";
89
import { mockPinnedHostnameResolution } from "openclaw/plugin-sdk/test-env";
910
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
@@ -84,7 +85,7 @@ async function loadInboundContextContract() {
8485

8586
type MockCallSource = {
8687
mock: {
87-
calls: ArrayLike<ReadonlyArray<unknown>>;
88+
calls: ReadonlyArray<ReadonlyArray<unknown>>;
8889
};
8990
};
9091

@@ -101,13 +102,22 @@ function requireArray(value: unknown, label: string): unknown[] {
101102
}
102103

103104
function mockArg(source: MockCallSource, callIndex: number, argIndex: number, label: string) {
104-
const call = source.mock.calls[callIndex];
105+
const call = source.mock.calls.at(callIndex);
105106
if (!call) {
106107
throw new Error(`expected mock call: ${label}`);
107108
}
108109
return call[argIndex];
109110
}
110111

112+
function mockMsgContextArg(
113+
source: MockCallSource,
114+
callIndex: number,
115+
argIndex: number,
116+
label: string,
117+
): MsgContext {
118+
return mockArg(source, callIndex, argIndex, label) as MsgContext;
119+
}
120+
111121
function execApprovalCall(index = 0) {
112122
return requireRecord(
113123
mockArg(resolveExecApprovalSpy as unknown as MockCallSource, index, 0, "exec approval call"),
@@ -553,7 +563,7 @@ describe("createTelegramBot", () => {
553563
});
554564

555565
expect(editMessageReplyMarkupSpy).toHaveBeenCalledTimes(1);
556-
const [chatId, messageId, replyMarkup] = editMessageReplyMarkupSpy.mock.calls[0] ?? [];
566+
const [chatId, messageId, replyMarkup] = editMessageReplyMarkupSpy.mock.calls.at(0) ?? [];
557567
expect(chatId).toBe(1234);
558568
expect(messageId).toBe(21);
559569
expect(replyMarkup).toEqual({ reply_markup: { inline_keyboard: [] } });
@@ -988,7 +998,7 @@ describe("createTelegramBot", () => {
988998
expect(listCall.cfg).toBeTypeOf("object");
989999
expect(listCall.agentIds).toEqual(["main"]);
9901000
expect(editMessageTextSpy).toHaveBeenCalledTimes(1);
991-
const [chatId, messageId, text, params] = editMessageTextSpy.mock.calls[0] ?? [];
1001+
const [chatId, messageId, text, params] = editMessageTextSpy.mock.calls.at(0) ?? [];
9921002
expect(chatId).toBe(1234);
9931003
expect(messageId).toBe(12);
9941004
expect(String(text)).toContain(`${INFO_EMOJI} Commands (2/`);
@@ -1143,10 +1153,10 @@ describe("createTelegramBot", () => {
11431153

11441154
expect(replySpy).not.toHaveBeenCalled();
11451155
expect(editMessageTextSpy).toHaveBeenCalledTimes(1);
1146-
expect(editMessageTextSpy.mock.calls[0]?.[2]).toContain(
1156+
expect(editMessageTextSpy.mock.calls.at(0)?.[2]).toContain(
11471157
`${CHECK_MARK_EMOJI} Model reset to default`,
11481158
);
1149-
expect(editMessageTextSpy.mock.calls[0]?.[2]).toContain(
1159+
expect(editMessageTextSpy.mock.calls.at(0)?.[2]).toContain(
11501160
"Session selection cleared. Runtime unchanged. New replies use the agent's configured default.",
11511161
);
11521162

@@ -1219,7 +1229,7 @@ describe("createTelegramBot", () => {
12191229

12201230
expect(replySpy).not.toHaveBeenCalled();
12211231
expect(editMessageTextSpy).toHaveBeenCalledTimes(1);
1222-
const [, , , params] = editMessageTextSpy.mock.calls[0] ?? [];
1232+
const [, , , params] = editMessageTextSpy.mock.calls.at(0) ?? [];
12231233
const inlineKeyboard = (
12241234
params as {
12251235
reply_markup?: {
@@ -1293,10 +1303,10 @@ describe("createTelegramBot", () => {
12931303

12941304
expect(replySpy).not.toHaveBeenCalled();
12951305
expect(editMessageTextSpy).toHaveBeenCalledTimes(1);
1296-
expect(editMessageTextSpy.mock.calls[0]?.[2]).toContain(
1306+
expect(editMessageTextSpy.mock.calls.at(0)?.[2]).toContain(
12971307
`${CHECK_MARK_EMOJI} Model reset to default`,
12981308
);
1299-
expect(editMessageTextSpy.mock.calls[0]?.[2]).toContain(
1309+
expect(editMessageTextSpy.mock.calls.at(0)?.[2]).toContain(
13001310
"Session selection cleared. Runtime unchanged. New replies use the agent's configured default.",
13011311
);
13021312

@@ -1368,7 +1378,7 @@ describe("createTelegramBot", () => {
13681378

13691379
expect(replySpy).not.toHaveBeenCalled();
13701380
expect(editMessageTextSpy).toHaveBeenCalledTimes(1);
1371-
const editCall = editMessageTextSpy.mock.calls[0];
1381+
const editCall = editMessageTextSpy.mock.calls.at(0);
13721382
expect(editCall?.[0]).toBe(1234);
13731383
expect(editCall?.[1]).toBe(17);
13741384
expect(editCall?.[2]).toBe(
@@ -1523,7 +1533,7 @@ describe("createTelegramBot", () => {
15231533

15241534
expect(replySpy).not.toHaveBeenCalled();
15251535
expect(editMessageTextSpy).toHaveBeenCalledTimes(1);
1526-
expect(editMessageTextSpy.mock.calls[0]?.[2]).toContain(
1536+
expect(editMessageTextSpy.mock.calls.at(0)?.[2]).toContain(
15271537
'Could not resolve model "shared-model".',
15281538
);
15291539
expect(answerCallbackQuerySpy).toHaveBeenCalledWith("cbq-model-compact-2");
@@ -1568,7 +1578,7 @@ describe("createTelegramBot", () => {
15681578
});
15691579

15701580
expect(replySpy).toHaveBeenCalledTimes(1);
1571-
const payload = replySpy.mock.calls[0][0];
1581+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
15721582
const { expectChannelInboundContextContract: expectInboundContextContract } =
15731583
await loadInboundContextContract();
15741584
const { escapeRegExp, formatEnvelopeTimestamp } = await loadEnvelopeTimestampHelpers();
@@ -1659,7 +1669,7 @@ describe("createTelegramBot", () => {
16591669
});
16601670

16611671
expect(replySpy).toHaveBeenCalledTimes(1);
1662-
const payload = replySpy.mock.calls[0][0];
1672+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
16631673
const [conversationContext] = requireArray(
16641674
payload.UntrustedStructuredContext,
16651675
"structured context",
@@ -1762,7 +1772,7 @@ describe("createTelegramBot", () => {
17621772
});
17631773

17641774
expect(replySpy).toHaveBeenCalledTimes(1);
1765-
const payload = replySpy.mock.calls[0][0];
1775+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
17661776
const [conversationContext] = requireArray(
17671777
payload.UntrustedStructuredContext,
17681778
"structured context",
@@ -1807,7 +1817,7 @@ describe("createTelegramBot", () => {
18071817
});
18081818

18091819
expect(replySpy).toHaveBeenCalledTimes(1);
1810-
const payload = replySpy.mock.calls[0][0];
1820+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
18111821
expect(payload.Body).toContain("[Reply chain - nearest first]");
18121822
expect(payload.Body).toContain("[1. Ada id:9001]");
18131823
expect(payload.Body).toContain('"summarize this"');
@@ -1845,7 +1855,7 @@ describe("createTelegramBot", () => {
18451855
});
18461856

18471857
expect(replySpy).toHaveBeenCalledTimes(1);
1848-
const payload = replySpy.mock.calls[0][0];
1858+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
18491859
expect(payload.Body).toContain("[Reply chain - nearest first]");
18501860
expect(payload.Body).toContain("[1. Ada id:9001]");
18511861
expect(payload.Body).not.toContain("PK");
@@ -1900,7 +1910,12 @@ describe("createTelegramBot", () => {
19001910
}
19011911

19021912
expect(replySpy).toHaveBeenCalledTimes(1);
1903-
const payload = replySpy.mock.calls[0][0] as {
1913+
const payload = mockMsgContextArg(
1914+
replySpy as unknown as MockCallSource,
1915+
0,
1916+
0,
1917+
"replySpy call",
1918+
) as {
19041919
MediaPath?: string;
19051920
MediaPaths?: string[];
19061921
ReplyToBody?: string;
@@ -1990,7 +2005,12 @@ describe("createTelegramBot", () => {
19902005
}
19912006

19922007
expect(replySpy).toHaveBeenCalledTimes(1);
1993-
const payload = replySpy.mock.calls[0][0] as {
2008+
const payload = mockMsgContextArg(
2009+
replySpy as unknown as MockCallSource,
2010+
0,
2011+
0,
2012+
"replySpy call",
2013+
) as {
19942014
ReplyChain?: Array<{
19952015
messageId?: string;
19962016
body?: string;
@@ -2178,7 +2198,7 @@ describe("createTelegramBot", () => {
21782198
});
21792199

21802200
expect(replySpy).toHaveBeenCalledTimes(1);
2181-
const payload = replySpy.mock.calls[0][0];
2201+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
21822202
expect(payload.Body).toContain("[Reply chain - nearest first]");
21832203
expect(payload.Body).toContain("[1. unknown sender]");
21842204
expect(payload.Body).toContain('"summarize this"');
@@ -2214,7 +2234,7 @@ describe("createTelegramBot", () => {
22142234
});
22152235

22162236
expect(replySpy).toHaveBeenCalledTimes(1);
2217-
const payload = replySpy.mock.calls[0][0];
2237+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
22182238
expect(payload.Body).toContain("[Reply chain - nearest first]");
22192239
expect(payload.Body).toContain("[1. Ada id:9002]");
22202240
expect(payload.Body).toContain('"summarize this"');
@@ -2262,7 +2282,7 @@ describe("createTelegramBot", () => {
22622282
});
22632283

22642284
expect(replySpy).toHaveBeenCalledTimes(1);
2265-
const payload = replySpy.mock.calls[0][0];
2285+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
22662286
expect(payload.ReplyToForwardedFrom).toBe("Bob Smith (@bobsmith)");
22672287
expect(payload.ReplyToForwardedFromType).toBe("user");
22682288
expect(payload.ReplyToForwardedFromId).toBe("999");
@@ -2325,7 +2345,7 @@ describe("createTelegramBot", () => {
23252345
});
23262346

23272347
expect(replySpy).toHaveBeenCalledTimes(1);
2328-
const payload = replySpy.mock.calls[0][0];
2348+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
23292349
expect(payload.ReplyToId).toBe("9003");
23302350
expect(payload.ReplyToBody).toBe("forwarded text");
23312351
expect(payload.ReplyToSender).toBe("Ada");
@@ -2365,7 +2385,7 @@ describe("createTelegramBot", () => {
23652385
});
23662386

23672387
expect(replySpy).toHaveBeenCalledTimes(1);
2368-
const payload = replySpy.mock.calls[0][0];
2388+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
23692389
expect(payload.WasMentioned).toBe(true);
23702390
});
23712391

@@ -2837,7 +2857,7 @@ describe("createTelegramBot", () => {
28372857
});
28382858

28392859
expect(replySpy).toHaveBeenCalledTimes(1);
2840-
const payload = replySpy.mock.calls[0][0];
2860+
const payload = mockMsgContextArg(replySpy as unknown as MockCallSource, 0, 0, "replySpy call");
28412861
expect(payload.CommandTargetSessionKey).toBe("agent:main:main");
28422862
});
28432863

@@ -3019,7 +3039,7 @@ describe("createTelegramBot", () => {
30193039
});
30203040

30213041
expect(enqueueSystemEventSpy).toHaveBeenCalledTimes(1);
3022-
expect(enqueueSystemEventSpy.mock.calls[0]?.[0]).toBe(
3042+
expect(enqueueSystemEventSpy.mock.calls.at(0)?.[0]).toBe(
30233043
`Telegram reaction added: ${THUMBS_UP_EMOJI} by Ada (@ada_bot) on msg 42`,
30243044
);
30253045
expect(String(systemEventOptions().contextKey)).toContain("telegram:reaction:add:1234:42:9");
@@ -3247,10 +3267,10 @@ describe("createTelegramBot", () => {
32473267
});
32483268

32493269
expect(enqueueSystemEventSpy).toHaveBeenCalledTimes(1);
3250-
expect(enqueueSystemEventSpy.mock.calls[0]?.[0]).toBe(
3270+
expect(enqueueSystemEventSpy.mock.calls.at(0)?.[0]).toBe(
32513271
`Telegram reaction added: ${PARTY_EMOJI} by Ada on msg 99`,
32523272
);
3253-
expect(enqueueSystemEventSpy.mock.calls[0]?.[1]).toBeTypeOf("object");
3273+
expect(enqueueSystemEventSpy.mock.calls.at(0)?.[1]).toBeTypeOf("object");
32543274
});
32553275

32563276
it("skips reaction in own mode when message is not sent by bot", async () => {
@@ -3444,7 +3464,7 @@ describe("createTelegramBot", () => {
34443464
});
34453465

34463466
expect(enqueueSystemEventSpy).toHaveBeenCalledTimes(1);
3447-
expect(enqueueSystemEventSpy.mock.calls[0]?.[0]).toBe(
3467+
expect(enqueueSystemEventSpy.mock.calls.at(0)?.[0]).toBe(
34483468
`Telegram reaction added: ${FIRE_EMOJI} by Bob (@bob_user) on msg 100`,
34493469
);
34503470
expect(String(systemEventOptions().sessionKey)).toContain("telegram:group:5678:topic:1");
@@ -3480,7 +3500,7 @@ describe("createTelegramBot", () => {
34803500
});
34813501

34823502
expect(enqueueSystemEventSpy).toHaveBeenCalledTimes(1);
3483-
expect(enqueueSystemEventSpy.mock.calls[0]?.[0]).toBe(
3503+
expect(enqueueSystemEventSpy.mock.calls.at(0)?.[0]).toBe(
34843504
`Telegram reaction added: ${EYES_EMOJI} by Bob on msg 101`,
34853505
);
34863506
expect(String(systemEventOptions().sessionKey)).toContain("telegram:group:5678:topic:1");
@@ -3515,13 +3535,13 @@ describe("createTelegramBot", () => {
35153535
});
35163536

35173537
expect(enqueueSystemEventSpy).toHaveBeenCalledTimes(1);
3518-
expect(enqueueSystemEventSpy.mock.calls[0]?.[0]).toBe(
3538+
expect(enqueueSystemEventSpy.mock.calls.at(0)?.[0]).toBe(
35193539
`Telegram reaction added: ${HEART_EMOJI} by Charlie on msg 200`,
35203540
);
35213541
expect(String(systemEventOptions().sessionKey)).toContain("telegram:group:9999");
35223542
expect(String(systemEventOptions().contextKey)).toContain("telegram:reaction:add:9999:200:11");
35233543
// Verify session key does NOT contain :topic:
3524-
const eventOptions = enqueueSystemEventSpy.mock.calls[0]?.[1] as {
3544+
const eventOptions = enqueueSystemEventSpy.mock.calls.at(0)?.[1] as {
35253545
sessionKey?: string;
35263546
};
35273547
const sessionKey = eventOptions.sessionKey ?? "";

0 commit comments

Comments
 (0)