Files
openclaw/src/auto-reply/reply/commands-plugins.toggle.test.ts
2026-03-24 21:00:36 +00:00

138 lines
4.2 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
import { createPluginRecord, createPluginStatusReport } from "../../plugins/status.test-helpers.js";
const {
readConfigFileSnapshotMock,
validateConfigObjectWithPluginsMock,
writeConfigFileMock,
buildPluginStatusReportMock,
} = vi.hoisted(() => ({
readConfigFileSnapshotMock: vi.fn(),
validateConfigObjectWithPluginsMock: vi.fn(),
writeConfigFileMock: vi.fn(),
buildPluginStatusReportMock: vi.fn(),
}));
vi.mock("../../config/config.js", async () => {
const actual =
await vi.importActual<typeof import("../../config/config.js")>("../../config/config.js");
return {
...actual,
readConfigFileSnapshot: readConfigFileSnapshotMock,
validateConfigObjectWithPlugins: validateConfigObjectWithPluginsMock,
writeConfigFile: writeConfigFileMock,
};
});
vi.mock("../../plugins/status.js", async () => {
const actual =
await vi.importActual<typeof import("../../plugins/status.js")>("../../plugins/status.js");
return {
...actual,
buildPluginStatusReport: buildPluginStatusReportMock,
};
});
import { handleCommands } from "./commands-core.js";
import { buildCommandTestParams } from "./commands.test-harness.js";
function buildCfg() {
return {
plugins: {
enabled: true,
},
commands: {
text: true,
plugins: true,
},
};
}
describe("handleCommands /plugins toggle", () => {
afterEach(() => {
readConfigFileSnapshotMock.mockReset();
validateConfigObjectWithPluginsMock.mockReset();
writeConfigFileMock.mockReset();
buildPluginStatusReportMock.mockReset();
});
it("enables a discovered plugin", async () => {
const config = buildCfg();
readConfigFileSnapshotMock.mockResolvedValue({
valid: true,
path: "/tmp/openclaw.json",
resolved: config,
});
buildPluginStatusReportMock.mockReturnValue(
createPluginStatusReport({
workspaceDir: "/tmp/workspace",
plugins: [
createPluginRecord({
id: "superpowers",
format: "bundle",
source: "/tmp/workspace/.openclaw/extensions/superpowers",
enabled: false,
status: "disabled",
}),
],
}),
);
validateConfigObjectWithPluginsMock.mockImplementation((next) => ({ ok: true, config: next }));
writeConfigFileMock.mockResolvedValue(undefined);
const params = buildCommandTestParams("/plugins enable superpowers", buildCfg());
params.command.senderIsOwner = true;
const result = await handleCommands(params);
expect(result.reply?.text).toContain('Plugin "superpowers" enabled');
expect(writeConfigFileMock).toHaveBeenCalledWith(
expect.objectContaining({
plugins: expect.objectContaining({
entries: expect.objectContaining({
superpowers: expect.objectContaining({ enabled: true }),
}),
}),
}),
);
});
it("disables a discovered plugin", async () => {
const config = buildCfg();
readConfigFileSnapshotMock.mockResolvedValue({
valid: true,
path: "/tmp/openclaw.json",
resolved: config,
});
buildPluginStatusReportMock.mockReturnValue(
createPluginStatusReport({
workspaceDir: "/tmp/workspace",
plugins: [
createPluginRecord({
id: "superpowers",
format: "bundle",
source: "/tmp/workspace/.openclaw/extensions/superpowers",
enabled: true,
}),
],
}),
);
validateConfigObjectWithPluginsMock.mockImplementation((next) => ({ ok: true, config: next }));
writeConfigFileMock.mockResolvedValue(undefined);
const params = buildCommandTestParams("/plugins disable superpowers", buildCfg());
params.command.senderIsOwner = true;
const result = await handleCommands(params);
expect(result.reply?.text).toContain('Plugin "superpowers" disabled');
expect(writeConfigFileMock).toHaveBeenCalledWith(
expect.objectContaining({
plugins: expect.objectContaining({
entries: expect.objectContaining({
superpowers: expect.objectContaining({ enabled: false }),
}),
}),
}),
);
});
});