mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 16:58:25 +00:00
refactor(test): dedupe repeated fixture setup helpers
This commit is contained in:
@@ -167,6 +167,26 @@ function setupPluginInstallDirs() {
|
||||
return { tmpDir, pluginDir, extensionsDir };
|
||||
}
|
||||
|
||||
function setupInstallPluginFromDirFixture(params?: { devDependencies?: Record<string, string> }) {
|
||||
const workDir = makeTempDir();
|
||||
const stateDir = makeTempDir();
|
||||
const pluginDir = path.join(workDir, "plugin");
|
||||
fs.mkdirSync(path.join(pluginDir, "dist"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@openclaw/test-plugin",
|
||||
version: "0.0.1",
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
dependencies: { "left-pad": "1.3.0" },
|
||||
...(params?.devDependencies ? { devDependencies: params.devDependencies } : {}),
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(path.join(pluginDir, "dist", "index.js"), "export {};", "utf-8");
|
||||
return { pluginDir, extensionsDir: path.join(stateDir, "extensions") };
|
||||
}
|
||||
|
||||
async function installFromDirWithWarnings(params: { pluginDir: string; extensionsDir: string }) {
|
||||
const warnings: string[] = [];
|
||||
const result = await installPluginFromDir({
|
||||
@@ -445,21 +465,7 @@ describe("installPluginFromArchive", () => {
|
||||
|
||||
describe("installPluginFromDir", () => {
|
||||
it("uses --ignore-scripts for dependency install", async () => {
|
||||
const workDir = makeTempDir();
|
||||
const stateDir = makeTempDir();
|
||||
const pluginDir = path.join(workDir, "plugin");
|
||||
fs.mkdirSync(path.join(pluginDir, "dist"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@openclaw/test-plugin",
|
||||
version: "0.0.1",
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
dependencies: { "left-pad": "1.3.0" },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(path.join(pluginDir, "dist", "index.js"), "export {};", "utf-8");
|
||||
const { pluginDir, extensionsDir } = setupInstallPluginFromDirFixture();
|
||||
|
||||
const run = vi.mocked(runCommandWithTimeout);
|
||||
await expectInstallUsesIgnoreScripts({
|
||||
@@ -467,31 +473,18 @@ describe("installPluginFromDir", () => {
|
||||
install: async () =>
|
||||
await installPluginFromDir({
|
||||
dirPath: pluginDir,
|
||||
extensionsDir: path.join(stateDir, "extensions"),
|
||||
extensionsDir,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
it("strips workspace devDependencies before npm install", async () => {
|
||||
const workDir = makeTempDir();
|
||||
const stateDir = makeTempDir();
|
||||
const pluginDir = path.join(workDir, "plugin");
|
||||
fs.mkdirSync(path.join(pluginDir, "dist"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@openclaw/test-plugin",
|
||||
version: "0.0.1",
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
dependencies: { "left-pad": "1.3.0" },
|
||||
devDependencies: {
|
||||
openclaw: "workspace:*",
|
||||
vitest: "^3.0.0",
|
||||
},
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(path.join(pluginDir, "dist", "index.js"), "export {};", "utf-8");
|
||||
const { pluginDir, extensionsDir } = setupInstallPluginFromDirFixture({
|
||||
devDependencies: {
|
||||
openclaw: "workspace:*",
|
||||
vitest: "^3.0.0",
|
||||
},
|
||||
});
|
||||
|
||||
const run = vi.mocked(runCommandWithTimeout);
|
||||
run.mockResolvedValue({
|
||||
@@ -505,7 +498,7 @@ describe("installPluginFromDir", () => {
|
||||
|
||||
const res = await installPluginFromDir({
|
||||
dirPath: pluginDir,
|
||||
extensionsDir: path.join(stateDir, "extensions"),
|
||||
extensionsDir,
|
||||
});
|
||||
expect(res.ok).toBe(true);
|
||||
if (!res.ok) {
|
||||
|
||||
@@ -46,6 +46,24 @@ async function createInstalledNpmPluginFixture(params: {
|
||||
};
|
||||
}
|
||||
|
||||
type UninstallResult = Awaited<ReturnType<typeof uninstallPlugin>>;
|
||||
|
||||
async function runDeleteInstalledNpmPluginFixture(baseDir: string): Promise<{
|
||||
pluginDir: string;
|
||||
result: UninstallResult;
|
||||
}> {
|
||||
const { pluginId, extensionsDir, pluginDir, config } = await createInstalledNpmPluginFixture({
|
||||
baseDir,
|
||||
});
|
||||
const result = await uninstallPlugin({
|
||||
config,
|
||||
pluginId,
|
||||
deleteFiles: true,
|
||||
extensionsDir,
|
||||
});
|
||||
return { pluginDir, result };
|
||||
}
|
||||
|
||||
function createSinglePluginEntries(pluginId = "my-plugin") {
|
||||
return {
|
||||
[pluginId]: { enabled: true },
|
||||
@@ -61,6 +79,21 @@ function createSinglePluginWithEmptySlotsConfig(): OpenClawConfig {
|
||||
};
|
||||
}
|
||||
|
||||
function createSingleNpmInstallConfig(installPath: string): OpenClawConfig {
|
||||
return {
|
||||
plugins: {
|
||||
entries: createSinglePluginEntries(),
|
||||
installs: {
|
||||
"my-plugin": {
|
||||
source: "npm",
|
||||
spec: "my-plugin@1.0.0",
|
||||
installPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function createPluginDirFixture(baseDir: string, pluginId = "my-plugin") {
|
||||
const pluginDir = path.join(baseDir, pluginId);
|
||||
await fs.mkdir(pluginDir, { recursive: true });
|
||||
@@ -330,18 +363,9 @@ describe("uninstallPlugin", () => {
|
||||
});
|
||||
|
||||
it("deletes directory when deleteFiles is true", async () => {
|
||||
const { pluginId, extensionsDir, pluginDir, config } = await createInstalledNpmPluginFixture({
|
||||
baseDir: tempDir,
|
||||
});
|
||||
const { pluginDir, result } = await runDeleteInstalledNpmPluginFixture(tempDir);
|
||||
|
||||
try {
|
||||
const result = await uninstallPlugin({
|
||||
config,
|
||||
pluginId,
|
||||
deleteFiles: true,
|
||||
extensionsDir,
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.actions.directory).toBe(true);
|
||||
@@ -389,18 +413,7 @@ describe("uninstallPlugin", () => {
|
||||
it("does not delete directory when deleteFiles is false", async () => {
|
||||
const pluginDir = await createPluginDirFixture(tempDir);
|
||||
|
||||
const config: OpenClawConfig = {
|
||||
plugins: {
|
||||
entries: createSinglePluginEntries(),
|
||||
installs: {
|
||||
"my-plugin": {
|
||||
source: "npm",
|
||||
spec: "my-plugin@1.0.0",
|
||||
installPath: pluginDir,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const config = createSingleNpmInstallConfig(pluginDir);
|
||||
|
||||
const result = await uninstallPlugin({
|
||||
config,
|
||||
@@ -417,20 +430,7 @@ describe("uninstallPlugin", () => {
|
||||
});
|
||||
|
||||
it("succeeds even if directory does not exist", async () => {
|
||||
const config: OpenClawConfig = {
|
||||
plugins: {
|
||||
entries: {
|
||||
"my-plugin": { enabled: true },
|
||||
},
|
||||
installs: {
|
||||
"my-plugin": {
|
||||
source: "npm",
|
||||
spec: "my-plugin@1.0.0",
|
||||
installPath: "/nonexistent/path",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const config = createSingleNpmInstallConfig("/nonexistent/path");
|
||||
|
||||
const result = await uninstallPlugin({
|
||||
config,
|
||||
@@ -447,18 +447,9 @@ describe("uninstallPlugin", () => {
|
||||
});
|
||||
|
||||
it("returns a warning when directory deletion fails unexpectedly", async () => {
|
||||
const { pluginId, extensionsDir, config } = await createInstalledNpmPluginFixture({
|
||||
baseDir: tempDir,
|
||||
});
|
||||
|
||||
const rmSpy = vi.spyOn(fs, "rm").mockRejectedValueOnce(new Error("permission denied"));
|
||||
try {
|
||||
const result = await uninstallPlugin({
|
||||
config,
|
||||
pluginId,
|
||||
deleteFiles: true,
|
||||
extensionsDir,
|
||||
});
|
||||
const { result } = await runDeleteInstalledNpmPluginFixture(tempDir);
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
@@ -477,20 +468,7 @@ describe("uninstallPlugin", () => {
|
||||
await fs.mkdir(outsideDir, { recursive: true });
|
||||
await fs.writeFile(path.join(outsideDir, "index.js"), "// keep me");
|
||||
|
||||
const config: OpenClawConfig = {
|
||||
plugins: {
|
||||
entries: {
|
||||
"my-plugin": { enabled: true },
|
||||
},
|
||||
installs: {
|
||||
"my-plugin": {
|
||||
source: "npm",
|
||||
spec: "my-plugin@1.0.0",
|
||||
installPath: outsideDir,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const config = createSingleNpmInstallConfig(outsideDir);
|
||||
|
||||
const result = await uninstallPlugin({
|
||||
config,
|
||||
|
||||
Reference in New Issue
Block a user