mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-25 03:04:29 -04:00
test: dedupe line and whatsapp target resolution tests
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import crypto from "node:crypto";
|
||||
import type { WebhookRequestBody } from "@line/bot-sdk";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createLineWebhookMiddleware } from "./webhook.js";
|
||||
|
||||
@@ -17,126 +18,97 @@ const createRes = () => {
|
||||
return res;
|
||||
};
|
||||
|
||||
describe("createLineWebhookMiddleware", () => {
|
||||
it("parses JSON from raw string body", async () => {
|
||||
const onEvents = vi.fn(async () => {});
|
||||
const secret = "secret";
|
||||
const rawBody = JSON.stringify({ events: [{ type: "message" }] });
|
||||
const middleware = createLineWebhookMiddleware({ channelSecret: secret, onEvents });
|
||||
const SECRET = "secret";
|
||||
|
||||
const req = {
|
||||
headers: { "x-line-signature": sign(rawBody, secret) },
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(200);
|
||||
expect(onEvents).toHaveBeenCalledWith(expect.objectContaining({ events: expect.any(Array) }));
|
||||
async function invokeWebhook(params: {
|
||||
body: unknown;
|
||||
headers?: Record<string, string>;
|
||||
onEvents?: ReturnType<typeof vi.fn>;
|
||||
autoSign?: boolean;
|
||||
}) {
|
||||
const onEventsMock = params.onEvents ?? vi.fn(async () => {});
|
||||
const middleware = createLineWebhookMiddleware({
|
||||
channelSecret: SECRET,
|
||||
onEvents: onEventsMock as unknown as (body: WebhookRequestBody) => Promise<void>,
|
||||
});
|
||||
|
||||
it("parses JSON from raw buffer body", async () => {
|
||||
const onEvents = vi.fn(async () => {});
|
||||
const secret = "secret";
|
||||
const rawBody = JSON.stringify({ events: [{ type: "follow" }] });
|
||||
const middleware = createLineWebhookMiddleware({ channelSecret: secret, onEvents });
|
||||
|
||||
const req = {
|
||||
headers: { "x-line-signature": sign(rawBody, secret) },
|
||||
body: Buffer.from(rawBody, "utf-8"),
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
const headers = { ...params.headers };
|
||||
const autoSign = params.autoSign ?? true;
|
||||
if (autoSign && !headers["x-line-signature"]) {
|
||||
if (typeof params.body === "string") {
|
||||
headers["x-line-signature"] = sign(params.body, SECRET);
|
||||
} else if (Buffer.isBuffer(params.body)) {
|
||||
headers["x-line-signature"] = sign(params.body.toString("utf-8"), SECRET);
|
||||
}
|
||||
}
|
||||
|
||||
const req = {
|
||||
headers,
|
||||
body: params.body,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
} as any;
|
||||
const res = createRes();
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
return { res, onEvents: onEventsMock };
|
||||
}
|
||||
|
||||
describe("createLineWebhookMiddleware", () => {
|
||||
it.each([
|
||||
["raw string body", JSON.stringify({ events: [{ type: "message" }] })],
|
||||
["raw buffer body", Buffer.from(JSON.stringify({ events: [{ type: "follow" }] }), "utf-8")],
|
||||
])("parses JSON from %s", async (_label, body) => {
|
||||
const { res, onEvents } = await invokeWebhook({ body });
|
||||
expect(res.status).toHaveBeenCalledWith(200);
|
||||
expect(onEvents).toHaveBeenCalledWith(expect.objectContaining({ events: expect.any(Array) }));
|
||||
});
|
||||
|
||||
it("rejects invalid JSON payloads", async () => {
|
||||
const onEvents = vi.fn(async () => {});
|
||||
const secret = "secret";
|
||||
const rawBody = "not json";
|
||||
const middleware = createLineWebhookMiddleware({ channelSecret: secret, onEvents });
|
||||
|
||||
const req = {
|
||||
headers: { "x-line-signature": sign(rawBody, secret) },
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
const { res, onEvents } = await invokeWebhook({ body: "not json" });
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(onEvents).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects webhooks with invalid signatures", async () => {
|
||||
const onEvents = vi.fn(async () => {});
|
||||
const secret = "secret";
|
||||
const rawBody = JSON.stringify({ events: [{ type: "message" }] });
|
||||
const middleware = createLineWebhookMiddleware({ channelSecret: secret, onEvents });
|
||||
|
||||
const req = {
|
||||
const { res, onEvents } = await invokeWebhook({
|
||||
body: JSON.stringify({ events: [{ type: "message" }] }),
|
||||
headers: { "x-line-signature": "invalid-signature" },
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
});
|
||||
expect(res.status).toHaveBeenCalledWith(401);
|
||||
expect(onEvents).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns 200 for verification request (empty events, no signature)", async () => {
|
||||
const onEvents = vi.fn(async () => {});
|
||||
const secret = "secret";
|
||||
const rawBody = JSON.stringify({ events: [] });
|
||||
const middleware = createLineWebhookMiddleware({ channelSecret: secret, onEvents });
|
||||
|
||||
const req = {
|
||||
const { res, onEvents } = await invokeWebhook({
|
||||
body: JSON.stringify({ events: [] }),
|
||||
headers: {},
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
autoSign: false,
|
||||
});
|
||||
expect(res.status).toHaveBeenCalledWith(200);
|
||||
expect(res.json).toHaveBeenCalledWith({ status: "ok" });
|
||||
expect(onEvents).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects missing signature when events are non-empty", async () => {
|
||||
const onEvents = vi.fn(async () => {});
|
||||
const secret = "secret";
|
||||
const rawBody = JSON.stringify({ events: [{ type: "message" }] });
|
||||
const middleware = createLineWebhookMiddleware({ channelSecret: secret, onEvents });
|
||||
|
||||
const req = {
|
||||
const { res, onEvents } = await invokeWebhook({
|
||||
body: JSON.stringify({ events: [{ type: "message" }] }),
|
||||
headers: {},
|
||||
body: rawBody,
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
} as any;
|
||||
const res = createRes();
|
||||
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
await middleware(req, res, {} as any);
|
||||
|
||||
autoSign: false,
|
||||
});
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.json).toHaveBeenCalledWith({ error: "Missing X-Line-Signature header" });
|
||||
expect(onEvents).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects signed requests when raw body is missing", async () => {
|
||||
const { res, onEvents } = await invokeWebhook({
|
||||
body: { events: [{ type: "message" }] },
|
||||
headers: { "x-line-signature": "signed" },
|
||||
});
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.json).toHaveBeenCalledWith({
|
||||
error: "Missing raw request body for signature verification",
|
||||
});
|
||||
expect(onEvents).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,73 +7,46 @@ vi.mock("../infra/outbound/target-errors.js", () => ({
|
||||
missingTargetError: (platform: string, format: string) => new Error(`${platform}: ${format}`),
|
||||
}));
|
||||
|
||||
type ResolveParams = Parameters<typeof resolveWhatsAppOutboundTarget>[0];
|
||||
|
||||
function expectResolutionError(params: ResolveParams) {
|
||||
const result = resolveWhatsAppOutboundTarget(params);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) {
|
||||
throw new Error("expected resolution to fail");
|
||||
}
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
|
||||
function expectResolutionOk(params: ResolveParams, expectedTarget: string) {
|
||||
const result = resolveWhatsAppOutboundTarget(params);
|
||||
expect(result).toEqual({ ok: true, to: expectedTarget });
|
||||
}
|
||||
|
||||
describe("resolveWhatsAppOutboundTarget", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
describe("empty/missing to parameter", () => {
|
||||
it("returns error when to is null", () => {
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: null,
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
});
|
||||
|
||||
it("returns error when to is undefined", () => {
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: undefined,
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
});
|
||||
|
||||
it("returns error when to is empty string", () => {
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "",
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
});
|
||||
|
||||
it("returns error when to is whitespace only", () => {
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: " ",
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
it.each([
|
||||
["null", null],
|
||||
["undefined", undefined],
|
||||
["empty string", ""],
|
||||
["whitespace only", " "],
|
||||
])("returns error when to is %s", (_label, to) => {
|
||||
expectResolutionError({ to, allowFrom: undefined, mode: undefined });
|
||||
});
|
||||
});
|
||||
|
||||
describe("normalization failures", () => {
|
||||
it("returns error when normalizeWhatsAppTarget returns null/undefined", () => {
|
||||
vi.mocked(normalize.normalizeWhatsAppTarget).mockReturnValueOnce(null);
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
expectResolutionError({
|
||||
to: "+1234567890",
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -82,30 +55,28 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
vi.mocked(normalize.normalizeWhatsAppTarget).mockReturnValueOnce("120363123456789@g.us");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(true);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "120363123456789@g.us",
|
||||
allowFrom: undefined,
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("120363123456789@g.us");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "120363123456789@g.us",
|
||||
allowFrom: undefined,
|
||||
mode: "implicit",
|
||||
},
|
||||
"120363123456789@g.us",
|
||||
);
|
||||
});
|
||||
|
||||
it("returns success for group JID in heartbeat mode", () => {
|
||||
vi.mocked(normalize.normalizeWhatsAppTarget).mockReturnValueOnce("120363999888777@g.us");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(true);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "120363999888777@g.us",
|
||||
allowFrom: undefined,
|
||||
mode: "heartbeat",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("120363999888777@g.us");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "120363999888777@g.us",
|
||||
allowFrom: undefined,
|
||||
mode: "heartbeat",
|
||||
},
|
||||
"120363999888777@g.us",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -116,15 +87,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+11234567890");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: ["*"],
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: ["*"],
|
||||
mode: "implicit",
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
|
||||
it("allows message when allowList is empty", () => {
|
||||
@@ -133,15 +103,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+11234567890");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: [],
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: [],
|
||||
mode: "implicit",
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
|
||||
it("allows message when target is in allowList", () => {
|
||||
@@ -150,15 +119,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+11234567890");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+11234567890"],
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+11234567890"],
|
||||
mode: "implicit",
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
|
||||
it("denies message when target is not in allowList", () => {
|
||||
@@ -167,15 +135,11 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+19876543210");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
expectResolutionError({
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+19876543210"],
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
});
|
||||
|
||||
it("handles mixed numeric and string allowList entries", () => {
|
||||
@@ -185,15 +149,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+11234567890"); // for allowFrom[1]
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: [1234567890, "+11234567890"],
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: [1234567890, "+11234567890"],
|
||||
mode: "implicit",
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
|
||||
it("filters out invalid normalized entries from allowList", () => {
|
||||
@@ -203,15 +166,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+11234567890"); // for 'to' param (processed last)
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: ["invalid", "+11234567890"],
|
||||
mode: "implicit",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: ["invalid", "+11234567890"],
|
||||
mode: "implicit",
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -222,15 +184,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+11234567890");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+11234567890"],
|
||||
mode: "heartbeat",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+11234567890"],
|
||||
mode: "heartbeat",
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
|
||||
it("denies message when target is not in allowList in heartbeat mode", () => {
|
||||
@@ -239,15 +200,11 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+19876543210");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
expectResolutionError({
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+19876543210"],
|
||||
mode: "heartbeat",
|
||||
});
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(result.error.message).toContain("WhatsApp");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -256,30 +213,28 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
vi.mocked(normalize.normalizeWhatsAppTarget).mockReturnValueOnce("+11234567890");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: undefined,
|
||||
mode: null,
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: undefined,
|
||||
mode: null,
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
|
||||
it("allows message in undefined mode", () => {
|
||||
vi.mocked(normalize.normalizeWhatsAppTarget).mockReturnValueOnce("+11234567890");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
|
||||
it("allows message in custom mode string", () => {
|
||||
@@ -288,15 +243,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
.mockReturnValueOnce("+11234567890"); // for 'to' param (happens second)
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+19876543210"],
|
||||
mode: "broadcast",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.to).toBe("+11234567890");
|
||||
}
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: "+11234567890",
|
||||
allowFrom: ["+19876543210"],
|
||||
mode: "broadcast",
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -305,12 +259,14 @@ describe("resolveWhatsAppOutboundTarget", () => {
|
||||
vi.mocked(normalize.normalizeWhatsAppTarget).mockReturnValueOnce("+11234567890");
|
||||
vi.mocked(normalize.isWhatsAppGroupJid).mockReturnValueOnce(false);
|
||||
|
||||
const result = resolveWhatsAppOutboundTarget({
|
||||
to: " +11234567890 ",
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
expectResolutionOk(
|
||||
{
|
||||
to: " +11234567890 ",
|
||||
allowFrom: undefined,
|
||||
mode: undefined,
|
||||
},
|
||||
"+11234567890",
|
||||
);
|
||||
expect(vi.mocked(normalize.normalizeWhatsAppTarget)).toHaveBeenCalledWith("+11234567890");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user