test: tighten plugin e2e matrix coverage

This commit is contained in:
Peter Steinberger
2026-02-21 21:43:22 +00:00
parent cc2ff68947
commit 5c8f0b5a77
2 changed files with 20 additions and 25 deletions

View File

@@ -4,7 +4,7 @@ import os from "node:os";
import path from "node:path"; import path from "node:path";
import JSZip from "jszip"; import JSZip from "jszip";
import * as tar from "tar"; import * as tar from "tar";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as skillScanner from "../security/skill-scanner.js"; import * as skillScanner from "../security/skill-scanner.js";
import { import {
expectSingleNpmInstallIgnoreScriptsCall, expectSingleNpmInstallIgnoreScriptsCall,
@@ -16,6 +16,10 @@ vi.mock("../process/exec.js", () => ({
})); }));
const tempDirs: string[] = []; const tempDirs: string[] = [];
let installPluginFromArchive: typeof import("./install.js").installPluginFromArchive;
let installPluginFromDir: typeof import("./install.js").installPluginFromDir;
let installPluginFromNpmSpec: typeof import("./install.js").installPluginFromNpmSpec;
let runCommandWithTimeout: typeof import("../process/exec.js").runCommandWithTimeout;
function makeTempDir() { function makeTempDir() {
const dir = path.join(os.tmpdir(), `openclaw-plugin-install-${randomUUID()}`); const dir = path.join(os.tmpdir(), `openclaw-plugin-install-${randomUUID()}`);
@@ -120,7 +124,6 @@ function setupPluginInstallDirs() {
} }
async function installFromDirWithWarnings(params: { pluginDir: string; extensionsDir: string }) { async function installFromDirWithWarnings(params: { pluginDir: string; extensionsDir: string }) {
const { installPluginFromDir } = await import("./install.js");
const warnings: string[] = []; const warnings: string[] = [];
const result = await installPluginFromDir({ const result = await installPluginFromDir({
dirPath: params.pluginDir, dirPath: params.pluginDir,
@@ -159,7 +162,6 @@ async function expectArchiveInstallReservedSegmentRejection(params: {
}); });
const extensionsDir = path.join(stateDir, "extensions"); const extensionsDir = path.join(stateDir, "extensions");
const { installPluginFromArchive } = await import("./install.js");
const result = await installPluginFromArchive({ const result = await installPluginFromArchive({
archivePath, archivePath,
extensionsDir, extensionsDir,
@@ -182,6 +184,12 @@ afterEach(() => {
} }
}); });
beforeAll(async () => {
({ installPluginFromArchive, installPluginFromDir, installPluginFromNpmSpec } =
await import("./install.js"));
({ runCommandWithTimeout } = await import("../process/exec.js"));
});
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();
}); });
@@ -193,7 +201,6 @@ describe("installPluginFromArchive", () => {
version: "0.0.1", version: "0.0.1",
}); });
const { installPluginFromArchive } = await import("./install.js");
const result = await installPluginFromArchive({ const result = await installPluginFromArchive({
archivePath, archivePath,
extensionsDir, extensionsDir,
@@ -212,7 +219,6 @@ describe("installPluginFromArchive", () => {
version: "0.0.1", version: "0.0.1",
}); });
const { installPluginFromArchive } = await import("./install.js");
const first = await installPluginFromArchive({ const first = await installPluginFromArchive({
archivePath, archivePath,
extensionsDir, extensionsDir,
@@ -249,7 +255,6 @@ describe("installPluginFromArchive", () => {
fs.writeFileSync(archivePath, buffer); fs.writeFileSync(archivePath, buffer);
const extensionsDir = path.join(stateDir, "extensions"); const extensionsDir = path.join(stateDir, "extensions");
const { installPluginFromArchive } = await import("./install.js");
const result = await installPluginFromArchive({ const result = await installPluginFromArchive({
archivePath, archivePath,
extensionsDir, extensionsDir,
@@ -278,7 +283,6 @@ describe("installPluginFromArchive", () => {
}); });
const extensionsDir = path.join(stateDir, "extensions"); const extensionsDir = path.join(stateDir, "extensions");
const { installPluginFromArchive } = await import("./install.js");
const first = await installPluginFromArchive({ const first = await installPluginFromArchive({
archivePath: archiveV1, archivePath: archiveV1,
extensionsDir, extensionsDir,
@@ -332,7 +336,6 @@ describe("installPluginFromArchive", () => {
}); });
const extensionsDir = path.join(stateDir, "extensions"); const extensionsDir = path.join(stateDir, "extensions");
const { installPluginFromArchive } = await import("./install.js");
const result = await installPluginFromArchive({ const result = await installPluginFromArchive({
archivePath, archivePath,
extensionsDir, extensionsDir,
@@ -433,7 +436,6 @@ describe("installPluginFromDir", () => {
); );
fs.writeFileSync(path.join(pluginDir, "dist", "index.js"), "export {};", "utf-8"); fs.writeFileSync(path.join(pluginDir, "dist", "index.js"), "export {};", "utf-8");
const { runCommandWithTimeout } = await import("../process/exec.js");
const run = vi.mocked(runCommandWithTimeout); const run = vi.mocked(runCommandWithTimeout);
run.mockResolvedValue({ run.mockResolvedValue({
code: 0, code: 0,
@@ -444,7 +446,6 @@ describe("installPluginFromDir", () => {
termination: "exit", termination: "exit",
}); });
const { installPluginFromDir } = await import("./install.js");
const res = await installPluginFromDir({ const res = await installPluginFromDir({
dirPath: pluginDir, dirPath: pluginDir,
extensionsDir: path.join(stateDir, "extensions"), extensionsDir: path.join(stateDir, "extensions"),
@@ -480,7 +481,6 @@ describe("installPluginFromNpmSpec", () => {
const extensionsDir = path.join(stateDir, "extensions"); const extensionsDir = path.join(stateDir, "extensions");
fs.mkdirSync(extensionsDir, { recursive: true }); fs.mkdirSync(extensionsDir, { recursive: true });
const { runCommandWithTimeout } = await import("../process/exec.js");
const run = vi.mocked(runCommandWithTimeout); const run = vi.mocked(runCommandWithTimeout);
let packTmpDir = ""; let packTmpDir = "";
@@ -510,7 +510,6 @@ describe("installPluginFromNpmSpec", () => {
throw new Error(`unexpected command: ${argv.join(" ")}`); throw new Error(`unexpected command: ${argv.join(" ")}`);
}); });
const { installPluginFromNpmSpec } = await import("./install.js");
const result = await installPluginFromNpmSpec({ const result = await installPluginFromNpmSpec({
spec: "@openclaw/voice-call@0.0.1", spec: "@openclaw/voice-call@0.0.1",
extensionsDir, extensionsDir,
@@ -533,7 +532,6 @@ describe("installPluginFromNpmSpec", () => {
}); });
it("rejects non-registry npm specs", async () => { it("rejects non-registry npm specs", async () => {
const { installPluginFromNpmSpec } = await import("./install.js");
const result = await installPluginFromNpmSpec({ spec: "github:evil/evil" }); const result = await installPluginFromNpmSpec({ spec: "github:evil/evil" });
expect(result.ok).toBe(false); expect(result.ok).toBe(false);
if (result.ok) { if (result.ok) {
@@ -543,7 +541,6 @@ describe("installPluginFromNpmSpec", () => {
}); });
it("aborts when integrity drift callback rejects the fetched artifact", async () => { it("aborts when integrity drift callback rejects the fetched artifact", async () => {
const { runCommandWithTimeout } = await import("../process/exec.js");
const run = vi.mocked(runCommandWithTimeout); const run = vi.mocked(runCommandWithTimeout);
run.mockResolvedValue({ run.mockResolvedValue({
code: 0, code: 0,
@@ -564,7 +561,6 @@ describe("installPluginFromNpmSpec", () => {
}); });
const onIntegrityDrift = vi.fn(async () => false); const onIntegrityDrift = vi.fn(async () => false);
const { installPluginFromNpmSpec } = await import("./install.js");
const result = await installPluginFromNpmSpec({ const result = await installPluginFromNpmSpec({
spec: "@openclaw/voice-call@0.0.1", spec: "@openclaw/voice-call@0.0.1",
expectedIntegrity: "sha512-old", expectedIntegrity: "sha512-old",

View File

@@ -1,7 +1,7 @@
/** /**
* Test: after_tool_call hook wiring (pi-embedded-subscribe.handlers.tools.ts) * Test: after_tool_call hook wiring (pi-embedded-subscribe.handlers.tools.ts)
*/ */
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const hookMocks = vi.hoisted(() => ({ const hookMocks = vi.hoisted(() => ({
runner: { runner: {
@@ -58,7 +58,15 @@ function createToolHandlerCtx(params: {
}; };
} }
let handleToolExecutionStart: typeof import("../agents/pi-embedded-subscribe.handlers.tools.js").handleToolExecutionStart;
let handleToolExecutionEnd: typeof import("../agents/pi-embedded-subscribe.handlers.tools.js").handleToolExecutionEnd;
describe("after_tool_call hook wiring", () => { describe("after_tool_call hook wiring", () => {
beforeAll(async () => {
({ handleToolExecutionStart, handleToolExecutionEnd } =
await import("../agents/pi-embedded-subscribe.handlers.tools.js"));
});
beforeEach(() => { beforeEach(() => {
hookMocks.runner.hasHooks.mockReset(); hookMocks.runner.hasHooks.mockReset();
hookMocks.runner.hasHooks.mockReturnValue(false); hookMocks.runner.hasHooks.mockReturnValue(false);
@@ -71,9 +79,6 @@ describe("after_tool_call hook wiring", () => {
it("calls runAfterToolCall in handleToolExecutionEnd when hook is registered", async () => { it("calls runAfterToolCall in handleToolExecutionEnd when hook is registered", async () => {
hookMocks.runner.hasHooks.mockReturnValue(true); hookMocks.runner.hasHooks.mockReturnValue(true);
const { handleToolExecutionEnd, handleToolExecutionStart } =
await import("../agents/pi-embedded-subscribe.handlers.tools.js");
const ctx = createToolHandlerCtx({ const ctx = createToolHandlerCtx({
runId: "test-run-1", runId: "test-run-1",
agentId: "main", agentId: "main",
@@ -125,9 +130,6 @@ describe("after_tool_call hook wiring", () => {
it("includes error in after_tool_call event on tool failure", async () => { it("includes error in after_tool_call event on tool failure", async () => {
hookMocks.runner.hasHooks.mockReturnValue(true); hookMocks.runner.hasHooks.mockReturnValue(true);
const { handleToolExecutionEnd, handleToolExecutionStart } =
await import("../agents/pi-embedded-subscribe.handlers.tools.js");
const ctx = createToolHandlerCtx({ runId: "test-run-2" }); const ctx = createToolHandlerCtx({ runId: "test-run-2" });
await handleToolExecutionStart( await handleToolExecutionStart(
@@ -166,9 +168,6 @@ describe("after_tool_call hook wiring", () => {
it("does not call runAfterToolCall when no hooks registered", async () => { it("does not call runAfterToolCall when no hooks registered", async () => {
hookMocks.runner.hasHooks.mockReturnValue(false); hookMocks.runner.hasHooks.mockReturnValue(false);
const { handleToolExecutionEnd } =
await import("../agents/pi-embedded-subscribe.handlers.tools.js");
const ctx = createToolHandlerCtx({ runId: "r" }); const ctx = createToolHandlerCtx({ runId: "r" });
await handleToolExecutionEnd( await handleToolExecutionEnd(