test: clear plugin install broad matchers

This commit is contained in:
Peter Steinberger
2026-05-10 15:01:18 +01:00
parent 5f6eb671c2
commit fdb65c035e

View File

@@ -308,6 +308,35 @@ function expectFailedInstallResult<
return params.result;
}
function expectWarningIncludes(warnings: readonly string[], fragment: string) {
expect(warnings.some((warning) => warning.includes(fragment))).toBe(true);
}
function expectWarningExcludes(warnings: readonly string[], fragment: string) {
expect(warnings.some((warning) => warning.includes(fragment))).toBe(false);
}
function requireRecord(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new Error(`expected ${label} to be an object`);
}
return value as Record<string, unknown>;
}
function requireHookPayload(handler: ReturnType<typeof vi.fn>): Record<string, unknown> {
const payload = handler.mock.calls[0]?.[0];
return requireRecord(payload, "before_install hook payload");
}
function expectHookRequest(
payload: Record<string, unknown>,
expected: { kind: string; mode: string },
) {
const request = requireRecord(payload.request, "before_install hook request");
expect(request.kind).toBe(expected.kind);
expect(request.mode).toBe(expected.mode);
}
function mockSuccessfulCommandRun(run: ReturnType<typeof vi.mocked<typeof runCommandWithTimeout>>) {
run.mockResolvedValue({
code: 0,
@@ -635,12 +664,14 @@ describe("installPluginFromArchive", () => {
});
expect(result.ok).toBe(true);
expect(vi.mocked(runCommandWithTimeout)).toHaveBeenCalledWith(
expect.arrayContaining(["npm", "install"]),
expect.objectContaining({
cwd: expect.stringContaining(".openclaw-install-stage-"),
}),
);
const commandRun = vi.mocked(runCommandWithTimeout).mock.calls[0];
expect(commandRun?.[0]).toContain("npm");
expect(commandRun?.[0]).toContain("install");
const commandOptions = commandRun?.[1];
if (!commandOptions || typeof commandOptions === "number") {
throw new Error("expected command options object");
}
expect(commandOptions.cwd).toContain(".openclaw-install-stage-");
});
it("installs scoped archives, rejects duplicate installs, and allows updates", async () => {
@@ -1142,9 +1173,7 @@ describe("installPluginFromArchive", () => {
expect(result.error).toContain('Plugin "dangerous-plugin" installation blocked');
expect(result.error).toContain("dangerous code patterns detected");
}
expect(warnings).toEqual(
expect.arrayContaining([expect.stringContaining("dangerous code pattern")]),
);
expectWarningIncludes(warnings, "dangerous code pattern");
});
it("allows package installs when dangerous scanner patterns are only in tests", async () => {
@@ -1168,9 +1197,7 @@ describe("installPluginFromArchive", () => {
const { result, warnings } = await installFromDirWithWarnings({ pluginDir, extensionsDir });
expect(result.ok).toBe(true);
expect(warnings).not.toEqual(
expect.arrayContaining([expect.stringContaining("dangerous code pattern")]),
);
expectWarningExcludes(warnings, "dangerous code pattern");
});
it("still scans declared package entrypoints when they live under test-looking paths", async () => {
@@ -2072,9 +2099,7 @@ describe("installPluginFromArchive", () => {
expect(result.code).toBe(PLUGIN_INSTALL_ERROR_CODE.SECURITY_SCAN_BLOCKED);
expect(result.error).toContain('Bundle "dangerous-bundle" installation blocked');
}
expect(warnings).toEqual(
expect.arrayContaining([expect.stringContaining("dangerous code pattern")]),
);
expectWarningIncludes(warnings, "dangerous code pattern");
});
it("allows bundle installs when dangerous scanner patterns are only in tests", async () => {
@@ -2092,9 +2117,7 @@ describe("installPluginFromArchive", () => {
const { result, warnings } = await installFromDirWithWarnings({ pluginDir, extensionsDir });
expect(result.ok).toBe(true);
expect(warnings).not.toEqual(
expect.arrayContaining([expect.stringContaining("dangerous code pattern")]),
);
expectWarningExcludes(warnings, "dangerous code pattern");
});
it("blocks bundle installs when a vendored manifest declares a blocked dependency", async () => {
@@ -2372,27 +2395,22 @@ describe("installPluginFromArchive", () => {
expect(result.ok).toBe(true);
expect(handler).toHaveBeenCalledTimes(1);
expect(handler.mock.calls[0]?.[0]).toMatchObject({
targetName: "hook-findings-plugin",
targetType: "plugin",
origin: "plugin-package",
sourcePath: pluginDir,
sourcePathKind: "directory",
request: {
kind: "plugin-dir",
mode: "install",
},
builtinScan: {
status: "ok",
findings: [],
},
plugin: {
contentType: "package",
pluginId: "hook-findings-plugin",
packageName: "hook-findings-plugin",
version: "1.0.0",
extensions: ["index.js"],
},
const payload = requireHookPayload(handler);
expect(payload.targetName).toBe("hook-findings-plugin");
expect(payload.targetType).toBe("plugin");
expect(payload.origin).toBe("plugin-package");
expect(payload.sourcePath).toBe(pluginDir);
expect(payload.sourcePathKind).toBe("directory");
expectHookRequest(payload, { kind: "plugin-dir", mode: "install" });
const builtinScan = requireRecord(payload.builtinScan, "builtin scan");
expect(builtinScan.status).toBe("ok");
expect(builtinScan.findings).toEqual([]);
expect(payload.plugin).toEqual({
contentType: "package",
pluginId: "hook-findings-plugin",
packageName: "hook-findings-plugin",
version: "1.0.0",
extensions: ["index.js"],
});
expect(handler.mock.calls[0]?.[1]).toEqual({
origin: "plugin-package",
@@ -2436,33 +2454,23 @@ describe("installPluginFromArchive", () => {
expect(result.code).toBeUndefined();
}
expect(handler).toHaveBeenCalledTimes(1);
expect(handler.mock.calls[0]?.[0]).toMatchObject({
targetName: "dangerous-blocked-plugin",
targetType: "plugin",
origin: "plugin-package",
request: {
kind: "plugin-dir",
mode: "install",
},
builtinScan: {
status: "ok",
findings: [
expect.objectContaining({
severity: "critical",
}),
],
},
plugin: {
contentType: "package",
pluginId: "dangerous-blocked-plugin",
packageName: "dangerous-blocked-plugin",
version: "1.0.0",
extensions: ["index.js"],
},
const payload = requireHookPayload(handler);
expect(payload.targetName).toBe("dangerous-blocked-plugin");
expect(payload.targetType).toBe("plugin");
expect(payload.origin).toBe("plugin-package");
expectHookRequest(payload, { kind: "plugin-dir", mode: "install" });
const builtinScan = requireRecord(payload.builtinScan, "builtin scan");
expect(builtinScan.status).toBe("ok");
const findings = builtinScan.findings as Array<{ severity?: string }>;
expect(findings.some((finding) => finding.severity === "critical")).toBe(true);
expect(payload.plugin).toEqual({
contentType: "package",
pluginId: "dangerous-blocked-plugin",
packageName: "dangerous-blocked-plugin",
version: "1.0.0",
extensions: ["index.js"],
});
expect(warnings).toEqual(
expect.arrayContaining([expect.stringContaining("dangerous code pattern")]),
);
expectWarningIncludes(warnings, "dangerous code pattern");
expect(
warnings.some((w) => w.includes("blocked by plugin hook: Blocked by enterprise policy")),
).toBe(true);
@@ -2538,12 +2546,7 @@ describe("installPluginFromArchive", () => {
expect(result.ok).toBe(true);
expect(handler).toHaveBeenCalledTimes(1);
expect(handler.mock.calls[0]?.[0]).toMatchObject({
request: {
kind: "plugin-dir",
mode: "install",
},
});
expectHookRequest(requireHookPayload(handler), { kind: "plugin-dir", mode: "install" });
});
it("reports update mode to before_install when replacing an existing target", async () => {
@@ -2576,12 +2579,7 @@ describe("installPluginFromArchive", () => {
expect(result.ok).toBe(true);
expect(handler).toHaveBeenCalledTimes(1);
expect(handler.mock.calls[0]?.[0]).toMatchObject({
request: {
kind: "plugin-dir",
mode: "update",
},
});
expectHookRequest(requireHookPayload(handler), { kind: "plugin-dir", mode: "update" });
});
it("scans extension entry files in hidden directories", async () => {
@@ -2604,12 +2602,8 @@ describe("installPluginFromArchive", () => {
const { result, warnings } = await installFromDirWithWarnings({ pluginDir, extensionsDir });
expect(result.ok).toBe(false);
expect(warnings).toEqual(
expect.arrayContaining([expect.stringContaining("hidden/node_modules path")]),
);
expect(warnings).toEqual(
expect.arrayContaining([expect.stringContaining("dangerous code pattern")]),
);
expectWarningIncludes(warnings, "hidden/node_modules path");
expectWarningIncludes(warnings, "dangerous code pattern");
});
it("blocks install when scanner throws", async () => {
@@ -2823,9 +2817,7 @@ describe("installPluginFromDir", () => {
});
expectInstalledWithPluginId(res, extensionsDir, "matrix");
expect(infoMessages).not.toEqual(
expect.arrayContaining([expect.stringContaining("differs from npm package name")]),
);
expectWarningExcludes(infoMessages, "differs from npm package name");
});
it.each([
@@ -3078,8 +3070,6 @@ describe("linkOpenClawPeerDependencies (via installPluginFromDir)", () => {
const { result, warnings } = await installFromDirWithWarnings({ pluginDir, extensionsDir });
expect(result.ok).toBe(true);
expect(warnings).toEqual(
expect.arrayContaining([expect.stringContaining("Could not locate openclaw package root")]),
);
expectWarningIncludes(warnings, "Could not locate openclaw package root");
});
});