import { describe, expect, it, vi } from "vitest"; vi.mock("openclaw/plugin-sdk", () => ({ getChatChannelMeta: () => ({ id: "whatsapp", label: "WhatsApp" }), normalizeWhatsAppTarget: (value: string) => { if (value === "invalid-target") return null; // Simulate E.164 normalization: strip leading + and whatsapp: prefix const stripped = value.replace(/^whatsapp:/i, "").replace(/^\+/, ""); return stripped.includes("@g.us") ? stripped : `${stripped}@s.whatsapp.net`; }, isWhatsAppGroupJid: (value: string) => value.endsWith("@g.us"), missingTargetError: (provider: string, hint: string) => new Error(`Delivering to ${provider} requires target ${hint}`), WhatsAppConfigSchema: {}, whatsappOnboardingAdapter: {}, resolveWhatsAppHeartbeatRecipients: vi.fn(), buildChannelConfigSchema: vi.fn(), collectWhatsAppStatusIssues: vi.fn(), createActionGate: vi.fn(), DEFAULT_ACCOUNT_ID: "default", escapeRegExp: vi.fn(), formatPairingApproveHint: vi.fn(), listWhatsAppAccountIds: vi.fn(), listWhatsAppDirectoryGroupsFromConfig: vi.fn(), listWhatsAppDirectoryPeersFromConfig: vi.fn(), looksLikeWhatsAppTargetId: vi.fn(), migrateBaseNameToDefaultAccount: vi.fn(), normalizeAccountId: vi.fn(), normalizeE164: vi.fn(), normalizeWhatsAppMessagingTarget: vi.fn(), readStringParam: vi.fn(), resolveDefaultWhatsAppAccountId: vi.fn(), resolveWhatsAppAccount: vi.fn(), resolveWhatsAppGroupRequireMention: vi.fn(), resolveWhatsAppGroupToolPolicy: vi.fn(), applyAccountNameToChannelSection: vi.fn(), })); vi.mock("./runtime.js", () => ({ getWhatsAppRuntime: vi.fn(() => ({ channel: { text: { chunkText: vi.fn() }, whatsapp: { sendMessageWhatsApp: vi.fn(), createLoginTool: vi.fn(), }, }, })), })); import { whatsappPlugin } from "./channel.js"; const resolveTarget = whatsappPlugin.outbound!.resolveTarget!; describe("whatsapp resolveTarget", () => { it("should resolve valid target in explicit mode", () => { const result = resolveTarget({ to: "5511999999999", mode: "explicit", allowFrom: [], }); expect(result.ok).toBe(true); expect(result.to).toBe("5511999999999@s.whatsapp.net"); }); it("should resolve target in implicit mode with wildcard", () => { const result = resolveTarget({ to: "5511999999999", mode: "implicit", allowFrom: ["*"], }); expect(result.ok).toBe(true); expect(result.to).toBe("5511999999999@s.whatsapp.net"); }); it("should resolve target in implicit mode when in allowlist", () => { const result = resolveTarget({ to: "5511999999999", mode: "implicit", allowFrom: ["5511999999999"], }); expect(result.ok).toBe(true); expect(result.to).toBe("5511999999999@s.whatsapp.net"); }); it("should allow group JID regardless of allowlist", () => { const result = resolveTarget({ to: "120363123456789@g.us", mode: "implicit", allowFrom: ["5511999999999"], }); expect(result.ok).toBe(true); expect(result.to).toBe("120363123456789@g.us"); }); it("should error when target not in allowlist (implicit mode)", () => { const result = resolveTarget({ to: "5511888888888", mode: "implicit", allowFrom: ["5511999999999", "5511777777777"], }); expect(result.ok).toBe(false); expect(result.error).toBeDefined(); }); it("should error on normalization failure with allowlist (implicit mode)", () => { const result = resolveTarget({ to: "invalid-target", mode: "implicit", allowFrom: ["5511999999999"], }); expect(result.ok).toBe(false); expect(result.error).toBeDefined(); }); it("should error when no target provided with allowlist", () => { const result = resolveTarget({ to: undefined, mode: "implicit", allowFrom: ["5511999999999"], }); expect(result.ok).toBe(false); expect(result.error).toBeDefined(); }); it("should error when no target and no allowlist", () => { const result = resolveTarget({ to: undefined, mode: "explicit", allowFrom: [], }); expect(result.ok).toBe(false); expect(result.error).toBeDefined(); }); it("should handle whitespace-only target", () => { const result = resolveTarget({ to: " ", mode: "explicit", allowFrom: [], }); expect(result.ok).toBe(false); expect(result.error).toBeDefined(); }); });