mirror of https://github.com/openclaw/openclaw.git
220 lines
5.7 KiB
TypeScript
220 lines
5.7 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const { botApi, botCtorSpy } = vi.hoisted(() => ({
|
|
botApi: {
|
|
sendMessage: vi.fn(),
|
|
sendVideo: vi.fn(),
|
|
sendVideoNote: vi.fn(),
|
|
},
|
|
botCtorSpy: vi.fn(),
|
|
}));
|
|
|
|
const { loadWebMedia } = vi.hoisted(() => ({
|
|
loadWebMedia: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("../web/media.js", () => ({
|
|
loadWebMedia,
|
|
}));
|
|
|
|
vi.mock("grammy", () => ({
|
|
Bot: class {
|
|
api = botApi;
|
|
catch = vi.fn();
|
|
constructor(
|
|
public token: string,
|
|
public options?: {
|
|
client?: { fetch?: typeof fetch; timeoutSeconds?: number };
|
|
},
|
|
) {
|
|
botCtorSpy(token, options);
|
|
}
|
|
},
|
|
InputFile: class {},
|
|
}));
|
|
|
|
const { loadConfig } = vi.hoisted(() => ({
|
|
loadConfig: vi.fn(() => ({})),
|
|
}));
|
|
vi.mock("../config/config.js", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("../config/config.js")>();
|
|
return {
|
|
...actual,
|
|
loadConfig,
|
|
};
|
|
});
|
|
|
|
import { sendMessageTelegram } from "./send.js";
|
|
|
|
describe("sendMessageTelegram video notes", () => {
|
|
beforeEach(() => {
|
|
loadConfig.mockReturnValue({});
|
|
loadWebMedia.mockReset();
|
|
botApi.sendMessage.mockReset();
|
|
botApi.sendVideo.mockReset();
|
|
botApi.sendVideoNote.mockReset();
|
|
botCtorSpy.mockReset();
|
|
});
|
|
|
|
it("sends video as video note when asVideoNote is true", async () => {
|
|
const chatId = "123";
|
|
const text = "ignored caption context"; // Should be sent separately
|
|
|
|
const sendVideoNote = vi.fn().mockResolvedValue({
|
|
message_id: 101,
|
|
chat: { id: chatId },
|
|
});
|
|
const sendMessage = vi.fn().mockResolvedValue({
|
|
message_id: 102,
|
|
chat: { id: chatId },
|
|
});
|
|
const api = { sendVideoNote, sendMessage } as unknown as {
|
|
sendVideoNote: typeof sendVideoNote;
|
|
sendMessage: typeof sendMessage;
|
|
};
|
|
|
|
loadWebMedia.mockResolvedValueOnce({
|
|
buffer: Buffer.from("fake-video"),
|
|
contentType: "video/mp4",
|
|
fileName: "video.mp4",
|
|
});
|
|
|
|
const res = await sendMessageTelegram(chatId, text, {
|
|
token: "tok",
|
|
api,
|
|
mediaUrl: "https://example.com/video.mp4",
|
|
asVideoNote: true,
|
|
});
|
|
|
|
// Video note sent WITHOUT caption (video notes cannot have captions)
|
|
expect(sendVideoNote).toHaveBeenCalledWith(chatId, expect.anything(), {});
|
|
|
|
// Text sent as separate message
|
|
expect(sendMessage).toHaveBeenCalledWith(chatId, text, {
|
|
parse_mode: "HTML",
|
|
});
|
|
|
|
// Returns the text message ID as it is the "main" content with text
|
|
expect(res.messageId).toBe("102");
|
|
});
|
|
|
|
it("sends regular video when asVideoNote is false", async () => {
|
|
const chatId = "123";
|
|
const text = "my caption";
|
|
|
|
const sendVideo = vi.fn().mockResolvedValue({
|
|
message_id: 201,
|
|
chat: { id: chatId },
|
|
});
|
|
const api = { sendVideo } as unknown as {
|
|
sendVideo: typeof sendVideo;
|
|
};
|
|
|
|
loadWebMedia.mockResolvedValueOnce({
|
|
buffer: Buffer.from("fake-video"),
|
|
contentType: "video/mp4",
|
|
fileName: "video.mp4",
|
|
});
|
|
|
|
const res = await sendMessageTelegram(chatId, text, {
|
|
token: "tok",
|
|
api,
|
|
mediaUrl: "https://example.com/video.mp4",
|
|
asVideoNote: false,
|
|
});
|
|
|
|
// Regular video sent WITH caption
|
|
expect(sendVideo).toHaveBeenCalledWith(chatId, expect.anything(), {
|
|
caption: expect.any(String),
|
|
parse_mode: "HTML",
|
|
});
|
|
expect(res.messageId).toBe("201");
|
|
});
|
|
|
|
it("adds reply_markup to separate text message for video notes", async () => {
|
|
const chatId = "123";
|
|
const text = "Check this out";
|
|
|
|
const sendVideoNote = vi.fn().mockResolvedValue({
|
|
message_id: 301,
|
|
chat: { id: chatId },
|
|
});
|
|
const sendMessage = vi.fn().mockResolvedValue({
|
|
message_id: 302,
|
|
chat: { id: chatId },
|
|
});
|
|
const api = { sendVideoNote, sendMessage } as unknown as {
|
|
sendVideoNote: typeof sendVideoNote;
|
|
sendMessage: typeof sendMessage;
|
|
};
|
|
|
|
loadWebMedia.mockResolvedValueOnce({
|
|
buffer: Buffer.from("fake-video"),
|
|
contentType: "video/mp4",
|
|
fileName: "video.mp4",
|
|
});
|
|
|
|
await sendMessageTelegram(chatId, text, {
|
|
token: "tok",
|
|
api,
|
|
mediaUrl: "https://example.com/video.mp4",
|
|
asVideoNote: true,
|
|
buttons: [[{ text: "Btn", callback_data: "dat" }]],
|
|
});
|
|
|
|
// Video note sent WITHOUT reply_markup (it goes to text)
|
|
expect(sendVideoNote).toHaveBeenCalledWith(chatId, expect.anything(), {});
|
|
|
|
// Text message gets reply markup
|
|
expect(sendMessage).toHaveBeenCalledWith(chatId, text, {
|
|
parse_mode: "HTML",
|
|
reply_markup: {
|
|
inline_keyboard: [[{ text: "Btn", callback_data: "dat" }]],
|
|
},
|
|
});
|
|
});
|
|
|
|
it("threads video note and text message correctly", async () => {
|
|
const chatId = "123";
|
|
const text = "Threaded reply";
|
|
|
|
const sendVideoNote = vi.fn().mockResolvedValue({
|
|
message_id: 401,
|
|
chat: { id: chatId },
|
|
});
|
|
const sendMessage = vi.fn().mockResolvedValue({
|
|
message_id: 402,
|
|
chat: { id: chatId },
|
|
});
|
|
const api = { sendVideoNote, sendMessage } as unknown as {
|
|
sendVideoNote: typeof sendVideoNote;
|
|
sendMessage: typeof sendMessage;
|
|
};
|
|
|
|
loadWebMedia.mockResolvedValueOnce({
|
|
buffer: Buffer.from("fake-video"),
|
|
contentType: "video/mp4",
|
|
fileName: "video.mp4",
|
|
});
|
|
|
|
await sendMessageTelegram(chatId, text, {
|
|
token: "tok",
|
|
api,
|
|
mediaUrl: "https://example.com/video.mp4",
|
|
asVideoNote: true,
|
|
replyToMessageId: 999,
|
|
});
|
|
|
|
// Video note threaded
|
|
expect(sendVideoNote).toHaveBeenCalledWith(chatId, expect.anything(), {
|
|
reply_to_message_id: 999,
|
|
});
|
|
|
|
// Text threaded
|
|
expect(sendMessage).toHaveBeenCalledWith(chatId, text, {
|
|
parse_mode: "HTML",
|
|
reply_to_message_id: 999,
|
|
});
|
|
});
|
|
});
|