mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 23:04:32 +00:00
test(telegram): dedupe send fallback/media fixtures and trim reset overhead
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import type { Bot } from "grammy";
|
import type { Bot } from "grammy";
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||||
import {
|
import {
|
||||||
getTelegramSendTestMocks,
|
getTelegramSendTestMocks,
|
||||||
importTelegramSendModule,
|
importTelegramSendModule,
|
||||||
@@ -40,6 +40,22 @@ async function expectChatNotFoundWithChatId(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mockLoadedMedia({
|
||||||
|
buffer = Buffer.from("media"),
|
||||||
|
contentType,
|
||||||
|
fileName,
|
||||||
|
}: {
|
||||||
|
buffer?: Buffer;
|
||||||
|
contentType?: string;
|
||||||
|
fileName?: string;
|
||||||
|
}): void {
|
||||||
|
loadWebMedia.mockResolvedValueOnce({
|
||||||
|
buffer,
|
||||||
|
...(contentType ? { contentType } : {}),
|
||||||
|
...(fileName ? { fileName } : {}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
describe("sent-message-cache", () => {
|
describe("sent-message-cache", () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
clearSentMessageCache();
|
clearSentMessageCache();
|
||||||
@@ -189,34 +205,81 @@ describe("sendMessageTelegram", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("falls back to plain text when Telegram rejects HTML", async () => {
|
it("falls back to plain text when Telegram rejects HTML and preserves send params", async () => {
|
||||||
const chatId = "123";
|
|
||||||
const parseErr = new Error(
|
const parseErr = new Error(
|
||||||
"400: Bad Request: can't parse entities: Can't find end of the entity starting at byte offset 9",
|
"400: Bad Request: can't parse entities: Can't find end of the entity starting at byte offset 9",
|
||||||
);
|
);
|
||||||
const sendMessage = vi
|
const cases = [
|
||||||
.fn()
|
{
|
||||||
.mockRejectedValueOnce(parseErr)
|
name: "plain text send",
|
||||||
.mockResolvedValueOnce({
|
chatId: "123",
|
||||||
message_id: 42,
|
text: "_oops_",
|
||||||
chat: { id: chatId },
|
htmlText: "<i>oops</i>",
|
||||||
|
messageId: 42,
|
||||||
|
options: { verbose: true } as const,
|
||||||
|
firstCall: { parse_mode: "HTML" },
|
||||||
|
secondCall: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "threaded reply send",
|
||||||
|
chatId: "-1001234567890",
|
||||||
|
text: "_bad markdown_",
|
||||||
|
htmlText: "<i>bad markdown</i>",
|
||||||
|
messageId: 60,
|
||||||
|
options: { messageThreadId: 271, replyToMessageId: 100 } as const,
|
||||||
|
firstCall: {
|
||||||
|
parse_mode: "HTML",
|
||||||
|
message_thread_id: 271,
|
||||||
|
reply_to_message_id: 100,
|
||||||
|
},
|
||||||
|
secondCall: {
|
||||||
|
message_thread_id: 271,
|
||||||
|
reply_to_message_id: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
for (const testCase of cases) {
|
||||||
|
const sendMessage = vi
|
||||||
|
.fn()
|
||||||
|
.mockRejectedValueOnce(parseErr)
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
message_id: testCase.messageId,
|
||||||
|
chat: { id: testCase.chatId },
|
||||||
|
});
|
||||||
|
const api = { sendMessage } as unknown as {
|
||||||
|
sendMessage: typeof sendMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await sendMessageTelegram(testCase.chatId, testCase.text, {
|
||||||
|
token: "tok",
|
||||||
|
api,
|
||||||
|
...testCase.options,
|
||||||
});
|
});
|
||||||
const api = { sendMessage } as unknown as {
|
|
||||||
sendMessage: typeof sendMessage;
|
|
||||||
};
|
|
||||||
|
|
||||||
const res = await sendMessageTelegram(chatId, "_oops_", {
|
expect(sendMessage, testCase.name).toHaveBeenNthCalledWith(
|
||||||
token: "tok",
|
1,
|
||||||
api,
|
testCase.chatId,
|
||||||
verbose: true,
|
testCase.htmlText,
|
||||||
});
|
testCase.firstCall,
|
||||||
|
);
|
||||||
expect(sendMessage).toHaveBeenNthCalledWith(1, chatId, "<i>oops</i>", {
|
if (testCase.secondCall) {
|
||||||
parse_mode: "HTML",
|
expect(sendMessage, testCase.name).toHaveBeenNthCalledWith(
|
||||||
});
|
2,
|
||||||
expect(sendMessage).toHaveBeenNthCalledWith(2, chatId, "_oops_");
|
testCase.chatId,
|
||||||
expect(res.chatId).toBe(chatId);
|
testCase.text,
|
||||||
expect(res.messageId).toBe("42");
|
testCase.secondCall,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
expect(sendMessage, testCase.name).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
testCase.chatId,
|
||||||
|
testCase.text,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect(res.chatId, testCase.name).toBe(testCase.chatId);
|
||||||
|
expect(res.messageId, testCase.name).toBe(String(testCase.messageId));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps link_preview_options disabled for both html and plain-text fallback", async () => {
|
it("keeps link_preview_options disabled for both html and plain-text fallback", async () => {
|
||||||
@@ -306,41 +369,6 @@ describe("sendMessageTelegram", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("preserves thread params in plain text fallback", async () => {
|
|
||||||
const chatId = "-1001234567890";
|
|
||||||
const parseErr = new Error(
|
|
||||||
"400: Bad Request: can't parse entities: Can't find end of the entity",
|
|
||||||
);
|
|
||||||
const sendMessage = vi
|
|
||||||
.fn()
|
|
||||||
.mockRejectedValueOnce(parseErr)
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
message_id: 60,
|
|
||||||
chat: { id: chatId },
|
|
||||||
});
|
|
||||||
const api = { sendMessage } as unknown as {
|
|
||||||
sendMessage: typeof sendMessage;
|
|
||||||
};
|
|
||||||
|
|
||||||
const res = await sendMessageTelegram(chatId, "_bad markdown_", {
|
|
||||||
token: "tok",
|
|
||||||
api,
|
|
||||||
messageThreadId: 271,
|
|
||||||
replyToMessageId: 100,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(sendMessage).toHaveBeenNthCalledWith(1, chatId, "<i>bad markdown</i>", {
|
|
||||||
parse_mode: "HTML",
|
|
||||||
message_thread_id: 271,
|
|
||||||
reply_to_message_id: 100,
|
|
||||||
});
|
|
||||||
expect(sendMessage).toHaveBeenNthCalledWith(2, chatId, "_bad markdown_", {
|
|
||||||
message_thread_id: 271,
|
|
||||||
reply_to_message_id: 100,
|
|
||||||
});
|
|
||||||
expect(res.messageId).toBe("60");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("includes thread params in media messages", async () => {
|
it("includes thread params in media messages", async () => {
|
||||||
const chatId = "-1001234567890";
|
const chatId = "-1001234567890";
|
||||||
const sendPhoto = vi.fn().mockResolvedValue({
|
const sendPhoto = vi.fn().mockResolvedValue({
|
||||||
@@ -351,7 +379,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendPhoto: typeof sendPhoto;
|
sendPhoto: typeof sendPhoto;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-image"),
|
buffer: Buffer.from("fake-image"),
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
fileName: "photo.jpg",
|
fileName: "photo.jpg",
|
||||||
@@ -388,7 +416,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendMessage: typeof sendMessage;
|
sendMessage: typeof sendMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-image"),
|
buffer: Buffer.from("fake-image"),
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
fileName: "photo.jpg",
|
fileName: "photo.jpg",
|
||||||
@@ -423,7 +451,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendMessage: typeof sendMessage;
|
sendMessage: typeof sendMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-image"),
|
buffer: Buffer.from("fake-image"),
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
fileName: "photo.jpg",
|
fileName: "photo.jpg",
|
||||||
@@ -455,7 +483,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendPhoto: typeof sendPhoto;
|
sendPhoto: typeof sendPhoto;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-image"),
|
buffer: Buffer.from("fake-image"),
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
fileName: "photo.jpg",
|
fileName: "photo.jpg",
|
||||||
@@ -491,7 +519,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendMessage: typeof sendMessage;
|
sendMessage: typeof sendMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-video"),
|
buffer: Buffer.from("fake-video"),
|
||||||
contentType: "video/mp4",
|
contentType: "video/mp4",
|
||||||
fileName: "video.mp4",
|
fileName: "video.mp4",
|
||||||
@@ -521,7 +549,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendVideo: typeof sendVideo;
|
sendVideo: typeof sendVideo;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-video"),
|
buffer: Buffer.from("fake-video"),
|
||||||
contentType: "video/mp4",
|
contentType: "video/mp4",
|
||||||
fileName: "video.mp4",
|
fileName: "video.mp4",
|
||||||
@@ -590,7 +618,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendMessage: typeof sendMessage;
|
sendMessage: typeof sendMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-video"),
|
buffer: Buffer.from("fake-video"),
|
||||||
contentType: "video/mp4",
|
contentType: "video/mp4",
|
||||||
fileName: "video.mp4",
|
fileName: "video.mp4",
|
||||||
@@ -680,7 +708,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendAnimation: typeof sendAnimation;
|
sendAnimation: typeof sendAnimation;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("GIF89a"),
|
buffer: Buffer.from("GIF89a"),
|
||||||
fileName: "fun.gif",
|
fileName: "fun.gif",
|
||||||
});
|
});
|
||||||
@@ -779,7 +807,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendVoice: typeof sendVoice;
|
sendVoice: typeof sendVoice;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("audio"),
|
buffer: Buffer.from("audio"),
|
||||||
contentType: testCase.contentType,
|
contentType: testCase.contentType,
|
||||||
fileName: testCase.fileName,
|
fileName: testCase.fileName,
|
||||||
@@ -1006,7 +1034,7 @@ describe("sendMessageTelegram", () => {
|
|||||||
sendPhoto: typeof sendPhoto;
|
sendPhoto: typeof sendPhoto;
|
||||||
};
|
};
|
||||||
|
|
||||||
loadWebMedia.mockResolvedValueOnce({
|
mockLoadedMedia({
|
||||||
buffer: Buffer.from("fake-image"),
|
buffer: Buffer.from("fake-image"),
|
||||||
contentType: "image/jpeg",
|
contentType: "image/jpeg",
|
||||||
fileName: "photo.jpg",
|
fileName: "photo.jpg",
|
||||||
@@ -1075,26 +1103,18 @@ describe("reactMessageTelegram", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("sendStickerTelegram", () => {
|
describe("sendStickerTelegram", () => {
|
||||||
beforeEach(() => {
|
|
||||||
loadConfig.mockReturnValue({});
|
|
||||||
botApi.sendSticker.mockReset();
|
|
||||||
botCtorSpy.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
const positiveSendCases = [
|
const positiveSendCases = [
|
||||||
{
|
{
|
||||||
name: "sends a sticker by file_id",
|
name: "sends a sticker by file_id",
|
||||||
fileId: "CAACAgIAAxkBAAI...sticker_file_id",
|
fileId: "CAACAgIAAxkBAAI...sticker_file_id",
|
||||||
expectedFileId: "CAACAgIAAxkBAAI...sticker_file_id",
|
expectedFileId: "CAACAgIAAxkBAAI...sticker_file_id",
|
||||||
expectedMessageId: 100,
|
expectedMessageId: 100,
|
||||||
assertResult: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "trims whitespace from fileId",
|
name: "trims whitespace from fileId",
|
||||||
fileId: " fileId123 ",
|
fileId: " fileId123 ",
|
||||||
expectedFileId: "fileId123",
|
expectedFileId: "fileId123",
|
||||||
expectedMessageId: 106,
|
expectedMessageId: 106,
|
||||||
assertResult: false,
|
|
||||||
},
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
@@ -1115,10 +1135,8 @@ describe("sendStickerTelegram", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(sendSticker).toHaveBeenCalledWith(chatId, testCase.expectedFileId, undefined);
|
expect(sendSticker).toHaveBeenCalledWith(chatId, testCase.expectedFileId, undefined);
|
||||||
if (testCase.assertResult) {
|
expect(res.messageId).toBe(String(testCase.expectedMessageId));
|
||||||
expect(res.messageId).toBe(String(testCase.expectedMessageId));
|
expect(res.chatId).toBe(chatId);
|
||||||
expect(res.chatId).toBe(chatId);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1253,11 +1271,6 @@ describe("shared send behaviors", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("editMessageTelegram", () => {
|
describe("editMessageTelegram", () => {
|
||||||
beforeEach(() => {
|
|
||||||
botApi.editMessageText.mockReset();
|
|
||||||
botCtorSpy.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("handles button payload + parse fallback behavior", async () => {
|
it("handles button payload + parse fallback behavior", async () => {
|
||||||
const cases: Array<{
|
const cases: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user