| import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; |
|
|
| import { resetLogger, setLoggerOverride } from "../logging.js"; |
| import { setActiveWebListener } from "./active-listener.js"; |
|
|
| const loadWebMediaMock = vi.fn(); |
| vi.mock("./media.js", () => ({ |
| loadWebMedia: (...args: unknown[]) => loadWebMediaMock(...args), |
| })); |
|
|
| import { sendMessageWhatsApp, sendPollWhatsApp, sendReactionWhatsApp } from "./outbound.js"; |
|
|
| describe("web outbound", () => { |
| const sendComposingTo = vi.fn(async () => {}); |
| const sendMessage = vi.fn(async () => ({ messageId: "msg123" })); |
| const sendPoll = vi.fn(async () => ({ messageId: "poll123" })); |
| const sendReaction = vi.fn(async () => {}); |
|
|
| beforeEach(() => { |
| vi.clearAllMocks(); |
| setActiveWebListener({ |
| sendComposingTo, |
| sendMessage, |
| sendPoll, |
| sendReaction, |
| }); |
| }); |
|
|
| afterEach(() => { |
| resetLogger(); |
| setLoggerOverride(null); |
| setActiveWebListener(null); |
| }); |
|
|
| it("sends message via active listener", async () => { |
| const result = await sendMessageWhatsApp("+1555", "hi", { verbose: false }); |
| expect(result).toEqual({ |
| messageId: "msg123", |
| toJid: "1555@s.whatsapp.net", |
| }); |
| expect(sendComposingTo).toHaveBeenCalledWith("+1555"); |
| expect(sendMessage).toHaveBeenCalledWith("+1555", "hi", undefined, undefined); |
| }); |
|
|
| it("throws a helpful error when no active listener exists", async () => { |
| setActiveWebListener(null); |
| await expect( |
| sendMessageWhatsApp("+1555", "hi", { verbose: false, accountId: "work" }), |
| ).rejects.toThrow(/No active WhatsApp Web listener/); |
| await expect( |
| sendMessageWhatsApp("+1555", "hi", { verbose: false, accountId: "work" }), |
| ).rejects.toThrow(/channels login/); |
| await expect( |
| sendMessageWhatsApp("+1555", "hi", { verbose: false, accountId: "work" }), |
| ).rejects.toThrow(/account: work/); |
| }); |
|
|
| it("maps audio to PTT with opus mime when ogg", async () => { |
| const buf = Buffer.from("audio"); |
| loadWebMediaMock.mockResolvedValueOnce({ |
| buffer: buf, |
| contentType: "audio/ogg", |
| kind: "audio", |
| }); |
| await sendMessageWhatsApp("+1555", "voice note", { |
| verbose: false, |
| mediaUrl: "/tmp/voice.ogg", |
| }); |
| expect(sendMessage).toHaveBeenLastCalledWith( |
| "+1555", |
| "voice note", |
| buf, |
| "audio/ogg; codecs=opus", |
| ); |
| }); |
|
|
| it("maps video with caption", async () => { |
| const buf = Buffer.from("video"); |
| loadWebMediaMock.mockResolvedValueOnce({ |
| buffer: buf, |
| contentType: "video/mp4", |
| kind: "video", |
| }); |
| await sendMessageWhatsApp("+1555", "clip", { |
| verbose: false, |
| mediaUrl: "/tmp/video.mp4", |
| }); |
| expect(sendMessage).toHaveBeenLastCalledWith("+1555", "clip", buf, "video/mp4"); |
| }); |
|
|
| it("marks gif playback for video when requested", async () => { |
| const buf = Buffer.from("gifvid"); |
| loadWebMediaMock.mockResolvedValueOnce({ |
| buffer: buf, |
| contentType: "video/mp4", |
| kind: "video", |
| }); |
| await sendMessageWhatsApp("+1555", "gif", { |
| verbose: false, |
| mediaUrl: "/tmp/anim.mp4", |
| gifPlayback: true, |
| }); |
| expect(sendMessage).toHaveBeenLastCalledWith("+1555", "gif", buf, "video/mp4", { |
| gifPlayback: true, |
| }); |
| }); |
|
|
| it("maps image with caption", async () => { |
| const buf = Buffer.from("img"); |
| loadWebMediaMock.mockResolvedValueOnce({ |
| buffer: buf, |
| contentType: "image/jpeg", |
| kind: "image", |
| }); |
| await sendMessageWhatsApp("+1555", "pic", { |
| verbose: false, |
| mediaUrl: "/tmp/pic.jpg", |
| }); |
| expect(sendMessage).toHaveBeenLastCalledWith("+1555", "pic", buf, "image/jpeg"); |
| }); |
|
|
| it("maps other kinds to document with filename", async () => { |
| const buf = Buffer.from("pdf"); |
| loadWebMediaMock.mockResolvedValueOnce({ |
| buffer: buf, |
| contentType: "application/pdf", |
| kind: "document", |
| fileName: "file.pdf", |
| }); |
| await sendMessageWhatsApp("+1555", "doc", { |
| verbose: false, |
| mediaUrl: "/tmp/file.pdf", |
| }); |
| expect(sendMessage).toHaveBeenLastCalledWith("+1555", "doc", buf, "application/pdf"); |
| }); |
|
|
| it("sends polls via active listener", async () => { |
| const result = await sendPollWhatsApp( |
| "+1555", |
| { question: "Lunch?", options: ["Pizza", "Sushi"], maxSelections: 2 }, |
| { verbose: false }, |
| ); |
| expect(result).toEqual({ |
| messageId: "poll123", |
| toJid: "1555@s.whatsapp.net", |
| }); |
| expect(sendPoll).toHaveBeenCalledWith("+1555", { |
| question: "Lunch?", |
| options: ["Pizza", "Sushi"], |
| maxSelections: 2, |
| durationHours: undefined, |
| }); |
| }); |
|
|
| it("sends reactions via active listener", async () => { |
| await sendReactionWhatsApp("1555@s.whatsapp.net", "msg123", "✅", { |
| verbose: false, |
| fromMe: false, |
| }); |
| expect(sendReaction).toHaveBeenCalledWith( |
| "1555@s.whatsapp.net", |
| "msg123", |
| "✅", |
| false, |
| undefined, |
| ); |
| }); |
| }); |
|
|