import { beforeEach, describe, expect, it, vi } from "vitest"; const installPluginFromNpmSpecMock = vi.fn(); vi.mock("./install.js", () => ({ installPluginFromNpmSpec: (...args: unknown[]) => installPluginFromNpmSpecMock(...args), resolvePluginInstallDir: (pluginId: string) => `/tmp/${pluginId}`, PLUGIN_INSTALL_ERROR_CODE: { NPM_PACKAGE_NOT_FOUND: "npm_package_not_found", }, })); describe("updateNpmInstalledPlugins", () => { beforeEach(() => { installPluginFromNpmSpecMock.mockReset(); }); it("formats package-not-found updates with a stable message", async () => { installPluginFromNpmSpecMock.mockResolvedValue({ ok: false, code: "npm_package_not_found", error: "Package not found on npm: @openclaw/missing.", }); const { updateNpmInstalledPlugins } = await import("./update.js"); const result = await updateNpmInstalledPlugins({ config: { plugins: { installs: { missing: { source: "npm", spec: "@openclaw/missing", installPath: "/tmp/missing", }, }, }, }, pluginIds: ["missing"], dryRun: true, }); expect(result.outcomes).toEqual([ { pluginId: "missing", status: "error", message: "Failed to check missing: npm package not found for @openclaw/missing.", }, ]); }); it("falls back to raw installer error for unknown error codes", async () => { installPluginFromNpmSpecMock.mockResolvedValue({ ok: false, code: "invalid_npm_spec", error: "unsupported npm spec: github:evil/evil", }); const { updateNpmInstalledPlugins } = await import("./update.js"); const result = await updateNpmInstalledPlugins({ config: { plugins: { installs: { bad: { source: "npm", spec: "github:evil/evil", installPath: "/tmp/bad", }, }, }, }, pluginIds: ["bad"], dryRun: true, }); expect(result.outcomes).toEqual([ { pluginId: "bad", status: "error", message: "Failed to check bad: unsupported npm spec: github:evil/evil", }, ]); }); });