mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 18:14:31 +00:00
test(outbound): share resolveOutboundTarget test suite
This commit is contained in:
@@ -2,8 +2,6 @@ import fs from "node:fs";
|
|||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { telegramPlugin } from "../../../extensions/telegram/src/channel.js";
|
|
||||||
import { whatsappPlugin } from "../../../extensions/whatsapp/src/channel.js";
|
|
||||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||||
import type { OpenClawConfig } from "../../config/config.js";
|
import type { OpenClawConfig } from "../../config/config.js";
|
||||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||||
@@ -39,7 +37,7 @@ import {
|
|||||||
normalizeOutboundPayloads,
|
normalizeOutboundPayloads,
|
||||||
normalizeOutboundPayloadsForJson,
|
normalizeOutboundPayloadsForJson,
|
||||||
} from "./payloads.js";
|
} from "./payloads.js";
|
||||||
import { resolveOutboundTarget } from "./targets.js";
|
import { runResolveOutboundTargetCoreTests } from "./targets.shared-test.js";
|
||||||
|
|
||||||
describe("delivery-queue", () => {
|
describe("delivery-queue", () => {
|
||||||
let tmpDir: string;
|
let tmpDir: string;
|
||||||
@@ -914,102 +912,4 @@ describe("formatOutboundPayloadLog", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("resolveOutboundTarget", () => {
|
runResolveOutboundTargetCoreTests();
|
||||||
beforeEach(() => {
|
|
||||||
setActivePluginRegistry(
|
|
||||||
createTestRegistry([
|
|
||||||
{ pluginId: "whatsapp", plugin: whatsappPlugin, source: "test" },
|
|
||||||
{ pluginId: "telegram", plugin: telegramPlugin, source: "test" },
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
setActivePluginRegistry(createTestRegistry());
|
|
||||||
});
|
|
||||||
|
|
||||||
it.each([
|
|
||||||
{
|
|
||||||
name: "normalizes whatsapp target when provided",
|
|
||||||
input: { channel: "whatsapp" as const, to: " (555) 123-4567 " },
|
|
||||||
expected: { ok: true as const, to: "+5551234567" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "keeps whatsapp group targets",
|
|
||||||
input: { channel: "whatsapp" as const, to: "120363401234567890@g.us" },
|
|
||||||
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "normalizes prefixed/uppercase whatsapp group targets",
|
|
||||||
input: {
|
|
||||||
channel: "whatsapp" as const,
|
|
||||||
to: " WhatsApp:120363401234567890@G.US ",
|
|
||||||
},
|
|
||||||
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp with empty target in explicit mode even with cfg allowFrom",
|
|
||||||
input: {
|
|
||||||
channel: "whatsapp" as const,
|
|
||||||
to: "",
|
|
||||||
cfg: { channels: { whatsapp: { allowFrom: ["+1555"] } } } as OpenClawConfig,
|
|
||||||
mode: "explicit" as const,
|
|
||||||
},
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp with empty target and allowFrom (no silent fallback)",
|
|
||||||
input: { channel: "whatsapp" as const, to: "", allowFrom: ["+1555"] },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp with empty target and prefixed allowFrom (no silent fallback)",
|
|
||||||
input: {
|
|
||||||
channel: "whatsapp" as const,
|
|
||||||
to: "",
|
|
||||||
allowFrom: ["whatsapp:(555) 123-4567"],
|
|
||||||
},
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects invalid whatsapp target",
|
|
||||||
input: { channel: "whatsapp" as const, to: "wat" },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp without to when allowFrom missing",
|
|
||||||
input: { channel: "whatsapp" as const, to: " " },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp allowFrom fallback when invalid",
|
|
||||||
input: { channel: "whatsapp" as const, to: "", allowFrom: ["wat"] },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
])("$name", ({ input, expected, expectedErrorIncludes }) => {
|
|
||||||
const res = resolveOutboundTarget(input);
|
|
||||||
if (expected) {
|
|
||||||
expect(res).toEqual(expected);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
expect(res.ok).toBe(false);
|
|
||||||
if (!res.ok) {
|
|
||||||
expect(res.error.message).toContain(expectedErrorIncludes);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("rejects invalid non-whatsapp targets", () => {
|
|
||||||
const cases = [
|
|
||||||
{ input: { channel: "telegram" as const, to: " " }, expectedErrorIncludes: "Telegram" },
|
|
||||||
{ input: { channel: "webchat" as const, to: "x" }, expectedErrorIncludes: "WebChat" },
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
for (const testCase of cases) {
|
|
||||||
const res = resolveOutboundTarget(testCase.input);
|
|
||||||
expect(res.ok).toBe(false);
|
|
||||||
if (!res.ok) {
|
|
||||||
expect(res.error.message).toContain(testCase.expectedErrorIncludes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
119
src/infra/outbound/targets.shared-test.ts
Normal file
119
src/infra/outbound/targets.shared-test.ts
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
import { telegramPlugin } from "../../../extensions/telegram/src/channel.js";
|
||||||
|
import { whatsappPlugin } from "../../../extensions/whatsapp/src/channel.js";
|
||||||
|
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||||
|
import { createTestRegistry } from "../../test-utils/channel-plugins.js";
|
||||||
|
import { resolveOutboundTarget } from "./targets.js";
|
||||||
|
|
||||||
|
export function installResolveOutboundTargetPluginRegistryHooks(): void {
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePluginRegistry(
|
||||||
|
createTestRegistry([
|
||||||
|
{ pluginId: "whatsapp", plugin: whatsappPlugin, source: "test" },
|
||||||
|
{ pluginId: "telegram", plugin: telegramPlugin, source: "test" },
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
setActivePluginRegistry(createTestRegistry());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function runResolveOutboundTargetCoreTests(): void {
|
||||||
|
describe("resolveOutboundTarget", () => {
|
||||||
|
installResolveOutboundTargetPluginRegistryHooks();
|
||||||
|
|
||||||
|
it("rejects whatsapp with empty target even when allowFrom configured", () => {
|
||||||
|
const cfg = {
|
||||||
|
channels: { whatsapp: { allowFrom: ["+1555"] } },
|
||||||
|
};
|
||||||
|
const res = resolveOutboundTarget({
|
||||||
|
channel: "whatsapp",
|
||||||
|
to: "",
|
||||||
|
cfg,
|
||||||
|
mode: "explicit",
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(false);
|
||||||
|
if (!res.ok) {
|
||||||
|
expect(res.error.message).toContain("WhatsApp");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
{
|
||||||
|
name: "normalizes whatsapp target when provided",
|
||||||
|
input: { channel: "whatsapp" as const, to: " (555) 123-4567 " },
|
||||||
|
expected: { ok: true as const, to: "+5551234567" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "keeps whatsapp group targets",
|
||||||
|
input: { channel: "whatsapp" as const, to: "120363401234567890@g.us" },
|
||||||
|
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normalizes prefixed/uppercase whatsapp group targets",
|
||||||
|
input: {
|
||||||
|
channel: "whatsapp" as const,
|
||||||
|
to: " WhatsApp:120363401234567890@G.US ",
|
||||||
|
},
|
||||||
|
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rejects whatsapp with empty target and allowFrom (no silent fallback)",
|
||||||
|
input: { channel: "whatsapp" as const, to: "", allowFrom: ["+1555"] },
|
||||||
|
expectedErrorIncludes: "WhatsApp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rejects whatsapp with empty target and prefixed allowFrom (no silent fallback)",
|
||||||
|
input: {
|
||||||
|
channel: "whatsapp" as const,
|
||||||
|
to: "",
|
||||||
|
allowFrom: ["whatsapp:(555) 123-4567"],
|
||||||
|
},
|
||||||
|
expectedErrorIncludes: "WhatsApp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rejects invalid whatsapp target",
|
||||||
|
input: { channel: "whatsapp" as const, to: "wat" },
|
||||||
|
expectedErrorIncludes: "WhatsApp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rejects whatsapp without to when allowFrom missing",
|
||||||
|
input: { channel: "whatsapp" as const, to: " " },
|
||||||
|
expectedErrorIncludes: "WhatsApp",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rejects whatsapp allowFrom fallback when invalid",
|
||||||
|
input: { channel: "whatsapp" as const, to: "", allowFrom: ["wat"] },
|
||||||
|
expectedErrorIncludes: "WhatsApp",
|
||||||
|
},
|
||||||
|
])("$name", ({ input, expected, expectedErrorIncludes }) => {
|
||||||
|
const res = resolveOutboundTarget(input);
|
||||||
|
if (expected) {
|
||||||
|
expect(res).toEqual(expected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expect(res.ok).toBe(false);
|
||||||
|
if (!res.ok) {
|
||||||
|
expect(res.error.message).toContain(expectedErrorIncludes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects telegram with missing target", () => {
|
||||||
|
const res = resolveOutboundTarget({ channel: "telegram", to: " " });
|
||||||
|
expect(res.ok).toBe(false);
|
||||||
|
if (!res.ok) {
|
||||||
|
expect(res.error.message).toContain("Telegram");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects webchat delivery", () => {
|
||||||
|
const res = resolveOutboundTarget({ channel: "webchat", to: "x" });
|
||||||
|
expect(res.ok).toBe(false);
|
||||||
|
if (!res.ok) {
|
||||||
|
expect(res.error.message).toContain("WebChat");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,22 +1,56 @@
|
|||||||
import { beforeEach, describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { telegramPlugin } from "../../../extensions/telegram/src/channel.js";
|
|
||||||
import { whatsappPlugin } from "../../../extensions/whatsapp/src/channel.js";
|
|
||||||
import type { OpenClawConfig } from "../../config/config.js";
|
import type { OpenClawConfig } from "../../config/config.js";
|
||||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
|
||||||
import { createTestRegistry } from "../../test-utils/channel-plugins.js";
|
|
||||||
import { resolveOutboundTarget, resolveSessionDeliveryTarget } from "./targets.js";
|
import { resolveOutboundTarget, resolveSessionDeliveryTarget } from "./targets.js";
|
||||||
|
import {
|
||||||
|
installResolveOutboundTargetPluginRegistryHooks,
|
||||||
|
runResolveOutboundTargetCoreTests,
|
||||||
|
} from "./targets.shared-test.js";
|
||||||
|
|
||||||
describe("resolveOutboundTarget", () => {
|
runResolveOutboundTargetCoreTests();
|
||||||
beforeEach(() => {
|
|
||||||
setActivePluginRegistry(
|
describe("resolveOutboundTarget defaultTo config fallback", () => {
|
||||||
createTestRegistry([
|
installResolveOutboundTargetPluginRegistryHooks();
|
||||||
{ pluginId: "whatsapp", plugin: whatsappPlugin, source: "test" },
|
|
||||||
{ pluginId: "telegram", plugin: telegramPlugin, source: "test" },
|
it("uses whatsapp defaultTo when no explicit target is provided", () => {
|
||||||
]),
|
const cfg: OpenClawConfig = {
|
||||||
);
|
channels: { whatsapp: { defaultTo: "+15551234567", allowFrom: ["*"] } },
|
||||||
|
};
|
||||||
|
const res = resolveOutboundTarget({
|
||||||
|
channel: "whatsapp",
|
||||||
|
to: undefined,
|
||||||
|
cfg,
|
||||||
|
mode: "implicit",
|
||||||
|
});
|
||||||
|
expect(res).toEqual({ ok: true, to: "+15551234567" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("rejects whatsapp with empty target even when allowFrom configured", () => {
|
it("uses telegram defaultTo when no explicit target is provided", () => {
|
||||||
|
const cfg: OpenClawConfig = {
|
||||||
|
channels: { telegram: { defaultTo: "123456789" } },
|
||||||
|
};
|
||||||
|
const res = resolveOutboundTarget({
|
||||||
|
channel: "telegram",
|
||||||
|
to: "",
|
||||||
|
cfg,
|
||||||
|
mode: "implicit",
|
||||||
|
});
|
||||||
|
expect(res).toEqual({ ok: true, to: "123456789" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("explicit --reply-to overrides defaultTo", () => {
|
||||||
|
const cfg: OpenClawConfig = {
|
||||||
|
channels: { whatsapp: { defaultTo: "+15551234567", allowFrom: ["*"] } },
|
||||||
|
};
|
||||||
|
const res = resolveOutboundTarget({
|
||||||
|
channel: "whatsapp",
|
||||||
|
to: "+15559999999",
|
||||||
|
cfg,
|
||||||
|
mode: "explicit",
|
||||||
|
});
|
||||||
|
expect(res).toEqual({ ok: true, to: "+15559999999" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still errors when no defaultTo and no explicit target", () => {
|
||||||
const cfg: OpenClawConfig = {
|
const cfg: OpenClawConfig = {
|
||||||
channels: { whatsapp: { allowFrom: ["+1555"] } },
|
channels: { whatsapp: { allowFrom: ["+1555"] } },
|
||||||
};
|
};
|
||||||
@@ -24,142 +58,9 @@ describe("resolveOutboundTarget", () => {
|
|||||||
channel: "whatsapp",
|
channel: "whatsapp",
|
||||||
to: "",
|
to: "",
|
||||||
cfg,
|
cfg,
|
||||||
mode: "explicit",
|
mode: "implicit",
|
||||||
});
|
});
|
||||||
expect(res.ok).toBe(false);
|
expect(res.ok).toBe(false);
|
||||||
if (!res.ok) {
|
|
||||||
expect(res.error.message).toContain("WhatsApp");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.each([
|
|
||||||
{
|
|
||||||
name: "normalizes whatsapp target when provided",
|
|
||||||
input: { channel: "whatsapp" as const, to: " (555) 123-4567 " },
|
|
||||||
expected: { ok: true as const, to: "+5551234567" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "keeps whatsapp group targets",
|
|
||||||
input: { channel: "whatsapp" as const, to: "120363401234567890@g.us" },
|
|
||||||
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "normalizes prefixed/uppercase whatsapp group targets",
|
|
||||||
input: {
|
|
||||||
channel: "whatsapp" as const,
|
|
||||||
to: " WhatsApp:120363401234567890@G.US ",
|
|
||||||
},
|
|
||||||
expected: { ok: true as const, to: "120363401234567890@g.us" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp with empty target and allowFrom (no silent fallback)",
|
|
||||||
input: { channel: "whatsapp" as const, to: "", allowFrom: ["+1555"] },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp with empty target and prefixed allowFrom (no silent fallback)",
|
|
||||||
input: {
|
|
||||||
channel: "whatsapp" as const,
|
|
||||||
to: "",
|
|
||||||
allowFrom: ["whatsapp:(555) 123-4567"],
|
|
||||||
},
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects invalid whatsapp target",
|
|
||||||
input: { channel: "whatsapp" as const, to: "wat" },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp without to when allowFrom missing",
|
|
||||||
input: { channel: "whatsapp" as const, to: " " },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "rejects whatsapp allowFrom fallback when invalid",
|
|
||||||
input: { channel: "whatsapp" as const, to: "", allowFrom: ["wat"] },
|
|
||||||
expectedErrorIncludes: "WhatsApp",
|
|
||||||
},
|
|
||||||
])("$name", ({ input, expected, expectedErrorIncludes }) => {
|
|
||||||
const res = resolveOutboundTarget(input);
|
|
||||||
if (expected) {
|
|
||||||
expect(res).toEqual(expected);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
expect(res.ok).toBe(false);
|
|
||||||
if (!res.ok) {
|
|
||||||
expect(res.error.message).toContain(expectedErrorIncludes);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("rejects telegram with missing target", () => {
|
|
||||||
const res = resolveOutboundTarget({ channel: "telegram", to: " " });
|
|
||||||
expect(res.ok).toBe(false);
|
|
||||||
if (!res.ok) {
|
|
||||||
expect(res.error.message).toContain("Telegram");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("rejects webchat delivery", () => {
|
|
||||||
const res = resolveOutboundTarget({ channel: "webchat", to: "x" });
|
|
||||||
expect(res.ok).toBe(false);
|
|
||||||
if (!res.ok) {
|
|
||||||
expect(res.error.message).toContain("WebChat");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("defaultTo config fallback", () => {
|
|
||||||
it("uses whatsapp defaultTo when no explicit target is provided", () => {
|
|
||||||
const cfg: OpenClawConfig = {
|
|
||||||
channels: { whatsapp: { defaultTo: "+15551234567", allowFrom: ["*"] } },
|
|
||||||
};
|
|
||||||
const res = resolveOutboundTarget({
|
|
||||||
channel: "whatsapp",
|
|
||||||
to: undefined,
|
|
||||||
cfg,
|
|
||||||
mode: "implicit",
|
|
||||||
});
|
|
||||||
expect(res).toEqual({ ok: true, to: "+15551234567" });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("uses telegram defaultTo when no explicit target is provided", () => {
|
|
||||||
const cfg: OpenClawConfig = {
|
|
||||||
channels: { telegram: { defaultTo: "123456789" } },
|
|
||||||
};
|
|
||||||
const res = resolveOutboundTarget({
|
|
||||||
channel: "telegram",
|
|
||||||
to: "",
|
|
||||||
cfg,
|
|
||||||
mode: "implicit",
|
|
||||||
});
|
|
||||||
expect(res).toEqual({ ok: true, to: "123456789" });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("explicit --reply-to overrides defaultTo", () => {
|
|
||||||
const cfg: OpenClawConfig = {
|
|
||||||
channels: { whatsapp: { defaultTo: "+15551234567", allowFrom: ["*"] } },
|
|
||||||
};
|
|
||||||
const res = resolveOutboundTarget({
|
|
||||||
channel: "whatsapp",
|
|
||||||
to: "+15559999999",
|
|
||||||
cfg,
|
|
||||||
mode: "explicit",
|
|
||||||
});
|
|
||||||
expect(res).toEqual({ ok: true, to: "+15559999999" });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("still errors when no defaultTo and no explicit target", () => {
|
|
||||||
const cfg: OpenClawConfig = {
|
|
||||||
channels: { whatsapp: { allowFrom: ["+1555"] } },
|
|
||||||
};
|
|
||||||
const res = resolveOutboundTarget({
|
|
||||||
channel: "whatsapp",
|
|
||||||
to: "",
|
|
||||||
cfg,
|
|
||||||
mode: "implicit",
|
|
||||||
});
|
|
||||||
expect(res.ok).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user