mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:30:43 +00:00
test: use synthetic outbound utility fixtures
This commit is contained in:
@@ -1,21 +1,28 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
resolveExternalBestEffortDeliveryTarget,
|
||||
shouldDowngradeDeliveryToSessionOnly,
|
||||
} from "./best-effort-delivery.js";
|
||||
|
||||
vi.mock("../../utils/message-channel.js", () => ({
|
||||
INTERNAL_MESSAGE_CHANNEL: "webchat",
|
||||
isDeliverableMessageChannel: (value: string) => ["alpha", "richchat"].includes(value),
|
||||
normalizeMessageChannel: (value?: string | null) =>
|
||||
typeof value === "string" ? value.trim().toLowerCase() : undefined,
|
||||
}));
|
||||
|
||||
describe("best-effort delivery helpers", () => {
|
||||
it("resolves external delivery targets only for deliverable channels with to", () => {
|
||||
expect(
|
||||
resolveExternalBestEffortDeliveryTarget({
|
||||
channel: "discord",
|
||||
channel: "richchat",
|
||||
to: "channel:123",
|
||||
accountId: "default",
|
||||
threadId: "thread-1",
|
||||
}),
|
||||
).toEqual({
|
||||
deliver: true,
|
||||
channel: "discord",
|
||||
channel: "richchat",
|
||||
to: "channel:123",
|
||||
accountId: "default",
|
||||
threadId: "thread-1",
|
||||
@@ -40,7 +47,7 @@ describe("best-effort delivery helpers", () => {
|
||||
it("returns session-only when to is missing", () => {
|
||||
expect(
|
||||
resolveExternalBestEffortDeliveryTarget({
|
||||
channel: "telegram",
|
||||
channel: "alpha",
|
||||
}),
|
||||
).toEqual({
|
||||
deliver: false,
|
||||
@@ -72,7 +79,7 @@ describe("best-effort delivery helpers", () => {
|
||||
shouldDowngradeDeliveryToSessionOnly({
|
||||
wantsDelivery: true,
|
||||
bestEffortDeliver: true,
|
||||
resolvedChannel: "discord",
|
||||
resolvedChannel: "richchat",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
|
||||
const TARGET_SESSION_KEY = "agent:main:subagent:child";
|
||||
|
||||
function createDiscordBinding(
|
||||
function createRuntimeBinding(
|
||||
targetSessionKey: string,
|
||||
conversationId: string,
|
||||
boundAt: number,
|
||||
@@ -19,7 +19,7 @@ function createDiscordBinding(
|
||||
targetSessionKey,
|
||||
targetKind: "subagent",
|
||||
conversation: {
|
||||
channel: "discord",
|
||||
channel: "richchat",
|
||||
accountId: "runtime",
|
||||
conversationId,
|
||||
parentConversationId,
|
||||
@@ -29,12 +29,12 @@ function createDiscordBinding(
|
||||
};
|
||||
}
|
||||
|
||||
function registerDiscordSessionBindings(
|
||||
function registerRuntimeSessionBindings(
|
||||
targetSessionKey: string,
|
||||
bindings: SessionBindingRecord[],
|
||||
): void {
|
||||
registerSessionBindingAdapter({
|
||||
channel: "discord",
|
||||
channel: "richchat",
|
||||
accountId: "runtime",
|
||||
listBySession: (requestedSessionKey) =>
|
||||
requestedSessionKey === targetSessionKey ? bindings : [],
|
||||
@@ -54,7 +54,7 @@ describe("bound delivery router", () => {
|
||||
failClosed?: boolean;
|
||||
}) => {
|
||||
if (params.bindings) {
|
||||
registerDiscordSessionBindings(
|
||||
registerRuntimeSessionBindings(
|
||||
params.targetSessionKey ?? TARGET_SESSION_KEY,
|
||||
params.bindings,
|
||||
);
|
||||
@@ -65,7 +65,7 @@ describe("bound delivery router", () => {
|
||||
...(params.requesterConversationId !== undefined
|
||||
? {
|
||||
requester: {
|
||||
channel: "discord",
|
||||
channel: "richchat",
|
||||
accountId: "runtime",
|
||||
conversationId: params.requesterConversationId,
|
||||
},
|
||||
@@ -78,7 +78,7 @@ describe("bound delivery router", () => {
|
||||
it.each([
|
||||
{
|
||||
name: "resolves to a bound destination when a single active binding exists",
|
||||
bindings: [createDiscordBinding(TARGET_SESSION_KEY, "thread-1", 1, "parent-1")],
|
||||
bindings: [createRuntimeBinding(TARGET_SESSION_KEY, "thread-1", 1, "parent-1")],
|
||||
requesterConversationId: "parent-1",
|
||||
expected: {
|
||||
mode: "bound",
|
||||
@@ -98,8 +98,8 @@ describe("bound delivery router", () => {
|
||||
{
|
||||
name: "fails closed when multiple bindings exist without requester signal",
|
||||
bindings: [
|
||||
createDiscordBinding(TARGET_SESSION_KEY, "thread-1", 1),
|
||||
createDiscordBinding(TARGET_SESSION_KEY, "thread-2", 2),
|
||||
createRuntimeBinding(TARGET_SESSION_KEY, "thread-1", 1),
|
||||
createRuntimeBinding(TARGET_SESSION_KEY, "thread-2", 2),
|
||||
],
|
||||
failClosed: true,
|
||||
expected: {
|
||||
@@ -111,8 +111,8 @@ describe("bound delivery router", () => {
|
||||
{
|
||||
name: "selects requester-matching conversation when multiple bindings exist",
|
||||
bindings: [
|
||||
createDiscordBinding(TARGET_SESSION_KEY, "thread-1", 1),
|
||||
createDiscordBinding(TARGET_SESSION_KEY, "thread-2", 2),
|
||||
createRuntimeBinding(TARGET_SESSION_KEY, "thread-1", 1),
|
||||
createRuntimeBinding(TARGET_SESSION_KEY, "thread-2", 2),
|
||||
],
|
||||
requesterConversationId: "thread-2",
|
||||
failClosed: true,
|
||||
@@ -126,17 +126,17 @@ describe("bound delivery router", () => {
|
||||
name: "normalizes adapter binding conversations before requester matching",
|
||||
bindings: [
|
||||
{
|
||||
...createDiscordBinding(TARGET_SESSION_KEY, "thread-1", 1),
|
||||
...createRuntimeBinding(TARGET_SESSION_KEY, "thread-1", 1),
|
||||
conversation: {
|
||||
channel: " discord ",
|
||||
channel: " richchat ",
|
||||
accountId: " runtime ",
|
||||
conversationId: " thread-1 ",
|
||||
},
|
||||
},
|
||||
{
|
||||
...createDiscordBinding(TARGET_SESSION_KEY, "thread-2", 2),
|
||||
...createRuntimeBinding(TARGET_SESSION_KEY, "thread-2", 2),
|
||||
conversation: {
|
||||
channel: " DISCORD ",
|
||||
channel: " RICHCHAT ",
|
||||
accountId: " Runtime ",
|
||||
conversationId: " thread-2 ",
|
||||
},
|
||||
@@ -152,7 +152,7 @@ describe("bound delivery router", () => {
|
||||
},
|
||||
{
|
||||
name: "falls back for invalid requester conversation values",
|
||||
bindings: [createDiscordBinding(TARGET_SESSION_KEY, "thread-1", 1)],
|
||||
bindings: [createRuntimeBinding(TARGET_SESSION_KEY, "thread-1", 1)],
|
||||
requesterConversationId: " ",
|
||||
failClosed: true,
|
||||
expected: {
|
||||
|
||||
@@ -7,21 +7,21 @@ describe("buildDirectoryCacheKey", () => {
|
||||
it.each([
|
||||
{
|
||||
input: {
|
||||
channel: "slack",
|
||||
channel: "workspace",
|
||||
kind: "channel",
|
||||
source: "cache",
|
||||
},
|
||||
expected: "slack:default:channel:cache:default",
|
||||
expected: "workspace:default:channel:cache:default",
|
||||
},
|
||||
{
|
||||
input: {
|
||||
channel: "discord",
|
||||
channel: "richchat",
|
||||
accountId: "work",
|
||||
kind: "user",
|
||||
source: "live",
|
||||
signature: "v2",
|
||||
},
|
||||
expected: "discord:work:user:live:v2",
|
||||
expected: "richchat:work:user:live:v2",
|
||||
},
|
||||
] satisfies Array<{ input: DirectoryCacheKey; expected: string }>)(
|
||||
"includes account and signature fallbacks for %j",
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { OutboundDeliveryJson } from "./format.js";
|
||||
|
||||
describe("buildOutboundResultEnvelope", () => {
|
||||
const delivery: OutboundDeliveryJson = {
|
||||
channel: "telegram",
|
||||
channel: "alpha",
|
||||
via: "direct",
|
||||
to: "123",
|
||||
messageId: "m1",
|
||||
|
||||
@@ -5,7 +5,19 @@ import {
|
||||
formatOutboundDeliverySummary,
|
||||
} from "./format.js";
|
||||
|
||||
const getChannelPluginMock = vi.hoisted(() => vi.fn((_channel: unknown) => undefined));
|
||||
const getChannelPluginMock = vi.hoisted(() =>
|
||||
vi.fn((channel: string) => {
|
||||
const labels: Record<string, string> = {
|
||||
alpha: "Alpha",
|
||||
localchat: "Local Chat",
|
||||
richchat: "Rich Chat",
|
||||
workspace: "Workspace",
|
||||
teamchat: "Team Chat",
|
||||
};
|
||||
const label = labels[channel];
|
||||
return label ? { meta: { label } } : undefined;
|
||||
}),
|
||||
);
|
||||
|
||||
vi.mock("../../channels/plugins/index.js", () => ({
|
||||
getLoadedChannelPlugin: getChannelPluginMock,
|
||||
@@ -14,50 +26,50 @@ vi.mock("../../channels/plugins/index.js", () => ({
|
||||
describe("formatOutboundDeliverySummary", () => {
|
||||
it.each([
|
||||
{
|
||||
channel: "telegram" as const,
|
||||
channel: "alpha" as const,
|
||||
result: undefined,
|
||||
expected: "✅ Sent via Telegram. Message ID: unknown",
|
||||
expected: "✅ Sent via Alpha. Message ID: unknown",
|
||||
},
|
||||
{
|
||||
channel: "imessage" as const,
|
||||
channel: "localchat" as const,
|
||||
result: undefined,
|
||||
expected: "✅ Sent via iMessage. Message ID: unknown",
|
||||
expected: "✅ Sent via Local Chat. Message ID: unknown",
|
||||
},
|
||||
{
|
||||
channel: "telegram" as const,
|
||||
channel: "alpha" as const,
|
||||
result: {
|
||||
channel: "telegram" as const,
|
||||
channel: "alpha" as const,
|
||||
messageId: "m1",
|
||||
chatId: "c1",
|
||||
},
|
||||
expected: "✅ Sent via Telegram. Message ID: m1 (chat c1)",
|
||||
expected: "✅ Sent via Alpha. Message ID: m1 (chat c1)",
|
||||
},
|
||||
{
|
||||
channel: "discord" as const,
|
||||
channel: "richchat" as const,
|
||||
result: {
|
||||
channel: "discord" as const,
|
||||
channel: "richchat" as const,
|
||||
messageId: "d1",
|
||||
channelId: "chan",
|
||||
},
|
||||
expected: "✅ Sent via Discord. Message ID: d1 (channel chan)",
|
||||
expected: "✅ Sent via Rich Chat. Message ID: d1 (channel chan)",
|
||||
},
|
||||
{
|
||||
channel: "slack" as const,
|
||||
channel: "workspace" as const,
|
||||
result: {
|
||||
channel: "slack" as const,
|
||||
channel: "workspace" as const,
|
||||
messageId: "s1",
|
||||
roomId: "room-1",
|
||||
},
|
||||
expected: "✅ Sent via Slack. Message ID: s1 (room room-1)",
|
||||
expected: "✅ Sent via Workspace. Message ID: s1 (room room-1)",
|
||||
},
|
||||
{
|
||||
channel: "msteams" as const,
|
||||
channel: "teamchat" as const,
|
||||
result: {
|
||||
channel: "msteams" as const,
|
||||
channel: "teamchat" as const,
|
||||
messageId: "t1",
|
||||
conversationId: "conv-1",
|
||||
},
|
||||
expected: "✅ Sent via Microsoft Teams. Message ID: t1 (conversation conv-1)",
|
||||
expected: "✅ Sent via Team Chat. Message ID: t1 (conversation conv-1)",
|
||||
},
|
||||
])("formats delivery summary for %j", ({ channel, result, expected }) => {
|
||||
expect(formatOutboundDeliverySummary(channel, result)).toBe(expected);
|
||||
@@ -68,13 +80,13 @@ describe("buildOutboundDeliveryJson", () => {
|
||||
it.each([
|
||||
{
|
||||
input: {
|
||||
channel: "telegram" as const,
|
||||
channel: "alpha" as const,
|
||||
to: "123",
|
||||
result: { channel: "telegram" as const, messageId: "m1", chatId: "c1" },
|
||||
result: { channel: "alpha" as const, messageId: "m1", chatId: "c1" },
|
||||
mediaUrl: "https://example.com/a.png",
|
||||
},
|
||||
expected: {
|
||||
channel: "telegram",
|
||||
channel: "alpha",
|
||||
via: "direct",
|
||||
to: "123",
|
||||
messageId: "m1",
|
||||
@@ -84,12 +96,12 @@ describe("buildOutboundDeliveryJson", () => {
|
||||
},
|
||||
{
|
||||
input: {
|
||||
channel: "whatsapp" as const,
|
||||
channel: "directchat" as const,
|
||||
to: "+1",
|
||||
result: { channel: "whatsapp" as const, messageId: "w1", toJid: "jid" },
|
||||
result: { channel: "directchat" as const, messageId: "w1", toJid: "jid" },
|
||||
},
|
||||
expected: {
|
||||
channel: "whatsapp",
|
||||
channel: "directchat",
|
||||
via: "direct",
|
||||
to: "+1",
|
||||
messageId: "w1",
|
||||
@@ -99,12 +111,12 @@ describe("buildOutboundDeliveryJson", () => {
|
||||
},
|
||||
{
|
||||
input: {
|
||||
channel: "signal" as const,
|
||||
channel: "pager" as const,
|
||||
to: "+1",
|
||||
result: { channel: "signal" as const, messageId: "s1", timestamp: 123 },
|
||||
result: { channel: "pager" as const, messageId: "s1", timestamp: 123 },
|
||||
},
|
||||
expected: {
|
||||
channel: "signal",
|
||||
channel: "pager",
|
||||
via: "direct",
|
||||
to: "+1",
|
||||
messageId: "s1",
|
||||
@@ -114,7 +126,7 @@ describe("buildOutboundDeliveryJson", () => {
|
||||
},
|
||||
{
|
||||
input: {
|
||||
channel: "discord" as const,
|
||||
channel: "richchat" as const,
|
||||
to: "channel:1",
|
||||
via: "gateway" as const,
|
||||
result: {
|
||||
@@ -124,7 +136,7 @@ describe("buildOutboundDeliveryJson", () => {
|
||||
},
|
||||
},
|
||||
expected: {
|
||||
channel: "discord",
|
||||
channel: "richchat",
|
||||
via: "gateway",
|
||||
to: "channel:1",
|
||||
messageId: "g1",
|
||||
@@ -141,12 +153,12 @@ describe("buildOutboundDeliveryJson", () => {
|
||||
describe("formatGatewaySummary", () => {
|
||||
it.each([
|
||||
{
|
||||
input: { channel: "whatsapp", messageId: "m1" },
|
||||
expected: "✅ Sent via gateway (whatsapp). Message ID: m1",
|
||||
input: { channel: "directchat", messageId: "m1" },
|
||||
expected: "✅ Sent via gateway (directchat). Message ID: m1",
|
||||
},
|
||||
{
|
||||
input: { action: "Poll sent", channel: "discord", messageId: "p1" },
|
||||
expected: "✅ Poll sent via gateway (discord). Message ID: p1",
|
||||
input: { action: "Poll sent", channel: "richchat", messageId: "p1" },
|
||||
expected: "✅ Poll sent via gateway (richchat). Message ID: p1",
|
||||
},
|
||||
{
|
||||
input: {},
|
||||
|
||||
@@ -60,23 +60,23 @@ describe("DirectoryCache", () => {
|
||||
});
|
||||
|
||||
describe("buildOutboundResultEnvelope", () => {
|
||||
const whatsappDelivery: OutboundDeliveryJson = {
|
||||
channel: "whatsapp",
|
||||
const directChatDelivery: OutboundDeliveryJson = {
|
||||
channel: "directchat",
|
||||
via: "gateway",
|
||||
to: "+1",
|
||||
messageId: "m1",
|
||||
mediaUrl: null,
|
||||
};
|
||||
const telegramDelivery: OutboundDeliveryJson = {
|
||||
channel: "telegram",
|
||||
const alphaDelivery: OutboundDeliveryJson = {
|
||||
channel: "alpha",
|
||||
via: "direct",
|
||||
to: "123",
|
||||
messageId: "m2",
|
||||
mediaUrl: null,
|
||||
chatId: "c1",
|
||||
};
|
||||
const discordDelivery: OutboundDeliveryJson = {
|
||||
channel: "discord",
|
||||
const richChatDelivery: OutboundDeliveryJson = {
|
||||
channel: "richchat",
|
||||
via: "gateway",
|
||||
to: "channel:C1",
|
||||
messageId: "m3",
|
||||
@@ -92,8 +92,8 @@ describe("buildOutboundResultEnvelope", () => {
|
||||
}>([
|
||||
{
|
||||
name: "flatten delivery by default",
|
||||
input: { delivery: whatsappDelivery },
|
||||
expected: whatsappDelivery,
|
||||
input: { delivery: directChatDelivery },
|
||||
expected: directChatDelivery,
|
||||
},
|
||||
{
|
||||
name: "keep payloads + meta",
|
||||
@@ -108,17 +108,17 @@ describe("buildOutboundResultEnvelope", () => {
|
||||
},
|
||||
{
|
||||
name: "include delivery when payloads exist",
|
||||
input: { payloads: [], delivery: telegramDelivery, meta: { ok: true } },
|
||||
input: { payloads: [], delivery: alphaDelivery, meta: { ok: true } },
|
||||
expected: {
|
||||
payloads: [],
|
||||
meta: { ok: true },
|
||||
delivery: telegramDelivery,
|
||||
delivery: alphaDelivery,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "keep wrapped delivery when flatten disabled",
|
||||
input: { delivery: discordDelivery, flattenDelivery: false },
|
||||
expected: { delivery: discordDelivery },
|
||||
input: { delivery: richChatDelivery, flattenDelivery: false },
|
||||
expected: { delivery: richChatDelivery },
|
||||
},
|
||||
]),
|
||||
)("$name", ({ input, expected }) => {
|
||||
|
||||
Reference in New Issue
Block a user