mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:30:44 +00:00
test: harden plugin update validation
This commit is contained in:
@@ -5,6 +5,15 @@ function writePluginManifest(file, id) {
|
||||
writeJson(file, { id, configSchema: { type: "object", properties: {} } });
|
||||
}
|
||||
|
||||
function writeFakeIsNumberPackage(dir) {
|
||||
writeJson(path.join(dir, "package.json"), {
|
||||
name: "is-number",
|
||||
version: "7.0.0",
|
||||
main: "index.js",
|
||||
});
|
||||
write(path.join(dir, "index.js"), "module.exports = (value) => typeof value === 'number';\n");
|
||||
}
|
||||
|
||||
function writePluginDemo([dir]) {
|
||||
write(
|
||||
path.join(requireArg(dir, "dir"), "index.js"),
|
||||
@@ -35,6 +44,22 @@ function writePlugin([dir, id, version, method, name]) {
|
||||
writePluginManifest(path.join(dir, "openclaw.plugin.json"), id);
|
||||
}
|
||||
|
||||
function writePluginWithVendoredDependency([dir, id, version, method, name]) {
|
||||
writePlugin([dir, id, version, method, name]);
|
||||
const packageJsonPath = path.join(dir, "package.json");
|
||||
writeJson(packageJsonPath, {
|
||||
name: `@openclaw/${id}`,
|
||||
version,
|
||||
dependencies: { "is-number": "7.0.0" },
|
||||
openclaw: { extensions: ["./index.js"] },
|
||||
});
|
||||
write(
|
||||
path.join(dir, "index.js"),
|
||||
`const isNumber = require("is-number");\nmodule.exports = { id: ${JSON.stringify(id)}, name: ${JSON.stringify(name)}, register(api) { api.registerGatewayMethod(${JSON.stringify(method)}, async () => ({ ok: isNumber(42) })); }, };\n`,
|
||||
);
|
||||
writeFakeIsNumberPackage(path.join(dir, "node_modules", "is-number"));
|
||||
}
|
||||
|
||||
function writePluginWithCli([dir, id, version, method, name, cliRoot, cliOutput]) {
|
||||
for (const [value, label] of [
|
||||
[dir, "dir"],
|
||||
@@ -50,11 +75,13 @@ function writePluginWithCli([dir, id, version, method, name, cliRoot, cliOutput]
|
||||
writeJson(path.join(dir, "package.json"), {
|
||||
name: `@openclaw/${id}`,
|
||||
version,
|
||||
dependencies: { "is-number": "file:./deps/is-number" },
|
||||
openclaw: { extensions: ["./index.js"] },
|
||||
});
|
||||
writeFakeIsNumberPackage(path.join(dir, "deps", "is-number"));
|
||||
write(
|
||||
path.join(dir, "index.js"),
|
||||
`module.exports = { id: ${JSON.stringify(id)}, name: ${JSON.stringify(name)}, register(api) { api.registerGatewayMethod(${JSON.stringify(method)}, async () => ({ ok: true })); api.registerCli(({ program }) => { const root = program.command(${JSON.stringify(cliRoot)}).description(${JSON.stringify(`${name} fixture command`)}); root.command("ping").description("Print fixture ping output").action(() => { console.log(${JSON.stringify(cliOutput)}); }); }, { descriptors: [{ name: ${JSON.stringify(cliRoot)}, description: ${JSON.stringify(`${name} fixture command`)}, hasSubcommands: true }] }); }, };\n`,
|
||||
`const isNumber = require("is-number");\nmodule.exports = { id: ${JSON.stringify(id)}, name: ${JSON.stringify(name)}, register(api) { api.registerGatewayMethod(${JSON.stringify(method)}, async () => ({ ok: isNumber(42) })); api.registerCli(({ program }) => { const root = program.command(${JSON.stringify(cliRoot)}).description(${JSON.stringify(`${name} fixture command`)}); root.command("ping").description("Print fixture ping output").action(() => { console.log(${JSON.stringify(cliOutput)}); }); }, { descriptors: [{ name: ${JSON.stringify(cliRoot)}, description: ${JSON.stringify(`${name} fixture command`)}, hasSubcommands: true }] }); }, };\n`,
|
||||
);
|
||||
writePluginManifest(path.join(dir, "openclaw.plugin.json"), id);
|
||||
}
|
||||
@@ -99,6 +126,7 @@ function writePluginMarketplace([root]) {
|
||||
export const pluginCommands = {
|
||||
"plugin-demo": writePluginDemo,
|
||||
plugin: writePlugin,
|
||||
"plugin-vendored-dep": writePluginWithVendoredDependency,
|
||||
"plugin-cli": writePluginWithCli,
|
||||
"plugin-manifest": ([file, id]) =>
|
||||
writePluginManifest(requireArg(file, "file"), requireArg(id, "id")),
|
||||
|
||||
@@ -258,6 +258,11 @@ function assertGitPlugin() {
|
||||
throw new Error(`git install path should point at cloned repo root: ${installPath}`);
|
||||
}
|
||||
assertRealPathInside(gitRoot, installPath, "git install path");
|
||||
const dependencyPackagePath = path.join(installPath, "node_modules", "is-number", "package.json");
|
||||
if (!fs.existsSync(dependencyPackagePath)) {
|
||||
throw new Error(`missing git plugin installed dependency: ${dependencyPackagePath}`);
|
||||
}
|
||||
assertRealPathInside(installPath, dependencyPackagePath, "git plugin installed dependency");
|
||||
}
|
||||
|
||||
function assertRealPathInside(parentPath, childPath, label) {
|
||||
@@ -292,6 +297,36 @@ function assertClawHubExternalInstallContract(installPath) {
|
||||
assertRealPathInside(installPath, dependencyPackagePath, "ClawHub isolated dependency");
|
||||
}
|
||||
|
||||
function assertPluginDirDeps() {
|
||||
const sourceDir = process.argv[3];
|
||||
assertSimplePlugin(
|
||||
"/tmp/plugins-dir-deps.json",
|
||||
"/tmp/plugins-dir-deps-inspect.json",
|
||||
"demo-plugin-dir-deps",
|
||||
"demo.dir.deps",
|
||||
);
|
||||
|
||||
const record = getInstallRecords()["demo-plugin-dir-deps"];
|
||||
if (!record) {
|
||||
throw new Error("missing local dependency plugin install record");
|
||||
}
|
||||
if (record.source !== "path") {
|
||||
throw new Error(`unexpected local dependency plugin source: ${record.source}`);
|
||||
}
|
||||
if (record.sourcePath !== sourceDir) {
|
||||
throw new Error(`unexpected local dependency plugin source path: ${record.sourcePath}`);
|
||||
}
|
||||
const installPath = record.installPath?.replace(/^~(?=$|\/)/u, process.env.HOME);
|
||||
if (!installPath || !fs.existsSync(installPath)) {
|
||||
throw new Error(`local dependency plugin install path missing on disk: ${installPath}`);
|
||||
}
|
||||
const dependencyPackagePath = path.join(installPath, "node_modules", "is-number", "package.json");
|
||||
if (!fs.existsSync(dependencyPackagePath)) {
|
||||
throw new Error(`missing copied local plugin dependency: ${dependencyPackagePath}`);
|
||||
}
|
||||
assertRealPathInside(installPath, dependencyPackagePath, "local plugin copied dependency");
|
||||
}
|
||||
|
||||
function assertMarketplaceUpdated() {
|
||||
const data = readJson("/tmp/plugins-marketplace-updated.json");
|
||||
const inspect = readJson("/tmp/plugins-marketplace-updated-inspect.json");
|
||||
@@ -459,6 +494,7 @@ const commands = {
|
||||
"demo-plugin-dir",
|
||||
"demo.dir",
|
||||
),
|
||||
"plugin-dir-deps": assertPluginDirDeps,
|
||||
"plugin-file": () =>
|
||||
assertSimplePlugin(
|
||||
"/tmp/plugins4.json",
|
||||
|
||||
@@ -32,6 +32,16 @@ write_fixture_plugin_with_cli() {
|
||||
node scripts/e2e/lib/fixture.mjs plugin-cli "$dir" "$id" "$version" "$method" "$name" "$cli_root" "$cli_output"
|
||||
}
|
||||
|
||||
write_fixture_plugin_with_vendored_dependency() {
|
||||
local dir="$1"
|
||||
local id="$2"
|
||||
local version="$3"
|
||||
local method="$4"
|
||||
local name="$5"
|
||||
|
||||
node scripts/e2e/lib/fixture.mjs plugin-vendored-dep "$dir" "$id" "$version" "$method" "$name"
|
||||
}
|
||||
|
||||
write_fixture_manifest() {
|
||||
local file="$1"
|
||||
local id="$2"
|
||||
|
||||
@@ -46,6 +46,16 @@ node "$OPENCLAW_ENTRY" plugins inspect demo-plugin-dir --runtime --json >/tmp/pl
|
||||
|
||||
node scripts/e2e/lib/plugins/assertions.mjs plugin-dir
|
||||
|
||||
echo "Testing install from local folder with preinstalled dependencies..."
|
||||
dir_deps_plugin="$(mktemp -d "/tmp/openclaw-plugin-dir-deps.XXXXXX")"
|
||||
write_fixture_plugin_with_vendored_dependency "$dir_deps_plugin" demo-plugin-dir-deps 0.0.1 demo.dir.deps "Demo Plugin DIR Deps"
|
||||
|
||||
run_logged install-dir-deps node "$OPENCLAW_ENTRY" plugins install "$dir_deps_plugin"
|
||||
node "$OPENCLAW_ENTRY" plugins list --json >/tmp/plugins-dir-deps.json
|
||||
node "$OPENCLAW_ENTRY" plugins inspect demo-plugin-dir-deps --runtime --json >/tmp/plugins-dir-deps-inspect.json
|
||||
|
||||
node scripts/e2e/lib/plugins/assertions.mjs plugin-dir-deps "$dir_deps_plugin"
|
||||
|
||||
echo "Testing install from npm spec (file:)..."
|
||||
file_pack_dir="$(mktemp -d "/tmp/openclaw-plugin-filepack.XXXXXX")"
|
||||
write_fixture_plugin "$file_pack_dir/package" demo-plugin-file 0.0.1 demo.file "Demo Plugin FILE"
|
||||
|
||||
Reference in New Issue
Block a user