import { describe, expect, it, vi } from "vitest"; import { sendMessageTelegram } from "./send.js"; describe("sendMessageTelegram", () => { it("falls back to plain text when Telegram rejects Markdown", async () => { const chatId = "123"; const parseErr = new Error( "400: Bad Request: can't parse entities: Can't find end of the entity starting at byte offset 9", ); const sendMessage = vi .fn() .mockRejectedValueOnce(parseErr) .mockResolvedValueOnce({ message_id: 42, chat: { id: chatId }, }); const api = { sendMessage } as unknown as { sendMessage: typeof sendMessage; }; const res = await sendMessageTelegram(chatId, "_oops_", { token: "tok", api, verbose: true, }); expect(sendMessage).toHaveBeenNthCalledWith(1, chatId, "_oops_", { parse_mode: "Markdown", }); expect(sendMessage).toHaveBeenNthCalledWith(2, chatId, "_oops_"); expect(res.chatId).toBe(chatId); expect(res.messageId).toBe("42"); }); it("normalizes chat ids with internal prefixes", async () => { const sendMessage = vi.fn().mockResolvedValue({ message_id: 1, chat: { id: "123" }, }); const api = { sendMessage } as unknown as { sendMessage: typeof sendMessage; }; await sendMessageTelegram("telegram:123", "hi", { token: "tok", api, }); expect(sendMessage).toHaveBeenCalledWith("123", "hi", { parse_mode: "Markdown", }); }); it("wraps chat-not-found with actionable context", async () => { const chatId = "123"; const err = new Error("400: Bad Request: chat not found"); const sendMessage = vi.fn().mockRejectedValue(err); const api = { sendMessage } as unknown as { sendMessage: typeof sendMessage; }; await expect( sendMessageTelegram(chatId, "hi", { token: "tok", api }), ).rejects.toThrow(/chat not found/i); await expect( sendMessageTelegram(chatId, "hi", { token: "tok", api }), ).rejects.toThrow(/chat_id=123/); }); });