mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 09:52:13 +00:00
124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
import { Command } from "commander";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const mocks = vi.hoisted(() => {
|
|
const logs: string[] = [];
|
|
const errors: string[] = [];
|
|
const runtime = {
|
|
log: vi.fn((value: unknown) => logs.push(String(value))),
|
|
error: vi.fn((value: unknown) => errors.push(String(value))),
|
|
writeJson: vi.fn((value: unknown, space = 2) =>
|
|
logs.push(JSON.stringify(value, null, space > 0 ? space : undefined)),
|
|
),
|
|
writeStdout: vi.fn((value: string) =>
|
|
logs.push(value.endsWith("\n") ? value.slice(0, -1) : value),
|
|
),
|
|
exit: vi.fn((code: number) => {
|
|
throw new Error(`__exit__:${code}`);
|
|
}),
|
|
};
|
|
return {
|
|
logs,
|
|
errors,
|
|
runtime,
|
|
searchClawHubPackages: vi.fn(),
|
|
};
|
|
});
|
|
|
|
vi.mock("../runtime.js", () => ({
|
|
defaultRuntime: mocks.runtime,
|
|
writeRuntimeJson: (runtime: typeof mocks.runtime, value: unknown, space = 2) =>
|
|
runtime.writeJson(value, space),
|
|
}));
|
|
|
|
vi.mock("../infra/clawhub.js", () => ({
|
|
searchClawHubPackages: mocks.searchClawHubPackages,
|
|
}));
|
|
|
|
const { runPluginsSearchCommand } = await import("./plugins-search-command.js");
|
|
const { registerPluginsCli } = await import("./plugins-cli.js");
|
|
|
|
describe("plugins search command", () => {
|
|
beforeEach(() => {
|
|
mocks.logs.length = 0;
|
|
mocks.errors.length = 0;
|
|
mocks.runtime.log.mockClear();
|
|
mocks.runtime.error.mockClear();
|
|
mocks.runtime.writeJson.mockClear();
|
|
mocks.runtime.exit.mockClear();
|
|
mocks.searchClawHubPackages.mockReset();
|
|
});
|
|
|
|
it("searches ClawHub code and bundle plugin families", async () => {
|
|
mocks.searchClawHubPackages
|
|
.mockResolvedValueOnce([
|
|
{
|
|
score: 12,
|
|
package: {
|
|
name: "openclaw-calendar",
|
|
displayName: "Calendar",
|
|
family: "code-plugin",
|
|
channel: "community",
|
|
isOfficial: false,
|
|
summary: "Calendar sync",
|
|
createdAt: 1,
|
|
updatedAt: 1,
|
|
latestVersion: "1.2.3",
|
|
},
|
|
},
|
|
])
|
|
.mockResolvedValueOnce([
|
|
{
|
|
score: 10,
|
|
package: {
|
|
name: "openclaw-calendar-bundle",
|
|
displayName: "Calendar Bundle",
|
|
family: "bundle-plugin",
|
|
channel: "official",
|
|
isOfficial: true,
|
|
summary: "Calendar bundle",
|
|
createdAt: 1,
|
|
updatedAt: 1,
|
|
latestVersion: "2.0.0",
|
|
},
|
|
},
|
|
]);
|
|
|
|
await runPluginsSearchCommand(["calendar"], { limit: 5 }, mocks.runtime);
|
|
|
|
expect(mocks.searchClawHubPackages).toHaveBeenCalledWith({
|
|
query: "calendar",
|
|
family: "code-plugin",
|
|
limit: 5,
|
|
});
|
|
expect(mocks.searchClawHubPackages).toHaveBeenCalledWith({
|
|
query: "calendar",
|
|
family: "bundle-plugin",
|
|
limit: 5,
|
|
});
|
|
expect(mocks.logs.join("\n")).toContain("openclaw-calendar");
|
|
expect(mocks.logs.join("\n")).toContain(
|
|
"Install: openclaw plugins install clawhub:openclaw-calendar",
|
|
);
|
|
});
|
|
|
|
it("writes JSON results when requested", async () => {
|
|
mocks.searchClawHubPackages.mockResolvedValueOnce([]).mockResolvedValueOnce([]);
|
|
|
|
await runPluginsSearchCommand("calendar", { json: true }, mocks.runtime);
|
|
|
|
expect(mocks.runtime.writeJson).toHaveBeenCalledWith({ results: [] }, 2);
|
|
});
|
|
|
|
it("rejects partial numeric search limits", async () => {
|
|
const program = new Command();
|
|
program.exitOverride();
|
|
registerPluginsCli(program);
|
|
|
|
await expect(
|
|
program.parseAsync(["plugins", "search", "calendar", "--limit", "10ms"], { from: "user" }),
|
|
).rejects.toThrow("--limit must be a positive integer.");
|
|
expect(mocks.searchClawHubPackages).not.toHaveBeenCalled();
|
|
});
|
|
});
|