






























@@ -42,18 +42,50 @@ describe("createWebSendApi", () => {
4242});
4343});
444445+function requireRecord(value: unknown, label: string): Record<string, unknown> {
46+expect(typeof value).toBe("object");
47+expect(value).not.toBeNull();
48+if (typeof value !== "object" || value === null) {
49+throw new Error(`${label} was not an object`);
50+}
51+return value as Record<string, unknown>;
52+}
53+54+function expectRecordFields(record: Record<string, unknown>, fields: Record<string, unknown>) {
55+for (const [key, value] of Object.entries(fields)) {
56+expect(record[key]).toEqual(value);
57+}
58+}
59+60+function requireSendContent(callIndex = 0): Record<string, unknown> {
61+return requireRecord(sendMessage.mock.calls[callIndex]?.[1], "sent message content");
62+}
63+64+function requireSendOptions(callIndex = 0): Record<string, unknown> {
65+return requireRecord(sendMessage.mock.calls[callIndex]?.[2], "sent message options");
66+}
67+68+function expectSendContentFields(callIndex: number, fields: Record<string, unknown>) {
69+expectRecordFields(requireSendContent(callIndex), fields);
70+}
71+72+function expectSendResultFields(
73+result: Awaited<ReturnType<typeof api.sendMessage | typeof api.sendReaction>>,
74+fields: Record<string, unknown>,
75+) {
76+expectRecordFields(requireRecord(result, "send result"), fields);
77+}
78+4579it("uses sendOptions fileName for outbound documents", async () => {
4680const payload = Buffer.from("pdf");
4781await api.sendMessage("+1555", "doc", payload, "application/pdf", { fileName: "invoice.pdf" });
48-expect(sendMessage).toHaveBeenCalledWith(
49-"1555@s.whatsapp.net",
50-expect.objectContaining({
51-document: payload,
52-fileName: "invoice.pdf",
53-caption: "doc",
54-mimetype: "application/pdf",
55-}),
56-);
82+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
83+expectSendContentFields(0, {
84+document: payload,
85+fileName: "invoice.pdf",
86+caption: "doc",
87+mimetype: "application/pdf",
88+});
5789expect(recordChannelActivity).toHaveBeenCalledWith({
5890channel: "whatsapp",
5991accountId: "main",
@@ -64,21 +96,19 @@ describe("createWebSendApi", () => {
6496it("falls back to default document filename when fileName is absent", async () => {
6597const payload = Buffer.from("pdf");
6698await api.sendMessage("+1555", "doc", payload, "application/pdf");
67-expect(sendMessage).toHaveBeenCalledWith(
68-"1555@s.whatsapp.net",
69-expect.objectContaining({
70-document: payload,
71-fileName: "file",
72-caption: "doc",
73-mimetype: "application/pdf",
74-}),
75-);
99+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
100+expectSendContentFields(0, {
101+document: payload,
102+fileName: "file",
103+caption: "doc",
104+mimetype: "application/pdf",
105+});
76106});
7710778108it("sends plain text messages", async () => {
79109const res = await api.sendMessage("+1555", "hello");
80110expect(sendMessage).toHaveBeenCalledWith("1555@s.whatsapp.net", { text: "hello" });
81-expect(res).toMatchObject({
111+expectSendResultFields(res, {
82112kind: "text",
83113messageId: "msg-1",
84114providerAccepted: true,
@@ -119,14 +149,12 @@ describe("createWebSendApi", () => {
119149it("supports image media with caption", async () => {
120150const payload = Buffer.from("img");
121151await api.sendMessage("+1555", "cap", payload, "image/jpeg");
122-expect(sendMessage).toHaveBeenCalledWith(
123-"1555@s.whatsapp.net",
124-expect.objectContaining({
125-image: payload,
126-caption: "cap",
127-mimetype: "image/jpeg",
128-}),
129-);
152+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
153+expectSendContentFields(0, {
154+image: payload,
155+caption: "cap",
156+mimetype: "image/jpeg",
157+});
130158});
131159132160it("adds native mention metadata to group media captions", async () => {
@@ -144,28 +172,24 @@ describe("createWebSendApi", () => {
144172145173await api.sendMessage("120363000000000000@g.us", "cap @15551234567", payload, "image/jpeg");
146174147-expect(sendMessage).toHaveBeenCalledWith(
148-"120363000000000000@g.us",
149-expect.objectContaining({
150-image: payload,
151-caption: "cap @15551234567",
152-mimetype: "image/jpeg",
153-mentions: ["15551234567@s.whatsapp.net"],
154-}),
155-);
175+expect(sendMessage.mock.calls[0]?.[0]).toBe("120363000000000000@g.us");
176+expectSendContentFields(0, {
177+image: payload,
178+caption: "cap @15551234567",
179+mimetype: "image/jpeg",
180+mentions: ["15551234567@s.whatsapp.net"],
181+});
156182});
157183158184it("supports audio as push-to-talk voice note", async () => {
159185const payload = Buffer.from("aud");
160186await api.sendMessage("+1555", "", payload, "audio/ogg", { accountId: "alt" });
161-expect(sendMessage).toHaveBeenCalledWith(
162-"1555@s.whatsapp.net",
163-expect.objectContaining({
164-audio: payload,
165-ptt: true,
166-mimetype: "audio/ogg",
167-}),
168-);
187+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
188+expectSendContentFields(0, {
189+audio: payload,
190+ptt: true,
191+mimetype: "audio/ogg",
192+});
169193expect(recordChannelActivity).toHaveBeenCalledWith({
170194channel: "whatsapp",
171195accountId: "alt",
@@ -179,19 +203,16 @@ describe("createWebSendApi", () => {
179203.mockResolvedValueOnce({ key: { id: "voice-1" } })
180204.mockResolvedValueOnce({ key: { id: "voice-text-1" } });
181205const res = await api.sendMessage("+1555", "voice text", payload, "audio/ogg");
182-expect(sendMessage).toHaveBeenNthCalledWith(
183-1,
184-"1555@s.whatsapp.net",
185-expect.objectContaining({
186-audio: payload,
187-ptt: true,
188-mimetype: "audio/ogg",
189-}),
190-);
206+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
207+expectSendContentFields(0, {
208+audio: payload,
209+ptt: true,
210+mimetype: "audio/ogg",
211+});
191212expect(sendMessage).toHaveBeenNthCalledWith(2, "1555@s.whatsapp.net", {
192213text: "voice text",
193214});
194-expect(res).toMatchObject({
215+expectSendResultFields(res, {
195216kind: "media",
196217messageId: "voice-1",
197218providerAccepted: true,
@@ -205,15 +226,13 @@ describe("createWebSendApi", () => {
205226it("supports video media and gifPlayback option", async () => {
206227const payload = Buffer.from("vid");
207228await api.sendMessage("+1555", "cap", payload, "video/mp4", { gifPlayback: true });
208-expect(sendMessage).toHaveBeenCalledWith(
209-"1555@s.whatsapp.net",
210-expect.objectContaining({
211-video: payload,
212-caption: "cap",
213-mimetype: "video/mp4",
214-gifPlayback: true,
215-}),
216-);
229+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
230+expectSendContentFields(0, {
231+video: payload,
232+caption: "cap",
233+mimetype: "video/mp4",
234+gifPlayback: true,
235+});
217236});
218237219238it("falls back to unknown messageId if Baileys result does not expose key.id", async () => {
@@ -228,12 +247,12 @@ describe("createWebSendApi", () => {
228247options: ["a", "b"],
229248maxSelections: 2,
230249});
231-expect(sendMessage).toHaveBeenCalledWith(
232- "1555@s.whatsapp.net",
233-expect.objectContaining({
234- poll: { name: "Q?", values: ["a", "b"], selectableCount: 2 },
235-}),
236-);
250+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
251+expect(requireSendContent().poll).toEqual({
252+name: "Q?",
253+values: ["a", "b"],
254+selectableCount: 2,
255+});
237256expect(res.messageId).toBe("msg-1");
238257expect(recordChannelActivity).toHaveBeenCalledWith({
239258channel: "whatsapp",
@@ -244,21 +263,16 @@ describe("createWebSendApi", () => {
244263245264it("sends reactions with participant JID normalization", async () => {
246265const res = await api.sendReaction("+1555", "msg-2", "👍", false, "+1999");
247-expect(sendMessage).toHaveBeenCalledWith(
248-"1555@s.whatsapp.net",
249-expect.objectContaining({
250-react: {
251-text: "👍",
252-key: expect.objectContaining({
253-remoteJid: "1555@s.whatsapp.net",
254-id: "msg-2",
255-fromMe: false,
256-participant: "1999@s.whatsapp.net",
257-}),
258-},
259-}),
260-);
261-expect(res).toMatchObject({
266+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
267+const react = requireRecord(requireSendContent().react, "reaction content");
268+expect(react.text).toBe("👍");
269+expectRecordFields(requireRecord(react.key, "reaction key"), {
270+remoteJid: "1555@s.whatsapp.net",
271+id: "msg-2",
272+fromMe: false,
273+participant: "1999@s.whatsapp.net",
274+});
275+expectSendResultFields(res, {
262276kind: "reaction",
263277messageId: "msg-1",
264278providerAccepted: true,
@@ -270,7 +284,7 @@ describe("createWebSendApi", () => {
270284271285const res = await api.sendMessage("+1555", "hello");
272286273-expect(res).toMatchObject({
287+expectSendResultFields(res, {
274288kind: "text",
275289messageId: "unknown",
276290providerAccepted: false,
@@ -280,38 +294,28 @@ describe("createWebSendApi", () => {
280294281295it("keeps direct-chat reactions without a participant key", async () => {
282296await api.sendReaction("+1555", "msg-2", "👍", false);
283-expect(sendMessage).toHaveBeenCalledWith(
284-"1555@s.whatsapp.net",
285-expect.objectContaining({
286-react: {
287-text: "👍",
288-key: expect.objectContaining({
289-remoteJid: "1555@s.whatsapp.net",
290-id: "msg-2",
291-fromMe: false,
292-participant: undefined,
293-}),
294-},
295-}),
296-);
297+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
298+const react = requireRecord(requireSendContent().react, "reaction content");
299+expect(react.text).toBe("👍");
300+expectRecordFields(requireRecord(react.key, "reaction key"), {
301+remoteJid: "1555@s.whatsapp.net",
302+id: "msg-2",
303+fromMe: false,
304+participant: undefined,
305+});
297306});
298307299308it("preserves LID participants in reaction keys", async () => {
300309await api.sendReaction("12345@g.us", "msg-2", "👍", false, "123@lid");
301-expect(sendMessage).toHaveBeenCalledWith(
302-"12345@g.us",
303-expect.objectContaining({
304-react: {
305-text: "👍",
306-key: expect.objectContaining({
307-remoteJid: "12345@g.us",
308-id: "msg-2",
309-fromMe: false,
310-participant: "123@lid",
311-}),
312-},
313-}),
314-);
310+expect(sendMessage.mock.calls[0]?.[0]).toBe("12345@g.us");
311+const react = requireRecord(requireSendContent().react, "reaction content");
312+expect(react.text).toBe("👍");
313+expectRecordFields(requireRecord(react.key, "reaction key"), {
314+remoteJid: "12345@g.us",
315+id: "msg-2",
316+fromMe: false,
317+participant: "123@lid",
318+});
315319});
316320317321it("sends composing presence updates to the recipient JID", async () => {
@@ -336,13 +340,11 @@ describe("createWebSendApi", () => {
336340337341await api.sendMessage("123", "hello", mediaBuffer, undefined);
338342339-expect(sendMessage).toHaveBeenCalledWith(
340-"123@s.whatsapp.net",
341-expect.objectContaining({
342-document: mediaBuffer,
343-mimetype: "application/octet-stream",
344-}),
345-);
343+expect(sendMessage.mock.calls[0]?.[0]).toBe("123@s.whatsapp.net");
344+expectSendContentFields(0, {
345+document: mediaBuffer,
346+mimetype: "application/octet-stream",
347+});
346348});
347349348350it("does not set mediaType when mediaBuffer is absent", async () => {
@@ -362,18 +364,13 @@ describe("createWebSendApi", () => {
362364},
363365});
364366365-expect(sendMessage).toHaveBeenCalledWith(
366-"1555@s.whatsapp.net",
367-{ text: "hello" },
368-expect.objectContaining({
369-quoted: expect.objectContaining({
370-key: expect.objectContaining({
371-remoteJid: "277038292303944@lid",
372-id: "quoted-1",
373-}),
374-}),
375-}),
376-);
367+expect(sendMessage.mock.calls[0]?.[0]).toBe("1555@s.whatsapp.net");
368+expect(sendMessage.mock.calls[0]?.[1]).toEqual({ text: "hello" });
369+const quoted = requireRecord(requireSendOptions().quoted, "quoted message");
370+expectRecordFields(requireRecord(quoted.key, "quoted key"), {
371+remoteJid: "277038292303944@lid",
372+id: "quoted-1",
373+});
377374});
378375});
379376@@ -382,7 +379,13 @@ describe("createWebSendApi", () => {
382379// otherwise messages going to LID-addressed contacts vanish into a
383380// sender-only ghost chat.
384381describe("createWebSendApi LID resolution (issue #67378)", () => {
385-const sendMessage = vi.fn(async () => ({ key: { id: "msg-1" } }));
382+const sendMessage = vi.fn(
383+async (
384+_jid: string,
385+_content: AnyMessageContent,
386+_options?: MiscMessageGenerationOptions,
387+): Promise<WAMessage | undefined> => ({ key: { id: "msg-1" } }) as WAMessage,
388+);
386389const sendPresenceUpdate = vi.fn(async () => {});
387390let authDir: string;
388391@@ -423,10 +426,10 @@ describe("createWebSendApi LID resolution (issue #67378)", () => {
423426 authDir,
424427});
425428await api.sendPoll("+15555550000", { question: "Q?", options: ["a", "b"] });
426-expect(sendMessage).toHaveBeenCalledWith(
427- "987654@lid",
428- expect.objectContaining({ poll: expect.any(Object) }),
429-);
429+expect(sendMessage.mock.calls[0]?.[0]).toBe("987654@lid");
430+expect(typeof sendMessage.mock.calls[0]?.[1]).toBe("object");
431+expect(sendMessage.mock.calls[0]?.[1]).not.toBeNull();
432+expect("poll" in (sendMessage.mock.calls[0]?.[1] as Record<string, unknown>)).toBe(true);
430433});
431434432435it("resolves PN to LID for sendComposingTo presence", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。