import crypto from "node:crypto"; import fsSync from "node:fs"; import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { resetLogger, setLoggerOverride } from "../logging.js"; import { monitorWebInbox } from "./inbound.js"; import { getLastSocket, resetBaileysMocks, resetLoadConfigMock, } from "./test-helpers.js"; describe("web monitor inbox", () => { beforeEach(() => { vi.clearAllMocks(); resetBaileysMocks(); resetLoadConfigMock(); }); afterEach(() => { resetLogger(); setLoggerOverride(null); vi.useRealTimers(); }); it("streams inbound messages", async () => { const onMessage = vi.fn(async (msg) => { await msg.sendComposing(); await msg.reply("pong"); }); const listener = await monitorWebInbox({ verbose: false, onMessage }); const sock = getLastSocket(); expect(sock.sendPresenceUpdate).toHaveBeenCalledWith("available"); const upsert = { type: "notify", messages: [ { key: { id: "abc", fromMe: false, remoteJid: "999@s.whatsapp.net" }, message: { conversation: "ping" }, messageTimestamp: 1_700_000_000, pushName: "Tester", }, ], }; sock.ev.emit("messages.upsert", upsert); await new Promise((resolve) => setImmediate(resolve)); expect(onMessage).toHaveBeenCalledWith( expect.objectContaining({ body: "ping", from: "+999", to: "+123" }), ); expect(sock.readMessages).toHaveBeenCalledWith([ { remoteJid: "999@s.whatsapp.net", id: "abc", participant: undefined, fromMe: false, }, ]); expect(sock.sendPresenceUpdate).toHaveBeenCalledWith("available"); expect(sock.sendPresenceUpdate).toHaveBeenCalledWith( "composing", "999@s.whatsapp.net", ); expect(sock.sendMessage).toHaveBeenCalledWith("999@s.whatsapp.net", { text: "pong", }); await listener.close(); }); it("captures media path for image messages", async () => { const onMessage = vi.fn(); const listener = await monitorWebInbox({ verbose: false, onMessage }); const sock = getLastSocket(); const upsert = { type: "notify", messages: [ { key: { id: "med1", fromMe: false, remoteJid: "888@s.whatsapp.net" }, message: { imageMessage: { mimetype: "image/jpeg" } }, messageTimestamp: 1_700_000_100, }, ], }; sock.ev.emit("messages.upsert", upsert); await new Promise((resolve) => setImmediate(resolve)); expect(onMessage).toHaveBeenCalledWith( expect.objectContaining({ body: "", mediaPath: "/tmp/mid", mediaType: "image/jpeg", }), ); expect(sock.readMessages).toHaveBeenCalledWith([ { remoteJid: "888@s.whatsapp.net", id: "med1", participant: undefined, fromMe: false, }, ]); expect(sock.sendPresenceUpdate).toHaveBeenCalledWith("available"); await listener.close(); }); it("resolves onClose when the socket closes", async () => { const listener = await monitorWebInbox({ verbose: false, onMessage: vi.fn(), }); const sock = getLastSocket(); const reasonPromise = listener.onClose; sock.ev.emit("connection.update", { connection: "close", lastDisconnect: { error: { output: { statusCode: 500 } } }, }); await expect(reasonPromise).resolves.toEqual( expect.objectContaining({ status: 500, isLoggedOut: false }), ); await listener.close(); }); it("logs inbound bodies to file", async () => { const logPath = path.join( os.tmpdir(), `warelay-log-test-${crypto.randomUUID()}.log`, ); setLoggerOverride({ level: "trace", file: logPath }); const onMessage = vi.fn(); const listener = await monitorWebInbox({ verbose: false, onMessage }); const sock = getLastSocket(); const upsert = { type: "notify", messages: [ { key: { id: "abc", fromMe: false, remoteJid: "999@s.whatsapp.net" }, message: { conversation: "ping" }, messageTimestamp: 1_700_000_000, pushName: "Tester", }, ], }; sock.ev.emit("messages.upsert", upsert); await new Promise((resolve) => setImmediate(resolve)); const content = fsSync.readFileSync(logPath, "utf-8"); expect(content).toContain('"module":"web-inbound"'); expect(content).toContain('"body":"ping"'); await listener.close(); }); it("includes participant when marking group messages read", async () => { const onMessage = vi.fn(); const listener = await monitorWebInbox({ verbose: false, onMessage }); const sock = getLastSocket(); const upsert = { type: "notify", messages: [ { key: { id: "grp1", fromMe: false, remoteJid: "12345-67890@g.us", participant: "111@s.whatsapp.net", }, message: { conversation: "group ping" }, }, ], }; sock.ev.emit("messages.upsert", upsert); await new Promise((resolve) => setImmediate(resolve)); expect(sock.readMessages).toHaveBeenCalledWith([ { remoteJid: "12345-67890@g.us", id: "grp1", participant: "111@s.whatsapp.net", fromMe: false, }, ]); await listener.close(); }); });