mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
test: isolate facade bundled fixture roots
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
clearBundledRuntimeDependencyNodePaths,
|
||||
resolveBundledRuntimeDependencyInstallRoot,
|
||||
@@ -15,19 +15,17 @@ import {
|
||||
setFacadeLoaderJitiFactoryForTest,
|
||||
} from "./facade-loader.js";
|
||||
import { listImportedBundledPluginFacadeIds as listImportedFacadeRuntimeIds } from "./facade-runtime.js";
|
||||
import {
|
||||
createBundledPluginPublicSurfaceFixture,
|
||||
createPluginSdkTestHarness,
|
||||
createThrowingBundledPluginPublicSurfaceFixture,
|
||||
} from "./test-helpers.js";
|
||||
import { createPluginSdkTestHarness } from "./test-helpers.js";
|
||||
|
||||
const { createTempDirSync } = createPluginSdkTestHarness();
|
||||
const originalBundledPluginsDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
const originalDisableBundledPlugins = process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS;
|
||||
const originalPluginStageDir = process.env.OPENCLAW_PLUGIN_STAGE_DIR;
|
||||
const trustedBundledFixturesRoot = path.resolve("dist-runtime", "extensions");
|
||||
const FACADE_LOADER_GLOBAL = "__openclawTestLoadBundledPluginPublicSurfaceModuleSync";
|
||||
const STAGED_RUNTIME_DEP_NAME = "openclaw-facade-loader-runtime-dep";
|
||||
type FacadeLoaderJitiFactory = NonNullable<Parameters<typeof setFacadeLoaderJitiFactoryForTest>[0]>;
|
||||
const trustedBundledFixtureDirs: string[] = [];
|
||||
|
||||
function forceNodeRuntimeVersionsForTest(): () => void {
|
||||
const originalVersions = process.versions;
|
||||
@@ -47,17 +45,52 @@ function forceNodeRuntimeVersionsForTest(): () => void {
|
||||
};
|
||||
}
|
||||
|
||||
function createTrustedBundledFixtureRoot(prefix: string): string {
|
||||
fs.mkdirSync(trustedBundledFixturesRoot, { recursive: true });
|
||||
const rootDir = fs.mkdtempSync(path.join(trustedBundledFixturesRoot, `.${prefix}`));
|
||||
trustedBundledFixtureDirs.push(rootDir);
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
function writePluginPackageJson(pluginDir: string, name = "demo"): void {
|
||||
writeJsonFile(path.join(pluginDir, "package.json"), {
|
||||
name: `@openclaw/plugin-${name}`,
|
||||
version: "0.0.0",
|
||||
type: "module",
|
||||
});
|
||||
}
|
||||
|
||||
function createBundledPluginDir(prefix: string, marker: string): string {
|
||||
return createBundledPluginPublicSurfaceFixture({ createTempDirSync, marker, prefix });
|
||||
const rootDir = createTrustedBundledFixtureRoot(prefix);
|
||||
const pluginDir = path.join(rootDir, "demo");
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
writePluginPackageJson(pluginDir);
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "api.js"),
|
||||
`export const marker = ${JSON.stringify(marker)};\n`,
|
||||
"utf8",
|
||||
);
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
function createThrowingPluginDir(prefix: string): string {
|
||||
return createThrowingBundledPluginPublicSurfaceFixture({ createTempDirSync, prefix });
|
||||
const rootDir = createTrustedBundledFixtureRoot(prefix);
|
||||
const pluginDir = path.join(rootDir, "bad");
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
writePluginPackageJson(pluginDir, "bad");
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "api.js"),
|
||||
`throw new Error("plugin load failure");\n`,
|
||||
"utf8",
|
||||
);
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
function createCircularPluginDir(prefix: string): string {
|
||||
const rootDir = createTempDirSync(prefix);
|
||||
fs.mkdirSync(path.join(rootDir, "demo"), { recursive: true });
|
||||
const rootDir = createTrustedBundledFixtureRoot(prefix);
|
||||
const pluginDir = path.join(rootDir, "demo");
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
writePluginPackageJson(pluginDir);
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, "facade.mjs"),
|
||||
[
|
||||
@@ -71,14 +104,14 @@ function createCircularPluginDir(prefix: string): string {
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, "demo", "helper.js"),
|
||||
path.join(pluginDir, "helper.js"),
|
||||
['import { marker } from "../facade.mjs";', "export const circularMarker = marker;", ""].join(
|
||||
"\n",
|
||||
),
|
||||
"utf8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, "demo", "api.js"),
|
||||
path.join(pluginDir, "api.js"),
|
||||
['import "./helper.js";', 'export const marker = "circular-ok";', ""].join("\n"),
|
||||
"utf8",
|
||||
);
|
||||
@@ -102,21 +135,17 @@ function createPackagedBundledPluginDirWithStagedRuntimeDep(params: {
|
||||
pluginRoot: string;
|
||||
stageRoot: string;
|
||||
} {
|
||||
const packageRoot = createTempDirSync(params.prefix);
|
||||
const pluginRoot = path.join(packageRoot, "dist", "extensions", "demo");
|
||||
const stageRoot = path.join(packageRoot, "stage");
|
||||
const packageRoot = path.resolve(".");
|
||||
const pluginRoot = path.join(trustedBundledFixturesRoot, "demo");
|
||||
const stageRoot = createTempDirSync(`${params.prefix}stage-`);
|
||||
const env = {
|
||||
...process.env,
|
||||
OPENCLAW_BUNDLED_PLUGINS_DIR: path.join(packageRoot, "dist", "extensions"),
|
||||
OPENCLAW_BUNDLED_PLUGINS_DIR: trustedBundledFixturesRoot,
|
||||
OPENCLAW_PLUGIN_STAGE_DIR: stageRoot,
|
||||
};
|
||||
trustedBundledFixtureDirs.push(pluginRoot);
|
||||
fs.mkdirSync(pluginRoot, { recursive: true });
|
||||
|
||||
writeJsonFile(path.join(packageRoot, "package.json"), {
|
||||
name: "openclaw",
|
||||
version: "0.0.0",
|
||||
type: "module",
|
||||
});
|
||||
writeJsonFile(path.join(pluginRoot, "package.json"), {
|
||||
name: "@openclaw/plugin-demo",
|
||||
version: "0.0.0",
|
||||
@@ -154,7 +183,7 @@ function createPackagedBundledPluginDirWithStagedRuntimeDep(params: {
|
||||
);
|
||||
|
||||
return {
|
||||
bundledPluginsDir: path.join(packageRoot, "dist", "extensions"),
|
||||
bundledPluginsDir: trustedBundledFixturesRoot,
|
||||
env,
|
||||
installRoot,
|
||||
modulePath,
|
||||
@@ -163,8 +192,18 @@ function createPackagedBundledPluginDirWithStagedRuntimeDep(params: {
|
||||
stageRoot,
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
delete process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS;
|
||||
delete process.env.OPENCLAW_PLUGIN_STAGE_DIR;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
for (const dir of trustedBundledFixtureDirs.splice(0)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
resetFacadeLoaderStateForTest();
|
||||
setFacadeLoaderJitiFactoryForTest(undefined);
|
||||
clearBundledRuntimeDependencyNodePaths();
|
||||
@@ -187,7 +226,7 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("plugin-sdk facade loader", () => {
|
||||
it("honors bundled plugin dir overrides outside the package root", () => {
|
||||
it("honors trusted bundled plugin dir overrides", () => {
|
||||
const overrideA = createBundledPluginDir("openclaw-facade-loader-a-", "override-a");
|
||||
const overrideB = createBundledPluginDir("openclaw-facade-loader-b-", "override-b");
|
||||
|
||||
@@ -251,11 +290,14 @@ describe("plugin-sdk facade loader", () => {
|
||||
});
|
||||
|
||||
it("uses the runtime-supported Jiti boundary for Windows dist facade loads", () => {
|
||||
const dir = createTempDirSync("openclaw-facade-loader-windows-dist-");
|
||||
const bundledPluginsDir = path.join(dir, "dist");
|
||||
fs.mkdirSync(path.join(bundledPluginsDir, "demo"), { recursive: true });
|
||||
const bundledPluginsDir = createTrustedBundledFixtureRoot(
|
||||
"openclaw-facade-loader-windows-dist-",
|
||||
);
|
||||
const pluginDir = path.join(bundledPluginsDir, "demo");
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
writePluginPackageJson(pluginDir);
|
||||
fs.writeFileSync(
|
||||
path.join(bundledPluginsDir, "demo", "api.js"),
|
||||
path.join(pluginDir, "api.js"),
|
||||
'export const marker = "windows-dist-ok";\n',
|
||||
"utf8",
|
||||
);
|
||||
@@ -314,13 +356,15 @@ describe("plugin-sdk facade loader", () => {
|
||||
expect(loaded.marker).toBe("facade:staged");
|
||||
expect(fs.existsSync(path.join(fixture.pluginRoot, "node_modules"))).toBe(false);
|
||||
expect(fs.realpathSync(fileURLToPath(loaded.moduleUrl))).toBe(
|
||||
fs.realpathSync(path.join(fixture.installRoot, "dist", "extensions", "demo", "api.js")),
|
||||
fs.realpathSync(
|
||||
path.join(fixture.installRoot, "dist-runtime", "extensions", "demo", "api.js"),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("loads built bundled async public surfaces through staged runtime deps", async () => {
|
||||
const fixture = createPackagedBundledPluginDirWithStagedRuntimeDep({
|
||||
marker: "async-staged",
|
||||
marker: "staged",
|
||||
prefix: "openclaw-facade-loader-built-async-",
|
||||
});
|
||||
|
||||
@@ -333,9 +377,11 @@ describe("plugin-sdk facade loader", () => {
|
||||
env: fixture.env,
|
||||
});
|
||||
|
||||
expect(loaded.marker).toBe("facade:async-staged");
|
||||
expect(loaded.marker).toBe("facade:staged");
|
||||
expect(fs.realpathSync(fileURLToPath(loaded.moduleUrl))).toBe(
|
||||
fs.realpathSync(path.join(fixture.installRoot, "dist", "extensions", "demo", "api.js")),
|
||||
fs.realpathSync(
|
||||
path.join(fixture.installRoot, "dist-runtime", "extensions", "demo", "api.js"),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { clearRuntimeConfigSnapshot, setRuntimeConfigSnapshot } from "../config/config.js";
|
||||
import { createPluginActivationSource, normalizePluginsConfig } from "../plugins/config-state.js";
|
||||
import { clearPluginDiscoveryCache } from "../plugins/discovery.js";
|
||||
@@ -17,27 +17,72 @@ import {
|
||||
loadBundledPluginPublicSurfaceModuleSync,
|
||||
resetFacadeRuntimeStateForTest,
|
||||
} from "./facade-runtime.js";
|
||||
import {
|
||||
createBundledPluginPublicSurfaceFixture,
|
||||
createPluginSdkTestHarness,
|
||||
createThrowingBundledPluginPublicSurfaceFixture,
|
||||
} from "./test-helpers.js";
|
||||
import { createPluginSdkTestHarness } from "./test-helpers.js";
|
||||
|
||||
const { createTempDirSync } = createPluginSdkTestHarness();
|
||||
const originalBundledPluginsDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
const originalDisableBundledPlugins = process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS;
|
||||
const originalStateDir = process.env.OPENCLAW_STATE_DIR;
|
||||
const trustedBundledFixturesRoot = path.resolve("dist-runtime", "extensions");
|
||||
const trustedBundledFixtureDirs: string[] = [];
|
||||
|
||||
function writeJsonFile(filePath: string, value: unknown): void {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
||||
}
|
||||
|
||||
function createTrustedBundledFixtureRoot(prefix: string): string {
|
||||
fs.mkdirSync(trustedBundledFixturesRoot, { recursive: true });
|
||||
const rootDir = fs.mkdtempSync(path.join(trustedBundledFixturesRoot, `.${prefix}`));
|
||||
trustedBundledFixtureDirs.push(rootDir);
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
function writePluginPackageJson(pluginDir: string, name = "demo"): void {
|
||||
writeJsonFile(path.join(pluginDir, "package.json"), {
|
||||
name: `@openclaw/plugin-${name}`,
|
||||
version: "0.0.0",
|
||||
type: "module",
|
||||
});
|
||||
}
|
||||
|
||||
function createBundledPluginDir(prefix: string, marker: string): string {
|
||||
return createBundledPluginPublicSurfaceFixture({ createTempDirSync, marker, prefix });
|
||||
const rootDir = createTrustedBundledFixtureRoot(prefix);
|
||||
const pluginDir = path.join(rootDir, "demo");
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
writePluginPackageJson(pluginDir);
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "api.js"),
|
||||
`export const marker = ${JSON.stringify(marker)};\n`,
|
||||
"utf8",
|
||||
);
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
function createThrowingPluginDir(prefix: string): string {
|
||||
return createThrowingBundledPluginPublicSurfaceFixture({ createTempDirSync, prefix });
|
||||
const rootDir = createTrustedBundledFixtureRoot(prefix);
|
||||
const pluginDir = path.join(rootDir, "bad");
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
writePluginPackageJson(pluginDir, "bad");
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "api.js"),
|
||||
`throw new Error("plugin load failure");\n`,
|
||||
"utf8",
|
||||
);
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
delete process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS;
|
||||
delete process.env.OPENCLAW_STATE_DIR;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
for (const dir of trustedBundledFixtureDirs.splice(0)) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
clearRuntimeConfigSnapshot();
|
||||
resetFacadeRuntimeStateForTest();
|
||||
resetFacadeActivationCheckRuntimeStateForTest();
|
||||
@@ -62,7 +107,7 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("plugin-sdk facade runtime", () => {
|
||||
it("honors bundled plugin dir overrides outside the package root", () => {
|
||||
it("honors trusted bundled plugin dir overrides", () => {
|
||||
const overrideA = createBundledPluginDir("openclaw-facade-runtime-a-", "override-a");
|
||||
const overrideB = createBundledPluginDir("openclaw-facade-runtime-b-", "override-b");
|
||||
|
||||
@@ -88,7 +133,10 @@ describe("plugin-sdk facade runtime", () => {
|
||||
});
|
||||
|
||||
it("falls back to package source surfaces when an override dir is partial", () => {
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = createTempDirSync("openclaw-facade-runtime-empty-");
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = createBundledPluginDir(
|
||||
"openclaw-facade-runtime-partial-",
|
||||
"partial",
|
||||
);
|
||||
|
||||
expect(
|
||||
__testing.resolveFacadeModuleLocation({
|
||||
|
||||
Reference in New Issue
Block a user