feat: add onboarding plugin install flow
This commit is contained in:
126
src/commands/onboarding/plugin-install.test.ts
Normal file
126
src/commands/onboarding/plugin-install.test.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import path from "node:path";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("node:fs", () => ({
|
||||
default: {
|
||||
existsSync: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const installPluginFromNpmSpec = vi.fn();
|
||||
vi.mock("../../plugins/install.js", () => ({
|
||||
installPluginFromNpmSpec: (...args: unknown[]) => installPluginFromNpmSpec(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/loader.js", () => ({
|
||||
loadClawdbotPlugins: vi.fn(),
|
||||
}));
|
||||
|
||||
import fs from "node:fs";
|
||||
import type { ChannelPluginCatalogEntry } from "../../channels/plugins/catalog.js";
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import type { WizardPrompter } from "../../wizard/prompts.js";
|
||||
import { makePrompter, makeRuntime } from "./__tests__/test-utils.js";
|
||||
import { ensureOnboardingPluginInstalled } from "./plugin-install.js";
|
||||
|
||||
const baseEntry: ChannelPluginCatalogEntry = {
|
||||
id: "zalo",
|
||||
meta: {
|
||||
id: "zalo",
|
||||
label: "Zalo",
|
||||
selectionLabel: "Zalo (Bot API)",
|
||||
docsPath: "/channels/zalo",
|
||||
docsLabel: "zalo",
|
||||
blurb: "Test",
|
||||
},
|
||||
install: {
|
||||
npmSpec: "@clawdbot/zalo",
|
||||
localPath: "extensions/zalo",
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("ensureOnboardingPluginInstalled", () => {
|
||||
it("installs from npm and enables the plugin", async () => {
|
||||
const runtime = makeRuntime();
|
||||
const prompter = makePrompter({
|
||||
select: vi.fn(async () => "npm") as WizardPrompter["select"],
|
||||
});
|
||||
const cfg: ClawdbotConfig = { plugins: { allow: ["other"] } };
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
installPluginFromNpmSpec.mockResolvedValue({
|
||||
ok: true,
|
||||
pluginId: "zalo",
|
||||
targetDir: "/tmp/zalo",
|
||||
extensions: [],
|
||||
});
|
||||
|
||||
const result = await ensureOnboardingPluginInstalled({
|
||||
cfg,
|
||||
entry: baseEntry,
|
||||
prompter,
|
||||
runtime,
|
||||
});
|
||||
|
||||
expect(result.installed).toBe(true);
|
||||
expect(result.cfg.plugins?.entries?.zalo?.enabled).toBe(true);
|
||||
expect(result.cfg.plugins?.allow).toContain("zalo");
|
||||
expect(installPluginFromNpmSpec).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ spec: "@clawdbot/zalo" }),
|
||||
);
|
||||
});
|
||||
|
||||
it("uses local path when selected", async () => {
|
||||
const runtime = makeRuntime();
|
||||
const prompter = makePrompter({
|
||||
select: vi.fn(async () => "local") as WizardPrompter["select"],
|
||||
});
|
||||
const cfg: ClawdbotConfig = {};
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
const result = await ensureOnboardingPluginInstalled({
|
||||
cfg,
|
||||
entry: baseEntry,
|
||||
prompter,
|
||||
runtime,
|
||||
});
|
||||
|
||||
const expectedPath = path.resolve(process.cwd(), "extensions/zalo");
|
||||
expect(result.installed).toBe(true);
|
||||
expect(result.cfg.plugins?.load?.paths).toContain(expectedPath);
|
||||
expect(result.cfg.plugins?.entries?.zalo?.enabled).toBe(true);
|
||||
});
|
||||
|
||||
it("falls back to local path after npm install failure", async () => {
|
||||
const runtime = makeRuntime();
|
||||
const note = vi.fn(async () => {});
|
||||
const confirm = vi.fn(async () => true);
|
||||
const prompter = makePrompter({
|
||||
select: vi.fn(async () => "npm") as WizardPrompter["select"],
|
||||
note,
|
||||
confirm,
|
||||
});
|
||||
const cfg: ClawdbotConfig = {};
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
installPluginFromNpmSpec.mockResolvedValue({
|
||||
ok: false,
|
||||
error: "nope",
|
||||
});
|
||||
|
||||
const result = await ensureOnboardingPluginInstalled({
|
||||
cfg,
|
||||
entry: baseEntry,
|
||||
prompter,
|
||||
runtime,
|
||||
});
|
||||
|
||||
const expectedPath = path.resolve(process.cwd(), "extensions/zalo");
|
||||
expect(result.installed).toBe(true);
|
||||
expect(result.cfg.plugins?.load?.paths).toContain(expectedPath);
|
||||
expect(note).toHaveBeenCalled();
|
||||
expect(runtime.error).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user