openclaw / src /cli /program /message /register.thread.test.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
eb3f11e verified
Raw
History Blame Contribute Delete
5.8 kB
// Register thread tests cover message thread command registration and option wiring.
import { Command } from "commander";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { setActivePluginRegistry } from "../../../plugins/runtime.js";
import {
createChannelTestPluginBase,
createTestRegistry,
} from "../../../test-utils/channel-plugins.js";
import type { MessageCliHelpers } from "./helpers.js";
import { registerMessageThreadCommands } from "./register.thread.js";
function createHelpers(runMessageAction: MessageCliHelpers["runMessageAction"]): MessageCliHelpers {
return {
withMessageBase: (command) => command.option("--channel <channel>", "Channel"),
withMessageTarget: (command) => command.option("-t, --target <dest>", "Target"),
withRequiredMessageTarget: (command) => command.requiredOption("-t, --target <dest>", "Target"),
runMessageAction,
};
}
function firstMessageActionCall(runMessageAction: { mock: { calls: unknown[][] } }) {
return runMessageAction.mock.calls[0] as [string, Record<string, unknown>] | undefined;
}
describe("registerMessageThreadCommands", () => {
const runMessageAction = vi.fn(
async (_action: string, _opts: Record<string, unknown>) => undefined,
);
beforeEach(() => {
setActivePluginRegistry(
createTestRegistry([
{
pluginId: "topic-chat",
source: "test",
plugin: {
...createChannelTestPluginBase({ id: "topic-chat", label: "Topic chat" }),
actions: {
resolveCliActionRequest: ({
action,
args,
}: {
action: string;
args: Record<string, unknown>;
}) => {
if (action !== "thread-create") {
return null;
}
const { threadName, ...rest } = args;
return {
action: "topic-create",
args: {
...rest,
name: threadName,
},
};
},
},
},
},
{
pluginId: "plain-chat",
source: "test",
plugin: createChannelTestPluginBase({ id: "plain-chat", label: "Plain chat" }),
},
]),
);
runMessageAction.mockClear();
});
it("routes plugin-remapped thread create actions through channel hooks", async () => {
const message = new Command().exitOverride();
registerMessageThreadCommands(message, createHelpers(runMessageAction));
await message.parseAsync(
[
"thread",
"create",
"--channel",
" topic-chat ",
"-t",
"room-1",
"--thread-name",
"Build Updates",
"-m",
"hello",
],
{ from: "user" },
);
const remappedCall = firstMessageActionCall(runMessageAction);
expect(remappedCall?.[0]).toBe("topic-create");
expect(remappedCall?.[1]?.channel).toBe(" topic-chat ");
expect(remappedCall?.[1]?.target).toBe("room-1");
expect(remappedCall?.[1]?.name).toBe("Build Updates");
expect(remappedCall?.[1]?.message).toBe("hello");
expect(remappedCall?.[1]).not.toHaveProperty("threadName");
});
it.each([
{
description: "infers the action owner from a registered channel-prefixed target",
channel: undefined,
target: "topic-chat:room-1",
action: "topic-create",
},
{
description: "prefers an explicit channel over a conflicting target prefix",
channel: "plain-chat",
target: "topic-chat:room-1",
action: "thread-create",
},
{
description: "keeps prefixed channels without an action remap unchanged",
channel: undefined,
target: "plain-chat:room-1",
action: "thread-create",
},
{
description: "keeps an explicit action owner over a conflicting target prefix",
channel: "topic-chat",
target: "plain-chat:room-1",
action: "topic-create",
},
])("$description", async ({ action, channel, target }) => {
const message = new Command().exitOverride();
registerMessageThreadCommands(message, createHelpers(runMessageAction));
await message.parseAsync(
[
"thread",
"create",
...(channel ? ["--channel", channel] : []),
"--target",
target,
"--thread-name",
"Build Updates",
],
{ from: "user" },
);
const call = firstMessageActionCall(runMessageAction);
expect(call?.[0]).toBe(action);
expect(call?.[1]?.channel).toBe(channel);
expect(call?.[1]?.target).toBe(target);
expect(call?.[1]?.[action === "topic-create" ? "name" : "threadName"]).toBe("Build Updates");
expect(call?.[1]).not.toHaveProperty(action === "topic-create" ? "threadName" : "name");
});
it("keeps default thread create params when the channel does not remap the action", async () => {
const message = new Command().exitOverride();
registerMessageThreadCommands(message, createHelpers(runMessageAction));
await message.parseAsync(
[
"thread",
"create",
"--channel",
"plain-chat",
"-t",
"channel:123",
"--thread-name",
"Build Updates",
"-m",
"hello",
],
{ from: "user" },
);
const defaultCall = firstMessageActionCall(runMessageAction);
expect(defaultCall?.[0]).toBe("thread-create");
expect(defaultCall?.[1]?.channel).toBe("plain-chat");
expect(defaultCall?.[1]?.target).toBe("channel:123");
expect(defaultCall?.[1]?.threadName).toBe("Build Updates");
expect(defaultCall?.[1]?.message).toBe("hello");
expect(defaultCall?.[1]).not.toHaveProperty("name");
});
});