


























@@ -3,6 +3,31 @@ import { createWhatsAppOutboundBase } from "./outbound-base.js";
33import { createWhatsAppPollFixture } from "./outbound-test-support.js";
44import { cacheInboundMessageMeta } from "./quoted-message.js";
556+type MockWithCalls = {
7+mock: { calls: unknown[][] };
8+};
9+10+function sendMessageOptionsAt(
11+mock: MockWithCalls,
12+index: number,
13+expectedTo: string,
14+expectedText: string,
15+): Record<string, unknown> {
16+const call = mock.mock.calls[index];
17+expect(call?.[0]).toBe(expectedTo);
18+expect(call?.[1]).toBe(expectedText);
19+const options = call?.[2];
20+if (
21+options === undefined ||
22+options === null ||
23+typeof options !== "object" ||
24+Array.isArray(options)
25+) {
26+throw new Error(`expected send call ${index} to include options`);
27+}
28+return options as Record<string, unknown>;
29+}
30+631describe("createWhatsAppOutboundBase", () => {
732it("exposes the provided chunker", () => {
833const outbound = createWhatsAppOutboundBase({
@@ -41,18 +66,14 @@ describe("createWhatsAppOutboundBase", () => {
4166gifPlayback: false,
4267});
436844-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
45-"whatsapp:+15551234567",
46-"photo",
47-expect.objectContaining({
48-verbose: false,
49-mediaUrl: "/tmp/workspace/photo.png",
50- mediaLocalRoots,
51-accountId: "default",
52-gifPlayback: false,
53-}),
54-);
55-expect(result).toMatchObject({ channel: "whatsapp", messageId: "msg-1" });
69+const options = sendMessageOptionsAt(sendMessageWhatsApp, 0, "whatsapp:+15551234567", "photo");
70+expect(options.verbose).toBe(false);
71+expect(options.mediaUrl).toBe("/tmp/workspace/photo.png");
72+expect(options.mediaLocalRoots).toBe(mediaLocalRoots);
73+expect(options.accountId).toBe("default");
74+expect(options.gifPlayback).toBe(false);
75+expect(result.channel).toBe("whatsapp");
76+expect(result.messageId).toBe("msg-1");
5677});
57785879it("forwards audioAsVoice to sendMessageWhatsApp", async () => {
@@ -78,15 +99,10 @@ describe("createWhatsAppOutboundBase", () => {
7899deps: { sendWhatsApp: sendMessageWhatsApp },
79100});
8010181-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
82-"whatsapp:+15551234567",
83-"voice",
84-expect.objectContaining({
85-mediaUrl: "/tmp/workspace/voice.ogg",
86-audioAsVoice: true,
87-accountId: "default",
88-}),
89-);
102+const options = sendMessageOptionsAt(sendMessageWhatsApp, 0, "whatsapp:+15551234567", "voice");
103+expect(options.mediaUrl).toBe("/tmp/workspace/voice.ogg");
104+expect(options.audioAsVoice).toBe(true);
105+expect(options.accountId).toBe("default");
90106});
9110792108it("uses the configured default account for quote metadata lookup when accountId is omitted", async () => {
@@ -123,19 +139,14 @@ describe("createWhatsAppOutboundBase", () => {
123139replyToId: "reply-1",
124140});
125141126-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
127-"whatsapp:+15551234567",
128-"reply",
129-expect.objectContaining({
130-quotedMessageKey: {
131-id: "reply-1",
132-remoteJid: "15551234567@s.whatsapp.net",
133-fromMe: false,
134-participant: "111@s.whatsapp.net",
135-messageText: "quoted body",
136-},
137-}),
138-);
142+const options = sendMessageOptionsAt(sendMessageWhatsApp, 0, "whatsapp:+15551234567", "reply");
143+expect(options.quotedMessageKey).toEqual({
144+id: "reply-1",
145+remoteJid: "15551234567@s.whatsapp.net",
146+fromMe: false,
147+participant: "111@s.whatsapp.net",
148+messageText: "quoted body",
149+});
139150});
140151141152it("normalizes mixed-case defaultAccount before quote metadata lookup", async () => {
@@ -173,19 +184,14 @@ describe("createWhatsAppOutboundBase", () => {
173184replyToId: "reply-case",
174185});
175186176-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
177-"whatsapp:+15551234567",
178-"reply",
179-expect.objectContaining({
180-quotedMessageKey: {
181-id: "reply-case",
182-remoteJid: "15551234567@s.whatsapp.net",
183-fromMe: false,
184-participant: "333@s.whatsapp.net",
185-messageText: "case-normalized body",
186-},
187-}),
188-);
187+const options = sendMessageOptionsAt(sendMessageWhatsApp, 0, "whatsapp:+15551234567", "reply");
188+expect(options.quotedMessageKey).toEqual({
189+id: "reply-case",
190+remoteJid: "15551234567@s.whatsapp.net",
191+fromMe: false,
192+participant: "333@s.whatsapp.net",
193+messageText: "case-normalized body",
194+});
189195});
190196191197it("matches sorted default-account fallback for quote metadata lookup when defaultAccount is unset", async () => {
@@ -222,19 +228,14 @@ describe("createWhatsAppOutboundBase", () => {
222228replyToId: "reply-2",
223229});
224230225-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
226-"whatsapp:+15551234567",
227-"reply",
228-expect.objectContaining({
229-quotedMessageKey: {
230-id: "reply-2",
231-remoteJid: "15551234567@s.whatsapp.net",
232-fromMe: false,
233-participant: "222@s.whatsapp.net",
234-messageText: "sorted default body",
235-},
236-}),
237-);
231+const options = sendMessageOptionsAt(sendMessageWhatsApp, 0, "whatsapp:+15551234567", "reply");
232+expect(options.quotedMessageKey).toEqual({
233+id: "reply-2",
234+remoteJid: "15551234567@s.whatsapp.net",
235+fromMe: false,
236+participant: "222@s.whatsapp.net",
237+messageText: "sorted default body",
238+});
238239});
239240240241it("reuses the cached inbound remoteJid when the outbound target normalizes differently", async () => {
@@ -272,19 +273,19 @@ describe("createWhatsAppOutboundBase", () => {
272273replyToId: "reply-lid",
273274});
274275275-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
276+const options = sendMessageOptionsAt(
277+sendMessageWhatsApp,
278+0,
276279"whatsapp:+5511976136970",
277280"reply",
278-expect.objectContaining({
279-quotedMessageKey: {
280-id: "reply-lid",
281-remoteJid: "277038292303944@lid",
282-fromMe: true,
283-participant: "5511976136970@s.whatsapp.net",
284-messageText: "quoted from lid chat",
285-},
286-}),
287281);
282+expect(options.quotedMessageKey).toEqual({
283+id: "reply-lid",
284+remoteJid: "277038292303944@lid",
285+fromMe: true,
286+participant: "5511976136970@s.whatsapp.net",
287+messageText: "quoted from lid chat",
288+});
288289});
289290290291it("normalizes explicit accountId before quote metadata lookup", async () => {
@@ -321,19 +322,14 @@ describe("createWhatsAppOutboundBase", () => {
321322replyToId: "reply-explicit",
322323});
323324324-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
325-"whatsapp:+15551234567",
326-"reply",
327-expect.objectContaining({
328-quotedMessageKey: {
329-id: "reply-explicit",
330-remoteJid: "15551234567@s.whatsapp.net",
331-fromMe: false,
332-participant: "333@s.whatsapp.net",
333-messageText: "explicit account body",
334-},
335-}),
336-);
325+const options = sendMessageOptionsAt(sendMessageWhatsApp, 0, "whatsapp:+15551234567", "reply");
326+expect(options.quotedMessageKey).toEqual({
327+id: "reply-explicit",
328+remoteJid: "15551234567@s.whatsapp.net",
329+fromMe: false,
330+participant: "333@s.whatsapp.net",
331+messageText: "explicit account body",
332+});
337333});
338334339335it("falls back to the target JID when quote metadata only exists in a different conversation", async () => {
@@ -370,19 +366,19 @@ describe("createWhatsAppOutboundBase", () => {
370366replyToId: "reply-group",
371367});
372368373-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
369+const options = sendMessageOptionsAt(
370+sendMessageWhatsApp,
371+0,
374372"whatsapp:+5511976136970",
375373"reply",
376-expect.objectContaining({
377-quotedMessageKey: {
378-id: "reply-group",
379-remoteJid: "5511976136970@s.whatsapp.net",
380-fromMe: false,
381-participant: undefined,
382-messageText: undefined,
383-},
384-}),
385374);
375+expect(options.quotedMessageKey).toEqual({
376+id: "reply-group",
377+remoteJid: "5511976136970@s.whatsapp.net",
378+fromMe: false,
379+participant: undefined,
380+messageText: undefined,
381+});
386382});
387383388384it("normalizes mediaUrls before payload delivery", async () => {
@@ -410,14 +406,14 @@ describe("createWhatsAppOutboundBase", () => {
410406});
411407412408expect(sendMessageWhatsApp).toHaveBeenCalledTimes(1);
413-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
409+const options = sendMessageOptionsAt(
410+sendMessageWhatsApp,
411+0,
414412"whatsapp:+15551234567",
415413"caption",
416-expect.objectContaining({
417-verbose: false,
418-mediaUrl: "/tmp/voice.ogg",
419-}),
420414);
415+expect(options.verbose).toBe(false);
416+expect(options.mediaUrl).toBe("/tmp/voice.ogg");
421417});
422418423419it("keeps explicit mediaUrl first when payload also includes mediaUrls", async () => {
@@ -445,22 +441,15 @@ describe("createWhatsAppOutboundBase", () => {
445441deps: { sendWhatsApp: sendMessageWhatsApp },
446442});
447443448-expect(sendMessageWhatsApp).toHaveBeenNthCalledWith(
449-1,
444+const firstOptions = sendMessageOptionsAt(
445+sendMessageWhatsApp,
446+0,
450447"whatsapp:+15551234567",
451448"caption",
452-expect.objectContaining({
453-mediaUrl: "/tmp/primary.ogg",
454-}),
455-);
456-expect(sendMessageWhatsApp).toHaveBeenNthCalledWith(
457-2,
458-"whatsapp:+15551234567",
459-"",
460-expect.objectContaining({
461-mediaUrl: "/tmp/secondary.ogg",
462-}),
463449);
450+expect(firstOptions.mediaUrl).toBe("/tmp/primary.ogg");
451+const secondOptions = sendMessageOptionsAt(sendMessageWhatsApp, 1, "whatsapp:+15551234567", "");
452+expect(secondOptions.mediaUrl).toBe("/tmp/secondary.ogg");
464453});
465454466455it("uses the caller-provided text normalization for payload delivery", async () => {
@@ -487,13 +476,13 @@ describe("createWhatsAppOutboundBase", () => {
487476deps: { sendWhatsApp: sendMessageWhatsApp },
488477});
489478490-expect(sendMessageWhatsApp).toHaveBeenCalledWith(
479+const options = sendMessageOptionsAt(
480+sendMessageWhatsApp,
481+0,
491482"whatsapp:+15551234567",
492483" indented",
493-expect.objectContaining({
494-verbose: false,
495-}),
496484);
485+expect(options.verbose).toBe(false);
497486});
498487499488it("rejects structured-only payloads instead of reporting an empty successful send", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。