mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 00:20:22 +00:00
test(plugins): reuse suite temp root helper in install fixture tests
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
|||||||
PLUGIN_INSTALL_ERROR_CODE,
|
PLUGIN_INSTALL_ERROR_CODE,
|
||||||
resolvePluginInstallDir,
|
resolvePluginInstallDir,
|
||||||
} from "./install.js";
|
} from "./install.js";
|
||||||
|
import { createSuiteTempRootTracker } from "./test-helpers/fs-fixtures.js";
|
||||||
|
|
||||||
vi.mock("../process/exec.js", () => ({
|
vi.mock("../process/exec.js", () => ({
|
||||||
runCommandWithTimeout: vi.fn(),
|
runCommandWithTimeout: vi.fn(),
|
||||||
@@ -41,14 +42,13 @@ vi.mock("./install.runtime.js", async () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
let suiteTempRoot = "";
|
|
||||||
let suiteFixtureRoot = "";
|
let suiteFixtureRoot = "";
|
||||||
let tempDirCounter = 0;
|
|
||||||
const pluginFixturesDir = path.resolve(process.cwd(), "test", "fixtures", "plugins-install");
|
const pluginFixturesDir = path.resolve(process.cwd(), "test", "fixtures", "plugins-install");
|
||||||
const archiveFixturePathCache = new Map<string, string>();
|
const archiveFixturePathCache = new Map<string, string>();
|
||||||
const dynamicArchiveTemplatePathCache = new Map<string, string>();
|
const dynamicArchiveTemplatePathCache = new Map<string, string>();
|
||||||
let installPluginFromDirTemplateDir = "";
|
let installPluginFromDirTemplateDir = "";
|
||||||
let manifestInstallTemplateDir = "";
|
let manifestInstallTemplateDir = "";
|
||||||
|
const suiteTempRootTracker = createSuiteTempRootTracker("openclaw-plugin-install");
|
||||||
const DYNAMIC_ARCHIVE_TEMPLATE_PRESETS = [
|
const DYNAMIC_ARCHIVE_TEMPLATE_PRESETS = [
|
||||||
{
|
{
|
||||||
outName: "traversal.tgz",
|
outName: "traversal.tgz",
|
||||||
@@ -78,28 +78,11 @@ const DYNAMIC_ARCHIVE_TEMPLATE_PRESETS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function ensureSuiteTempRoot() {
|
|
||||||
if (suiteTempRoot) {
|
|
||||||
return suiteTempRoot;
|
|
||||||
}
|
|
||||||
const bundleTempRoot = path.join(process.cwd(), ".tmp");
|
|
||||||
fs.mkdirSync(bundleTempRoot, { recursive: true });
|
|
||||||
suiteTempRoot = fs.mkdtempSync(path.join(bundleTempRoot, "openclaw-plugin-install-"));
|
|
||||||
return suiteTempRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeTempDir() {
|
|
||||||
const dir = path.join(ensureSuiteTempRoot(), `case-${String(tempDirCounter)}`);
|
|
||||||
tempDirCounter += 1;
|
|
||||||
fs.mkdirSync(dir);
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureSuiteFixtureRoot() {
|
function ensureSuiteFixtureRoot() {
|
||||||
if (suiteFixtureRoot) {
|
if (suiteFixtureRoot) {
|
||||||
return suiteFixtureRoot;
|
return suiteFixtureRoot;
|
||||||
}
|
}
|
||||||
suiteFixtureRoot = path.join(ensureSuiteTempRoot(), "_fixtures");
|
suiteFixtureRoot = path.join(suiteTempRootTracker.ensureSuiteTempRoot(), "_fixtures");
|
||||||
fs.mkdirSync(suiteFixtureRoot, { recursive: true });
|
fs.mkdirSync(suiteFixtureRoot, { recursive: true });
|
||||||
return suiteFixtureRoot;
|
return suiteFixtureRoot;
|
||||||
}
|
}
|
||||||
@@ -178,7 +161,7 @@ function expectSuccessfulArchiveInstall(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupPluginInstallDirs() {
|
function setupPluginInstallDirs() {
|
||||||
const tmpDir = makeTempDir();
|
const tmpDir = suiteTempRootTracker.makeTempDir();
|
||||||
const pluginDir = path.join(tmpDir, "plugin-src");
|
const pluginDir = path.join(tmpDir, "plugin-src");
|
||||||
const extensionsDir = path.join(tmpDir, "extensions");
|
const extensionsDir = path.join(tmpDir, "extensions");
|
||||||
fs.mkdirSync(pluginDir, { recursive: true });
|
fs.mkdirSync(pluginDir, { recursive: true });
|
||||||
@@ -187,7 +170,7 @@ function setupPluginInstallDirs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupInstallPluginFromDirFixture(params?: { devDependencies?: Record<string, string> }) {
|
function setupInstallPluginFromDirFixture(params?: { devDependencies?: Record<string, string> }) {
|
||||||
const caseDir = makeTempDir();
|
const caseDir = suiteTempRootTracker.makeTempDir();
|
||||||
const stateDir = path.join(caseDir, "state");
|
const stateDir = path.join(caseDir, "state");
|
||||||
const pluginDir = path.join(caseDir, "plugin");
|
const pluginDir = path.join(caseDir, "plugin");
|
||||||
fs.mkdirSync(stateDir, { recursive: true });
|
fs.mkdirSync(stateDir, { recursive: true });
|
||||||
@@ -242,7 +225,7 @@ async function installFromArchiveWithWarnings(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupManifestInstallFixture(params: { manifestId: string; packageName?: string }) {
|
function setupManifestInstallFixture(params: { manifestId: string; packageName?: string }) {
|
||||||
const caseDir = makeTempDir();
|
const caseDir = suiteTempRootTracker.makeTempDir();
|
||||||
const stateDir = path.join(caseDir, "state");
|
const stateDir = path.join(caseDir, "state");
|
||||||
const pluginDir = path.join(caseDir, "plugin-src");
|
const pluginDir = path.join(caseDir, "plugin-src");
|
||||||
fs.mkdirSync(stateDir, { recursive: true });
|
fs.mkdirSync(stateDir, { recursive: true });
|
||||||
@@ -319,7 +302,7 @@ function setupBundleInstallFixture(params: {
|
|||||||
bundleFormat: "codex" | "claude" | "cursor";
|
bundleFormat: "codex" | "claude" | "cursor";
|
||||||
name: string;
|
name: string;
|
||||||
}) {
|
}) {
|
||||||
const caseDir = makeTempDir();
|
const caseDir = suiteTempRootTracker.makeTempDir();
|
||||||
const stateDir = path.join(caseDir, "state");
|
const stateDir = path.join(caseDir, "state");
|
||||||
const pluginDir = path.join(caseDir, "plugin-src");
|
const pluginDir = path.join(caseDir, "plugin-src");
|
||||||
fs.mkdirSync(stateDir, { recursive: true });
|
fs.mkdirSync(stateDir, { recursive: true });
|
||||||
@@ -359,7 +342,7 @@ function setupBundleInstallFixture(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupManifestlessClaudeInstallFixture() {
|
function setupManifestlessClaudeInstallFixture() {
|
||||||
const caseDir = makeTempDir();
|
const caseDir = suiteTempRootTracker.makeTempDir();
|
||||||
const stateDir = path.join(caseDir, "state");
|
const stateDir = path.join(caseDir, "state");
|
||||||
const pluginDir = path.join(caseDir, "claude-manifestless");
|
const pluginDir = path.join(caseDir, "claude-manifestless");
|
||||||
fs.mkdirSync(stateDir, { recursive: true });
|
fs.mkdirSync(stateDir, { recursive: true });
|
||||||
@@ -374,7 +357,7 @@ function setupManifestlessClaudeInstallFixture() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupDualFormatInstallFixture(params: { bundleFormat: "codex" | "claude" }) {
|
function setupDualFormatInstallFixture(params: { bundleFormat: "codex" | "claude" }) {
|
||||||
const caseDir = makeTempDir();
|
const caseDir = suiteTempRootTracker.makeTempDir();
|
||||||
const stateDir = path.join(caseDir, "state");
|
const stateDir = path.join(caseDir, "state");
|
||||||
const pluginDir = path.join(caseDir, "plugin-src");
|
const pluginDir = path.join(caseDir, "plugin-src");
|
||||||
fs.mkdirSync(path.join(pluginDir, "dist"), { recursive: true });
|
fs.mkdirSync(path.join(pluginDir, "dist"), { recursive: true });
|
||||||
@@ -443,7 +426,7 @@ async function installArchivePackageAndReturnResult(params: {
|
|||||||
withDistIndex?: boolean;
|
withDistIndex?: boolean;
|
||||||
flatRoot?: boolean;
|
flatRoot?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const stateDir = makeTempDir();
|
const stateDir = suiteTempRootTracker.makeTempDir();
|
||||||
const archivePath = await ensureDynamicArchiveTemplate({
|
const archivePath = await ensureDynamicArchiveTemplate({
|
||||||
outName: params.outName,
|
outName: params.outName,
|
||||||
packageJson: params.packageJson,
|
packageJson: params.packageJson,
|
||||||
@@ -490,7 +473,7 @@ async function ensureDynamicArchiveTemplate(params: {
|
|||||||
if (cachedPath) {
|
if (cachedPath) {
|
||||||
return cachedPath;
|
return cachedPath;
|
||||||
}
|
}
|
||||||
const templateDir = makeTempDir();
|
const templateDir = suiteTempRootTracker.makeTempDir();
|
||||||
const pkgDir = params.flatRoot ? templateDir : path.join(templateDir, "package");
|
const pkgDir = params.flatRoot ? templateDir : path.join(templateDir, "package");
|
||||||
fs.mkdirSync(pkgDir, { recursive: true });
|
fs.mkdirSync(pkgDir, { recursive: true });
|
||||||
if (params.withDistIndex) {
|
if (params.withDistIndex) {
|
||||||
@@ -514,15 +497,8 @@ async function ensureDynamicArchiveTemplate(params: {
|
|||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
resetGlobalHookRunner();
|
resetGlobalHookRunner();
|
||||||
if (!suiteTempRoot) {
|
suiteTempRootTracker.cleanup();
|
||||||
return;
|
suiteFixtureRoot = "";
|
||||||
}
|
|
||||||
try {
|
|
||||||
fs.rmSync(suiteTempRoot, { recursive: true, force: true });
|
|
||||||
} finally {
|
|
||||||
suiteTempRoot = "";
|
|
||||||
tempDirCounter = 0;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
@@ -593,7 +569,7 @@ beforeEach(() => {
|
|||||||
|
|
||||||
describe("installPluginFromArchive", () => {
|
describe("installPluginFromArchive", () => {
|
||||||
it("installs scoped archives, rejects duplicate installs, and allows updates", async () => {
|
it("installs scoped archives, rejects duplicate installs, and allows updates", async () => {
|
||||||
const stateDir = makeTempDir();
|
const stateDir = suiteTempRootTracker.makeTempDir();
|
||||||
const archiveV1 = getArchiveFixturePath({
|
const archiveV1 = getArchiveFixturePath({
|
||||||
cacheKey: "voice-call:0.0.1",
|
cacheKey: "voice-call:0.0.1",
|
||||||
outName: "voice-call-0.0.1.tgz",
|
outName: "voice-call-0.0.1.tgz",
|
||||||
@@ -637,7 +613,7 @@ describe("installPluginFromArchive", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("installs from a zip archive", async () => {
|
it("installs from a zip archive", async () => {
|
||||||
const stateDir = makeTempDir();
|
const stateDir = suiteTempRootTracker.makeTempDir();
|
||||||
const archivePath = getArchiveFixturePath({
|
const archivePath = getArchiveFixturePath({
|
||||||
cacheKey: "zipper:0.0.1",
|
cacheKey: "zipper:0.0.1",
|
||||||
outName: "zipper-0.0.1.zip",
|
outName: "zipper-0.0.1.zip",
|
||||||
@@ -653,7 +629,7 @@ describe("installPluginFromArchive", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("allows archive installs with dangerous code patterns when forced unsafe install is set", async () => {
|
it("allows archive installs with dangerous code patterns when forced unsafe install is set", async () => {
|
||||||
const stateDir = makeTempDir();
|
const stateDir = suiteTempRootTracker.makeTempDir();
|
||||||
const extensionsDir = path.join(stateDir, "extensions");
|
const extensionsDir = path.join(stateDir, "extensions");
|
||||||
fs.mkdirSync(extensionsDir, { recursive: true });
|
fs.mkdirSync(extensionsDir, { recursive: true });
|
||||||
|
|
||||||
@@ -1323,7 +1299,7 @@ describe("installPluginFromDir", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it("keeps scoped install-dir validation aligned for real scoped ids", () => {
|
it("keeps scoped install-dir validation aligned for real scoped ids", () => {
|
||||||
const extensionsDir = path.join(makeTempDir(), "extensions");
|
const extensionsDir = path.join(suiteTempRootTracker.makeTempDir(), "extensions");
|
||||||
const scopedTarget = resolvePluginInstallDir("@scope/name", extensionsDir);
|
const scopedTarget = resolvePluginInstallDir("@scope/name", extensionsDir);
|
||||||
const hashedFlatId = safePathSegmentHashed("@scope/name");
|
const hashedFlatId = safePathSegmentHashed("@scope/name");
|
||||||
const flatTarget = resolvePluginInstallDir(hashedFlatId, extensionsDir);
|
const flatTarget = resolvePluginInstallDir(hashedFlatId, extensionsDir);
|
||||||
|
|||||||
Reference in New Issue
Block a user