From b28070543a126eccdeb3d07277a15ab0e1d738e2 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 16 Jul 2026 02:48:15 -0700 Subject: [PATCH] test(discord): split channel target resolver tests (#108857) --- .../src/channel.target-resolver.test.ts | 85 +++++++++++++++++++ extensions/discord/src/channel.test.ts | 78 ----------------- 2 files changed, 85 insertions(+), 78 deletions(-) create mode 100644 extensions/discord/src/channel.target-resolver.test.ts diff --git a/extensions/discord/src/channel.target-resolver.test.ts b/extensions/discord/src/channel.target-resolver.test.ts new file mode 100644 index 000000000000..523a328847a5 --- /dev/null +++ b/extensions/discord/src/channel.target-resolver.test.ts @@ -0,0 +1,85 @@ +// Discord channel target-resolver tests cover normalized and directory-backed routing. +import { describe, expect, it, vi } from "vitest"; +import { discordPlugin } from "./channel.js"; +import * as directoryLive from "./directory-live.js"; +import type { OpenClawConfig } from "./runtime-api.js"; + +function createCfg(): OpenClawConfig { + return { + channels: { + discord: { + enabled: true, + token: "test-token-placeholder", + }, + }, + } as OpenClawConfig; +} + +function requireResolveTarget() { + const resolveTarget = discordPlugin.messaging?.targetResolver?.resolveTarget; + if (!resolveTarget) { + throw new Error("Expected discordPlugin.messaging.targetResolver.resolveTarget to be defined"); + } + return resolveTarget; +} + +describe("discordPlugin messaging target resolver", () => { + it("resolves Discord usernames through the messaging target resolver", async () => { + vi.spyOn(directoryLive, "listDiscordDirectoryPeersLive").mockResolvedValueOnce([ + { kind: "user", id: "user:999", name: "Jane" } as const, + ]); + + await expect( + requireResolveTarget()({ + cfg: createCfg(), + accountId: "default", + input: "jane", + normalized: "channel:jane", + preferredKind: "user", + }), + ).resolves.toEqual({ + to: "user:999", + kind: "user", + display: "jane", + source: "directory", + }); + }); + + it("rejects unresolved Discord names after the shared directory lookup misses", async () => { + vi.spyOn(directoryLive, "listDiscordDirectoryPeersLive").mockResolvedValue([]); + + await expect( + requireResolveTarget()({ + cfg: createCfg(), + accountId: "default", + input: "channel:missing", + normalized: "channel:missing", + preferredKind: "channel", + }), + ).resolves.toBeNull(); + await expect( + requireResolveTarget()({ + cfg: createCfg(), + accountId: "default", + input: "user:missing", + normalized: "user:missing", + preferredKind: "user", + }), + ).resolves.toBeNull(); + }); + + it("does not reinterpret a bare channel name as a Discord username on fallback", async () => { + vi.spyOn(directoryLive, "listDiscordDirectoryPeersLive").mockResolvedValueOnce([ + { kind: "user", id: "user:999", name: "General" } as const, + ]); + + await expect( + requireResolveTarget()({ + cfg: createCfg(), + accountId: "default", + input: "general", + normalized: "channel:general", + }), + ).resolves.toBeNull(); + }); +}); diff --git a/extensions/discord/src/channel.test.ts b/extensions/discord/src/channel.test.ts index 8c1930d3d6bd..4a2cda42a88c 100644 --- a/extensions/discord/src/channel.test.ts +++ b/extensions/discord/src/channel.test.ts @@ -6,7 +6,6 @@ import { createStartAccountContext } from "openclaw/plugin-sdk/channel-test-help import type { PluginRuntime } from "openclaw/plugin-sdk/core"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import type { ResolvedDiscordAccount } from "./accounts.js"; -import * as directoryLive from "./directory-live.js"; import type { OpenClawConfig } from "./runtime-api.js"; import * as sendModule from "./send.js"; import { createDiscordSendReceipt } from "./send.receipt.js"; @@ -262,83 +261,6 @@ describe("discordPlugin outbound", () => { expect(messaging.inferTargetChatType({ to: "1470130713209602050" })).toBe("channel"); }); - it("resolves Discord usernames through the messaging target resolver", async () => { - vi.spyOn(directoryLive, "listDiscordDirectoryPeersLive").mockResolvedValueOnce([ - { kind: "user", id: "user:999", name: "Jane" } as const, - ]); - const resolveTarget = discordPlugin.messaging?.targetResolver?.resolveTarget; - if (!resolveTarget) { - throw new Error( - "Expected discordPlugin.messaging.targetResolver.resolveTarget to be defined", - ); - } - - await expect( - resolveTarget({ - cfg: createCfg(), - accountId: "default", - input: "jane", - normalized: "channel:jane", - preferredKind: "user", - }), - ).resolves.toEqual({ - to: "user:999", - kind: "user", - display: "jane", - source: "directory", - }); - }); - - it("rejects unresolved Discord names after the shared directory lookup misses", async () => { - vi.spyOn(directoryLive, "listDiscordDirectoryPeersLive").mockResolvedValue([]); - const resolveTarget = discordPlugin.messaging?.targetResolver?.resolveTarget; - if (!resolveTarget) { - throw new Error( - "Expected discordPlugin.messaging.targetResolver.resolveTarget to be defined", - ); - } - - await expect( - resolveTarget({ - cfg: createCfg(), - accountId: "default", - input: "channel:missing", - normalized: "channel:missing", - preferredKind: "channel", - }), - ).resolves.toBeNull(); - await expect( - resolveTarget({ - cfg: createCfg(), - accountId: "default", - input: "user:missing", - normalized: "user:missing", - preferredKind: "user", - }), - ).resolves.toBeNull(); - }); - - it("does not reinterpret a bare channel name as a Discord username on fallback", async () => { - vi.spyOn(directoryLive, "listDiscordDirectoryPeersLive").mockResolvedValueOnce([ - { kind: "user", id: "user:999", name: "General" } as const, - ]); - const resolveTarget = discordPlugin.messaging?.targetResolver?.resolveTarget; - if (!resolveTarget) { - throw new Error( - "Expected discordPlugin.messaging.targetResolver.resolveTarget to be defined", - ); - } - - await expect( - resolveTarget({ - cfg: createCfg(), - accountId: "default", - input: "general", - normalized: "channel:general", - }), - ).resolves.toBeNull(); - }); - it("preserves the normalized channel kind for bare current-channel ids", async () => { const resolveTarget = discordPlugin.messaging?.targetResolver?.resolveTarget; if (!resolveTarget) {