chore(qa): cover plugin testing harness contracts (#118933)

* test(qa): cover plugin testing harness contracts

* test(qa): narrow plugin harness tool factory
This commit is contained in:
Vincent Koc
2026-08-04 09:07:27 +08:00
committed by GitHub
parent 79dac911f6
commit 84d9e93dbb
2 changed files with 142 additions and 0 deletions
@@ -0,0 +1,29 @@
title: Plugin testing harness contracts
scenario:
id: plugin-testing-harness-contracts
surface: plugins
category: plugins.testing-plugins
coverage:
primary:
- plugins.test-fixtures
- plugins.local-test-environment
- plugins.harness-contracts-tools
- plugins.unit-and-integration-scaffolds
objective: Verify the repo-local plugin test helpers provide isolated state, typed fixtures, real registry registration, tool execution, and contract diagnostics.
successCriteria:
- The temporary-home helper creates isolated OpenClaw state and restores the caller environment.
- Typed fixture cases drive an actual tool registered through the plugin registry harness.
- A virtual plugin with a declared tools contract registers and executes its tool.
- A virtual plugin without a tools contract records the canonical diagnostic and registers no tool.
docsRefs:
- docs/plugins/sdk-testing.md
codeRefs:
- src/plugin-sdk/plugin-test-contracts.ts
- src/plugin-sdk/test-env.ts
- src/plugin-sdk/test-fixtures.ts
- src/plugins/contracts/plugin-testing-harness.contract.test.ts
execution:
kind: vitest
path: src/plugins/contracts/plugin-testing-harness.contract.test.ts
summary: Run the repo-local plugin harness across isolated state, typed fixtures, tool execution, and contract rejection.
@@ -0,0 +1,113 @@
import fs from "node:fs/promises";
import path from "node:path";
import {
createPluginRegistryFixture,
registerVirtualTestPlugin,
} from "openclaw/plugin-sdk/plugin-test-contracts";
import { withTempHome } from "openclaw/plugin-sdk/test-env";
import { typedCases } from "openclaw/plugin-sdk/test-fixtures";
import { describe, expect, it } from "vitest";
const echoCases = typedCases([
{ message: "alpha", expected: "scoped:alpha" },
{ message: "beta", expected: "scoped:beta" },
]);
describe("plugin testing harness contracts", () => {
it("executes declared tools and reports missing tool contracts", async () => {
const previousHome = process.env.HOME;
const previousStateDir = process.env.OPENCLAW_STATE_DIR;
await withTempHome(async (home) => {
const stateDir = path.join(home, ".openclaw");
await expect(
fs.stat(path.join(stateDir, "agents", "main", "sessions")),
).resolves.toBeDefined();
expect(process.env.HOME).toBe(home);
expect(process.env.OPENCLAW_STATE_DIR).toBe(stateDir);
const { config, registry } = createPluginRegistryFixture({
plugins: {
entries: {
"fixture-echo": {
config: { prefix: "scoped" },
},
},
},
});
registerVirtualTestPlugin({
registry,
config,
id: "fixture-echo",
name: "Fixture Echo",
contracts: { tools: ["fixture_echo"] },
register(api) {
const prefix = api.config.plugins?.entries?.["fixture-echo"]?.config?.prefix;
if (typeof prefix !== "string") {
throw new Error("fixture prefix missing");
}
api.registerTool({
name: "fixture_echo",
label: "Fixture Echo",
description: "Echo a fixture value",
parameters: {},
execute: async (_toolCallId, params) => {
const message = (params as { message: string }).message;
return {
content: [{ type: "text", text: `${prefix}:${message}` }],
details: { home, message },
};
},
});
},
});
expect(registry.registry.tools).toHaveLength(1);
const registration = registry.registry.tools[0];
expect(registration?.pluginId).toBe("fixture-echo");
expect(registration?.names).toEqual(["fixture_echo"]);
const tool = registration?.factory({ workspaceDir: home });
if (!tool || Array.isArray(tool)) {
throw new Error("expected one registered fixture tool");
}
expect(tool.name).toBe("fixture_echo");
for (const testCase of echoCases) {
await expect(tool.execute("fixture-call", { message: testCase.message })).resolves.toEqual({
content: [{ type: "text", text: testCase.expected }],
details: { home, message: testCase.message },
});
}
expect(registry.registry.diagnostics).toEqual([]);
const missingContract = createPluginRegistryFixture();
registerVirtualTestPlugin({
registry: missingContract.registry,
config: missingContract.config,
id: "missing-contract",
name: "Missing Contract",
register(api) {
api.registerTool({
name: "fixture_echo",
label: "Fixture Echo",
description: "Echo a fixture value",
parameters: {},
execute: async () => ({ content: [], details: {} }),
});
},
});
expect(missingContract.registry.registry.tools).toEqual([]);
expect(missingContract.registry.registry.diagnostics).toContainEqual({
level: "error",
pluginId: "missing-contract",
source: "/virtual/missing-contract/index.ts",
message: "plugin must declare contracts.tools before registering agent tools",
});
});
expect(process.env.HOME).toBe(previousHome);
expect(process.env.OPENCLAW_STATE_DIR).toBe(previousStateDir);
});
});