test(config): reuse fixtures for faster validation

This commit is contained in:
Peter Steinberger
2026-03-02 09:45:52 +00:00
parent fcb956a0a2
commit fd4d157e45
5 changed files with 520 additions and 378 deletions

View File

@@ -1,7 +1,8 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterAll, describe, expect, it } from "vitest";
import { afterAll, beforeAll, describe, expect, it } from "vitest";
import { clearPluginManifestRegistryCache } from "../plugins/manifest-registry.js";
import { validateConfigObjectWithPlugins } from "./config.js";
async function writePluginFixture(params: {
@@ -31,27 +32,44 @@ async function writePluginFixture(params: {
}
describe("config plugin validation", () => {
const fixtureRoot = path.join(os.tmpdir(), "openclaw-config-plugin-validation");
let caseIndex = 0;
let fixtureRoot = "";
let suiteHome = "";
const envSnapshot = {
OPENCLAW_STATE_DIR: process.env.OPENCLAW_STATE_DIR,
OPENCLAW_PLUGIN_MANIFEST_CACHE_MS: process.env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS,
};
function createCaseHome() {
const home = path.join(fixtureRoot, `case-${caseIndex++}`);
return fs.mkdir(home, { recursive: true }).then(() => home);
}
const validateInHome = (home: string, raw: unknown) => {
process.env.OPENCLAW_STATE_DIR = path.join(home, ".openclaw");
const validateInSuite = (raw: unknown) => {
process.env.OPENCLAW_STATE_DIR = path.join(suiteHome, ".openclaw");
return validateConfigObjectWithPlugins(raw);
};
beforeAll(async () => {
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-config-plugin-validation-"));
suiteHome = path.join(fixtureRoot, "home");
await fs.mkdir(suiteHome, { recursive: true });
process.env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS = "10000";
clearPluginManifestRegistryCache();
});
afterAll(async () => {
await fs.rm(fixtureRoot, { recursive: true, force: true });
clearPluginManifestRegistryCache();
if (envSnapshot.OPENCLAW_STATE_DIR === undefined) {
delete process.env.OPENCLAW_STATE_DIR;
} else {
process.env.OPENCLAW_STATE_DIR = envSnapshot.OPENCLAW_STATE_DIR;
}
if (envSnapshot.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS === undefined) {
delete process.env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS;
} else {
process.env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS = envSnapshot.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS;
}
});
it("rejects missing plugin load paths", async () => {
const home = await createCaseHome();
const missingPath = path.join(home, "missing-plugin");
const res = validateInHome(home, {
const missingPath = path.join(suiteHome, "missing-plugin");
const res = validateInSuite({
agents: { list: [{ id: "pi" }] },
plugins: { enabled: false, load: { paths: [missingPath] } },
});
@@ -66,8 +84,7 @@ describe("config plugin validation", () => {
});
it("warns for missing plugin ids in entries instead of failing validation", async () => {
const home = await createCaseHome();
const res = validateInHome(home, {
const res = validateInSuite({
agents: { list: [{ id: "pi" }] },
plugins: { enabled: false, entries: { "missing-plugin": { enabled: true } } },
});
@@ -82,8 +99,7 @@ describe("config plugin validation", () => {
});
it("rejects missing plugin ids in allow/deny/slots", async () => {
const home = await createCaseHome();
const res = validateInHome(home, {
const res = validateInSuite({
agents: { list: [{ id: "pi" }] },
plugins: {
enabled: false,
@@ -105,9 +121,8 @@ describe("config plugin validation", () => {
});
it("warns for removed legacy plugin ids instead of failing validation", async () => {
const home = await createCaseHome();
const removedId = "google-antigravity-auth";
const res = validateInHome(home, {
const res = validateInSuite({
agents: { list: [{ id: "pi" }] },
plugins: {
enabled: false,
@@ -147,8 +162,7 @@ describe("config plugin validation", () => {
});
it("surfaces plugin config diagnostics", async () => {
const home = await createCaseHome();
const pluginDir = path.join(home, "bad-plugin");
const pluginDir = path.join(suiteHome, "bad-plugin");
await writePluginFixture({
dir: pluginDir,
id: "bad-plugin",
@@ -162,7 +176,7 @@ describe("config plugin validation", () => {
},
});
const res = validateInHome(home, {
const res = validateInSuite({
agents: { list: [{ id: "pi" }] },
plugins: {
enabled: true,
@@ -182,8 +196,7 @@ describe("config plugin validation", () => {
});
it("accepts known plugin ids", async () => {
const home = await createCaseHome();
const res = validateInHome(home, {
const res = validateInSuite({
agents: { list: [{ id: "pi" }] },
plugins: { enabled: false, entries: { discord: { enabled: true } } },
});
@@ -191,8 +204,7 @@ describe("config plugin validation", () => {
});
it("accepts channels.modelByChannel", async () => {
const home = await createCaseHome();
const res = validateInHome(home, {
const res = validateInSuite({
agents: { list: [{ id: "pi" }] },
channels: {
modelByChannel: {
@@ -206,8 +218,7 @@ describe("config plugin validation", () => {
});
it("accepts plugin heartbeat targets", async () => {
const home = await createCaseHome();
const pluginDir = path.join(home, "bluebubbles-plugin");
const pluginDir = path.join(suiteHome, "bluebubbles-plugin");
await writePluginFixture({
dir: pluginDir,
id: "bluebubbles-plugin",
@@ -215,7 +226,7 @@ describe("config plugin validation", () => {
schema: { type: "object" },
});
const res = validateInHome(home, {
const res = validateInSuite({
agents: { defaults: { heartbeat: { target: "bluebubbles" } }, list: [{ id: "pi" }] },
plugins: { enabled: false, load: { paths: [pluginDir] } },
});
@@ -223,8 +234,7 @@ describe("config plugin validation", () => {
});
it("rejects unknown heartbeat targets", async () => {
const home = await createCaseHome();
const res = validateInHome(home, {
const res = validateInSuite({
agents: { defaults: { heartbeat: { target: "not-a-channel" } }, list: [{ id: "pi" }] },
});
expect(res.ok).toBe(false);
@@ -237,8 +247,7 @@ describe("config plugin validation", () => {
});
it("accepts heartbeat directPolicy enum values", async () => {
const home = await createCaseHome();
const res = validateInHome(home, {
const res = validateInSuite({
agents: {
defaults: { heartbeat: { target: "last", directPolicy: "block" } },
list: [{ id: "pi", heartbeat: { directPolicy: "allow" } }],
@@ -248,8 +257,7 @@ describe("config plugin validation", () => {
});
it("rejects invalid heartbeat directPolicy values", async () => {
const home = await createCaseHome();
const res = validateInHome(home, {
const res = validateInSuite({
agents: {
defaults: { heartbeat: { directPolicy: "maybe" } },
list: [{ id: "pi" }],