import { beforeEach, describe, expect, it, vi } from "vitest"; const recordChannelActivity = vi.fn(); vi.mock("../../infra/channel-activity.js", () => ({ recordChannelActivity: (...args: unknown[]) => recordChannelActivity(...args), })); import { createWebSendApi } from "./send-api.js"; describe("createWebSendApi", () => { const sendMessage = vi.fn(async () => ({ key: { id: "msg-1" } })); const sendPresenceUpdate = vi.fn(async () => {}); const api = createWebSendApi({ sock: { sendMessage, sendPresenceUpdate }, defaultAccountId: "main", }); beforeEach(() => { vi.clearAllMocks(); }); it("uses sendOptions fileName for outbound documents", async () => { const payload = Buffer.from("pdf"); await api.sendMessage("+1555", "doc", payload, "application/pdf", { fileName: "invoice.pdf" }); expect(sendMessage).toHaveBeenCalledWith( "1555@s.whatsapp.net", expect.objectContaining({ document: payload, fileName: "invoice.pdf", caption: "doc", mimetype: "application/pdf", }), ); expect(recordChannelActivity).toHaveBeenCalledWith({ channel: "whatsapp", accountId: "main", direction: "outbound", }); }); it("falls back to default document filename when fileName is absent", async () => { const payload = Buffer.from("pdf"); await api.sendMessage("+1555", "doc", payload, "application/pdf"); expect(sendMessage).toHaveBeenCalledWith( "1555@s.whatsapp.net", expect.objectContaining({ document: payload, fileName: "file", caption: "doc", mimetype: "application/pdf", }), ); }); it("sends plain text messages", async () => { await api.sendMessage("+1555", "hello"); expect(sendMessage).toHaveBeenCalledWith("1555@s.whatsapp.net", { text: "hello" }); expect(recordChannelActivity).toHaveBeenCalledWith({ channel: "whatsapp", accountId: "main", direction: "outbound", }); }); it("supports image media with caption", async () => { const payload = Buffer.from("img"); await api.sendMessage("+1555", "cap", payload, "image/jpeg"); expect(sendMessage).toHaveBeenCalledWith( "1555@s.whatsapp.net", expect.objectContaining({ image: payload, caption: "cap", mimetype: "image/jpeg", }), ); }); it("supports audio as push-to-talk voice note", async () => { const payload = Buffer.from("aud"); await api.sendMessage("+1555", "", payload, "audio/ogg", { accountId: "alt" }); expect(sendMessage).toHaveBeenCalledWith( "1555@s.whatsapp.net", expect.objectContaining({ audio: payload, ptt: true, mimetype: "audio/ogg", }), ); expect(recordChannelActivity).toHaveBeenCalledWith({ channel: "whatsapp", accountId: "alt", direction: "outbound", }); }); it("supports video media and gifPlayback option", async () => { const payload = Buffer.from("vid"); await api.sendMessage("+1555", "cap", payload, "video/mp4", { gifPlayback: true }); expect(sendMessage).toHaveBeenCalledWith( "1555@s.whatsapp.net", expect.objectContaining({ video: payload, caption: "cap", mimetype: "video/mp4", gifPlayback: true, }), ); }); it("falls back to unknown messageId if Baileys result does not expose key.id", async () => { sendMessage.mockResolvedValueOnce({ key: {} }); const res = await api.sendMessage("+1555", "hello"); expect(res.messageId).toBe("unknown"); }); it("sends polls and records outbound activity", async () => { const res = await api.sendPoll("+1555", { question: "Q?", options: ["a", "b"], maxSelections: 2, }); expect(sendMessage).toHaveBeenCalledWith( "1555@s.whatsapp.net", expect.objectContaining({ poll: { name: "Q?", values: ["a", "b"], selectableCount: 2 }, }), ); expect(res.messageId).toBe("msg-1"); expect(recordChannelActivity).toHaveBeenCalledWith({ channel: "whatsapp", accountId: "main", direction: "outbound", }); }); it("sends reactions with participant JID normalization", async () => { await api.sendReaction("+1555", "msg-2", "👍", false, "+1999"); expect(sendMessage).toHaveBeenCalledWith( "1555@s.whatsapp.net", expect.objectContaining({ react: { text: "👍", key: expect.objectContaining({ remoteJid: "1555@s.whatsapp.net", id: "msg-2", fromMe: false, participant: "1999@s.whatsapp.net", }), }, }), ); }); it("sends composing presence updates to the recipient JID", async () => { await api.sendComposingTo("+1555"); expect(sendPresenceUpdate).toHaveBeenCalledWith("composing", "1555@s.whatsapp.net"); }); });