Files
openclaw/src/cli/run-main.test.ts
2026-02-17 10:15:20 +01:00

226 lines
6.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
rewriteUpdateFlagArgv,
shouldEnsureCliPath,
shouldRegisterPrimarySubcommand,
shouldSkipPluginCommandRegistration,
shouldUseInteractiveCommandSelector,
stripInteractiveSelectorArgs,
} from "./run-main.js";
describe("rewriteUpdateFlagArgv", () => {
it("leaves argv unchanged when --update is absent", () => {
const argv = ["node", "entry.js", "status"];
expect(rewriteUpdateFlagArgv(argv)).toBe(argv);
});
it("rewrites --update into the update command", () => {
expect(rewriteUpdateFlagArgv(["node", "entry.js", "--update"])).toEqual([
"node",
"entry.js",
"update",
]);
});
it("preserves global flags that appear before --update", () => {
expect(rewriteUpdateFlagArgv(["node", "entry.js", "--profile", "p", "--update"])).toEqual([
"node",
"entry.js",
"--profile",
"p",
"update",
]);
});
it("keeps update options after the rewritten command", () => {
expect(rewriteUpdateFlagArgv(["node", "entry.js", "--update", "--json"])).toEqual([
"node",
"entry.js",
"update",
"--json",
]);
});
});
describe("shouldRegisterPrimarySubcommand", () => {
it("skips eager primary registration for help/version invocations", () => {
expect(shouldRegisterPrimarySubcommand(["node", "openclaw", "status", "--help"])).toBe(false);
expect(shouldRegisterPrimarySubcommand(["node", "openclaw", "-V"])).toBe(false);
});
it("keeps eager primary registration for regular command runs", () => {
expect(shouldRegisterPrimarySubcommand(["node", "openclaw", "status"])).toBe(true);
});
});
describe("shouldSkipPluginCommandRegistration", () => {
it("skips plugin registration for root help/version", () => {
expect(
shouldSkipPluginCommandRegistration({
argv: ["node", "openclaw", "--help"],
primary: null,
hasBuiltinPrimary: false,
}),
).toBe(true);
});
it("skips plugin registration for builtin subcommand help", () => {
expect(
shouldSkipPluginCommandRegistration({
argv: ["node", "openclaw", "config", "--help"],
primary: "config",
hasBuiltinPrimary: true,
}),
).toBe(true);
});
it("skips plugin registration for builtin command runs", () => {
expect(
shouldSkipPluginCommandRegistration({
argv: ["node", "openclaw", "sessions", "--json"],
primary: "sessions",
hasBuiltinPrimary: true,
}),
).toBe(true);
});
it("keeps plugin registration for non-builtin help", () => {
expect(
shouldSkipPluginCommandRegistration({
argv: ["node", "openclaw", "voicecall", "--help"],
primary: "voicecall",
hasBuiltinPrimary: false,
}),
).toBe(false);
});
it("keeps plugin registration for non-builtin command runs", () => {
expect(
shouldSkipPluginCommandRegistration({
argv: ["node", "openclaw", "voicecall", "status"],
primary: "voicecall",
hasBuiltinPrimary: false,
}),
).toBe(false);
});
});
describe("shouldUseInteractiveCommandSelector", () => {
it("enables selector for -i", () => {
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw", "-i"],
stdinIsTTY: true,
stdoutIsTTY: true,
}),
).toBe(true);
});
it("enables selector for interactive command", () => {
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw", "interactive"],
stdinIsTTY: true,
stdoutIsTTY: true,
}),
).toBe(true);
});
it("keeps default no-arg invocation on fast help path", () => {
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw"],
stdinIsTTY: true,
stdoutIsTTY: true,
}),
).toBe(false);
});
it("ignores -i when a real command is already present", () => {
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw", "-i", "status"],
stdinIsTTY: true,
stdoutIsTTY: true,
}),
).toBe(false);
});
it("disables selector for non-interactive terminals or CI", () => {
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw", "-i"],
stdinIsTTY: false,
stdoutIsTTY: true,
}),
).toBe(false);
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw", "-i"],
stdinIsTTY: true,
stdoutIsTTY: true,
ciEnv: "1",
}),
).toBe(false);
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw", "interactive"],
stdinIsTTY: true,
stdoutIsTTY: true,
disableSelectorEnv: "1",
}),
).toBe(false);
});
it("disables selector for help/version invocations", () => {
expect(
shouldUseInteractiveCommandSelector({
argv: ["node", "openclaw", "-i", "--help"],
stdinIsTTY: true,
stdoutIsTTY: true,
}),
).toBe(false);
});
});
describe("stripInteractiveSelectorArgs", () => {
it("removes -i from root invocations", () => {
expect(stripInteractiveSelectorArgs(["node", "openclaw", "-i"])).toEqual(["node", "openclaw"]);
});
it("removes interactive command from root invocations", () => {
expect(stripInteractiveSelectorArgs(["node", "openclaw", "interactive"])).toEqual([
"node",
"openclaw",
]);
});
it("keeps unrelated arguments", () => {
expect(stripInteractiveSelectorArgs(["node", "openclaw", "--profile", "dev", "-i"])).toEqual([
"node",
"openclaw",
"--profile",
"dev",
]);
});
});
describe("shouldEnsureCliPath", () => {
it("skips path bootstrap for help/version invocations", () => {
expect(shouldEnsureCliPath(["node", "openclaw", "--help"])).toBe(false);
expect(shouldEnsureCliPath(["node", "openclaw", "-V"])).toBe(false);
});
it("skips path bootstrap for read-only fast paths", () => {
expect(shouldEnsureCliPath(["node", "openclaw", "status"])).toBe(false);
expect(shouldEnsureCliPath(["node", "openclaw", "sessions", "--json"])).toBe(false);
expect(shouldEnsureCliPath(["node", "openclaw", "config", "get", "update"])).toBe(false);
expect(shouldEnsureCliPath(["node", "openclaw", "models", "status", "--json"])).toBe(false);
});
it("keeps path bootstrap for mutating or unknown commands", () => {
expect(shouldEnsureCliPath(["node", "openclaw", "message", "send"])).toBe(true);
expect(shouldEnsureCliPath(["node", "openclaw", "voicecall", "status"])).toBe(true);
});
});