Files
openclaw/extensions/whatsapp/src/qa-driver.runtime.test.ts
Patrick Erichsen 84e8e09725 Add WhatsApp live QA lane (#77704)
* feat(qa): add whatsapp live lane

* ci: add gated whatsapp and discord qa live lanes

* ci: honor qa live env gates in release selection

* test: update qa live workflow gate assertion

* ci: split live QA release gates
2026-05-05 12:09:28 -07:00

124 lines
3.3 KiB
TypeScript

import { EventEmitter } from "node:events";
import type { WAMessage } from "@whiskeysockets/baileys";
import { afterEach, describe, expect, it, vi } from "vitest";
import { startWhatsAppQaDriverSession } from "./qa-driver.runtime.js";
const mocks = vi.hoisted(() => ({
createWaSocket: vi.fn(),
jidToE164: vi.fn(),
sendMessage: vi.fn(),
waitForWaConnection: vi.fn(),
}));
vi.mock("./session.js", () => ({
createWaSocket: mocks.createWaSocket,
waitForWaConnection: mocks.waitForWaConnection,
}));
vi.mock("./text-runtime.js", () => ({
jidToE164: mocks.jidToE164,
}));
vi.mock("./inbound/send-api.js", () => ({
createWebSendApi: () => ({
sendMessage: mocks.sendMessage,
}),
}));
function createMockSocket() {
return {
end: vi.fn(),
ev: new EventEmitter(),
ws: {
close: vi.fn(),
},
};
}
function incomingMessage(remoteJid: string, text: string): WAMessage {
return {
key: {
fromMe: false,
id: "message-1",
remoteJid,
},
message: {
conversation: text,
},
} as WAMessage;
}
describe("startWhatsAppQaDriverSession", () => {
afterEach(() => {
vi.useRealTimers();
vi.clearAllMocks();
});
it("normalizes LID-backed senders using the QA auth directory", async () => {
const sock = createMockSocket();
mocks.createWaSocket.mockResolvedValue(sock);
mocks.waitForWaConnection.mockResolvedValue(undefined);
mocks.jidToE164.mockReturnValue("+15551234567");
const session = await startWhatsAppQaDriverSession({
authDir: "/tmp/openclaw-whatsapp-auth",
});
sock.ev.emit("messages.upsert", {
messages: [incomingMessage("12345@lid", "hello")],
});
expect(mocks.jidToE164).toHaveBeenCalledWith("12345@lid", {
authDir: "/tmp/openclaw-whatsapp-auth",
});
expect(session.getObservedMessages()).toMatchObject([
{
fromJid: "12345@lid",
fromPhoneE164: "+15551234567",
messageId: "message-1",
text: "hello",
},
]);
await session.close();
});
it("clears the connection timeout after a successful connection", async () => {
vi.useFakeTimers();
const sock = createMockSocket();
mocks.createWaSocket.mockResolvedValue(sock);
mocks.waitForWaConnection.mockResolvedValue(undefined);
const session = await startWhatsAppQaDriverSession({
authDir: "/tmp/openclaw-whatsapp-auth",
connectionTimeoutMs: 45_000,
});
expect(vi.getTimerCount()).toBe(0);
await session.close();
});
it("closes the socket and removes listeners when connection setup times out", async () => {
vi.useFakeTimers();
const sock = createMockSocket();
mocks.createWaSocket.mockResolvedValue(sock);
mocks.waitForWaConnection.mockReturnValue(new Promise(() => {}));
const started = startWhatsAppQaDriverSession({
authDir: "/tmp/openclaw-whatsapp-auth",
connectionTimeoutMs: 10,
});
const rejection = started.catch((error: unknown) => error);
await vi.advanceTimersByTimeAsync(10);
const error = await rejection;
expect(error).toBeInstanceOf(Error);
expect((error as Error).message).toContain("timed out waiting for WhatsApp QA driver session");
expect(sock.ev.listenerCount("messages.upsert")).toBe(0);
expect(sock.end).toHaveBeenCalledOnce();
expect(vi.getTimerCount()).toBe(0);
});
});