mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 17:10:49 +00:00
Tests: avoid bundled Discord runtime lookup
This commit is contained in:
@@ -1,17 +1,25 @@
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
import type { NativeCommandSpec } from "openclaw/plugin-sdk/command-auth";
|
||||
import { resolveDirectStatusReplyForSession } from "openclaw/plugin-sdk/command-status-runtime";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { clearPluginCommands, registerPluginCommand } from "openclaw/plugin-sdk/plugin-runtime";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
clearPluginCommands,
|
||||
executePluginCommand,
|
||||
matchPluginCommand,
|
||||
registerPluginCommand,
|
||||
} from "openclaw/plugin-sdk/plugin-runtime";
|
||||
import { dispatchReplyWithDispatcher } from "openclaw/plugin-sdk/reply-dispatch-runtime";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
createTestRegistry,
|
||||
setActivePluginRegistry,
|
||||
} from "../../../../test/helpers/plugins/plugin-registry.js";
|
||||
import { resolveDiscordNativeInteractionRouteState } from "./native-command-route.js";
|
||||
import {
|
||||
createMockCommandInteraction,
|
||||
type MockCommandInteraction,
|
||||
} from "./native-command.test-helpers.js";
|
||||
import { createNoopThreadBindingManager } from "./thread-bindings.js";
|
||||
import { createNoopThreadBindingManager } from "./thread-bindings.manager.js";
|
||||
|
||||
let createDiscordNativeCommand: typeof import("./native-command.js").createDiscordNativeCommand;
|
||||
let discordNativeCommandTesting: typeof import("./native-command.js").__testing;
|
||||
@@ -22,33 +30,6 @@ const runtimeModuleMocks = vi.hoisted(() => ({
|
||||
resolveDirectStatusReplyForSession: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/plugin-runtime", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/plugin-runtime")>(
|
||||
"openclaw/plugin-sdk/plugin-runtime",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
matchPluginCommand: (...args: unknown[]) => runtimeModuleMocks.matchPluginCommand(...args),
|
||||
executePluginCommand: (...args: unknown[]) => runtimeModuleMocks.executePluginCommand(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/reply-runtime", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/reply-runtime")>(
|
||||
"openclaw/plugin-sdk/reply-runtime",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
dispatchReplyWithDispatcher: (...args: unknown[]) =>
|
||||
runtimeModuleMocks.dispatchReplyWithDispatcher(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/command-status-runtime", () => ({
|
||||
resolveDirectStatusReplyForSession: (...args: unknown[]) =>
|
||||
runtimeModuleMocks.resolveDirectStatusReplyForSession(...args),
|
||||
}));
|
||||
|
||||
function createInteraction(params?: {
|
||||
channelType?: ChannelType;
|
||||
channelId?: string;
|
||||
@@ -270,13 +251,16 @@ async function expectPairCommandReply(params: {
|
||||
cfg: OpenClawConfig;
|
||||
commandName: string;
|
||||
interaction: MockCommandInteraction;
|
||||
expectedRegisteredName?: string;
|
||||
}) {
|
||||
const command = await createPluginCommand({
|
||||
cfg: params.cfg,
|
||||
name: params.commandName,
|
||||
});
|
||||
const dispatchSpy = runtimeModuleMocks.dispatchReplyWithDispatcher;
|
||||
|
||||
const executeSpy = runtimeModuleMocks.executePluginCommand.mockResolvedValue({
|
||||
text: "paired:now",
|
||||
});
|
||||
await (command as { run: (interaction: unknown) => Promise<void> }).run(
|
||||
Object.assign(params.interaction, {
|
||||
options: {
|
||||
@@ -288,6 +272,12 @@ async function expectPairCommandReply(params: {
|
||||
);
|
||||
|
||||
expect(dispatchSpy).not.toHaveBeenCalled();
|
||||
expect(executeSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
command: expect.objectContaining({ name: params.expectedRegisteredName ?? "pair" }),
|
||||
args: "now",
|
||||
}),
|
||||
);
|
||||
expect(params.interaction.followUp).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ content: "paired:now" }),
|
||||
);
|
||||
@@ -338,21 +328,28 @@ describe("Discord native plugin command dispatch", () => {
|
||||
await import("./native-command.js"));
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
afterAll(() => {
|
||||
clearPluginCommands();
|
||||
setActivePluginRegistry(createTestRegistry());
|
||||
discordNativeCommandTesting.setMatchPluginCommand(matchPluginCommand);
|
||||
discordNativeCommandTesting.setExecutePluginCommand(executePluginCommand);
|
||||
discordNativeCommandTesting.setDispatchReplyWithDispatcher(dispatchReplyWithDispatcher);
|
||||
discordNativeCommandTesting.setResolveDirectStatusReplyForSession(
|
||||
resolveDirectStatusReplyForSession,
|
||||
);
|
||||
discordNativeCommandTesting.setResolveDiscordNativeInteractionRouteState(
|
||||
resolveDiscordNativeInteractionRouteState,
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
clearPluginCommands();
|
||||
setActivePluginRegistry(createTestRegistry());
|
||||
const actualPluginRuntime = await vi.importActual<
|
||||
typeof import("openclaw/plugin-sdk/plugin-runtime")
|
||||
>("openclaw/plugin-sdk/plugin-runtime");
|
||||
runtimeModuleMocks.matchPluginCommand.mockReset();
|
||||
runtimeModuleMocks.matchPluginCommand.mockImplementation(
|
||||
actualPluginRuntime.matchPluginCommand,
|
||||
);
|
||||
runtimeModuleMocks.matchPluginCommand.mockImplementation(matchPluginCommand);
|
||||
runtimeModuleMocks.executePluginCommand.mockReset();
|
||||
runtimeModuleMocks.executePluginCommand.mockImplementation(
|
||||
actualPluginRuntime.executePluginCommand,
|
||||
);
|
||||
runtimeModuleMocks.executePluginCommand.mockImplementation(executePluginCommand);
|
||||
runtimeModuleMocks.dispatchReplyWithDispatcher.mockReset();
|
||||
runtimeModuleMocks.dispatchReplyWithDispatcher.mockResolvedValue({
|
||||
counts: {
|
||||
@@ -372,7 +369,10 @@ describe("Discord native plugin command dispatch", () => {
|
||||
runtimeModuleMocks.executePluginCommand as typeof import("openclaw/plugin-sdk/plugin-runtime").executePluginCommand,
|
||||
);
|
||||
discordNativeCommandTesting.setDispatchReplyWithDispatcher(
|
||||
runtimeModuleMocks.dispatchReplyWithDispatcher as typeof import("openclaw/plugin-sdk/reply-runtime").dispatchReplyWithDispatcher,
|
||||
runtimeModuleMocks.dispatchReplyWithDispatcher as typeof dispatchReplyWithDispatcher,
|
||||
);
|
||||
discordNativeCommandTesting.setResolveDirectStatusReplyForSession(
|
||||
runtimeModuleMocks.resolveDirectStatusReplyForSession as typeof resolveDirectStatusReplyForSession,
|
||||
);
|
||||
discordNativeCommandTesting.setResolveDiscordNativeInteractionRouteState(async (params) =>
|
||||
createUnboundRouteState({
|
||||
@@ -436,7 +436,6 @@ describe("Discord native plugin command dispatch", () => {
|
||||
description: "Pair",
|
||||
acceptsArgs: true,
|
||||
};
|
||||
const command = await createNativeCommand(cfg, commandSpec);
|
||||
const interaction = createInteraction({
|
||||
channelType: ChannelType.GuildText,
|
||||
channelId: "234567890123456789",
|
||||
@@ -455,6 +454,7 @@ describe("Discord native plugin command dispatch", () => {
|
||||
handler: async ({ args }) => ({ text: `open:${args ?? ""}` }),
|
||||
}),
|
||||
).toEqual({ ok: true });
|
||||
const command = await createNativeCommand(cfg, commandSpec);
|
||||
|
||||
const executeSpy = runtimeModuleMocks.executePluginCommand;
|
||||
const dispatchSpy = runtimeModuleMocks.dispatchReplyWithDispatcher.mockResolvedValue(
|
||||
|
||||
@@ -94,6 +94,7 @@ const DISCORD_COMMAND_DESCRIPTION_MAX = 100;
|
||||
let matchPluginCommandImpl = pluginRuntime.matchPluginCommand;
|
||||
let executePluginCommandImpl = pluginRuntime.executePluginCommand;
|
||||
let dispatchReplyWithDispatcherImpl = dispatchReplyWithDispatcher;
|
||||
let resolveDirectStatusReplyForSessionImpl = resolveDirectStatusReplyForSession;
|
||||
let resolveDiscordNativeInteractionRouteStateImpl = resolveDiscordNativeInteractionRouteState;
|
||||
|
||||
export const __testing = {
|
||||
@@ -118,6 +119,13 @@ export const __testing = {
|
||||
dispatchReplyWithDispatcherImpl = next;
|
||||
return previous;
|
||||
},
|
||||
setResolveDirectStatusReplyForSession(
|
||||
next: typeof resolveDirectStatusReplyForSession,
|
||||
): typeof resolveDirectStatusReplyForSession {
|
||||
const previous = resolveDirectStatusReplyForSessionImpl;
|
||||
resolveDirectStatusReplyForSessionImpl = next;
|
||||
return previous;
|
||||
},
|
||||
setResolveDiscordNativeInteractionRouteState(
|
||||
next: typeof resolveDiscordNativeInteractionRouteState,
|
||||
): typeof resolveDiscordNativeInteractionRouteState {
|
||||
@@ -621,6 +629,19 @@ async function safeDiscordInteractionCall<T>(
|
||||
}
|
||||
}
|
||||
|
||||
function createNativeCommandDefinition(command: NativeCommandSpec): ChatCommandDefinition {
|
||||
return {
|
||||
key: command.name,
|
||||
nativeName: command.name,
|
||||
description: command.description,
|
||||
textAliases: [],
|
||||
acceptsArgs: command.acceptsArgs,
|
||||
args: command.args,
|
||||
argsParsing: "none",
|
||||
scope: "native",
|
||||
};
|
||||
}
|
||||
|
||||
export function createDiscordNativeCommand(params: {
|
||||
command: NativeCommandSpec;
|
||||
cfg: ReturnType<typeof loadConfig>;
|
||||
@@ -639,18 +660,13 @@ export function createDiscordNativeCommand(params: {
|
||||
ephemeralDefault,
|
||||
threadBindings,
|
||||
} = params;
|
||||
const fallbackCommandDefinition = createNativeCommandDefinition(command);
|
||||
const commandDefinition =
|
||||
findCommandByNativeName(command.name, "discord") ??
|
||||
({
|
||||
key: command.name,
|
||||
nativeName: command.name,
|
||||
description: command.description,
|
||||
textAliases: [],
|
||||
acceptsArgs: command.acceptsArgs,
|
||||
args: command.args,
|
||||
argsParsing: "none",
|
||||
scope: "native",
|
||||
} satisfies ChatCommandDefinition);
|
||||
matchPluginCommandImpl(`/${command.name}`) !== null
|
||||
? fallbackCommandDefinition
|
||||
: (findCommandByNativeName(command.name, "discord", {
|
||||
includeBundledChannelFallback: false,
|
||||
}) ?? fallbackCommandDefinition);
|
||||
const argDefinitions = commandDefinition.args ?? command.args;
|
||||
const commandOptions = buildDiscordCommandOptions({
|
||||
command: commandDefinition,
|
||||
@@ -1130,7 +1146,7 @@ async function dispatchDiscordCommandInteraction(params: {
|
||||
});
|
||||
const mediaLocalRoots = getAgentScopedMediaLocalRoots(cfg, effectiveRoute.agentId);
|
||||
if (!suppressReplies && commandName === "status") {
|
||||
const statusReply = await resolveDirectStatusReplyForSession({
|
||||
const statusReply = await resolveDirectStatusReplyForSessionImpl({
|
||||
cfg,
|
||||
sessionKey: commandTargetSessionKey?.trim() || sessionKey,
|
||||
channel: "discord",
|
||||
|
||||
Reference in New Issue
Block a user