UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

149 lines (134 loc) 5.74 kB
import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { resolveWindowsLobsterSpawn } from "./windows-spawn.js"; function setProcessPlatform(platform: NodeJS.Platform) { Object.defineProperty(process, "platform", { value: platform, configurable: true, }); } describe("resolveWindowsLobsterSpawn", () => { let tempDir = ""; const originalPlatform = Object.getOwnPropertyDescriptor(process, "platform"); const originalPath = process.env.PATH; const originalPathAlt = process.env.Path; const originalPathExt = process.env.PATHEXT; const originalPathExtAlt = process.env.Pathext; beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-lobster-win-spawn-")); setProcessPlatform("win32"); }); afterEach(async () => { if (originalPlatform) { Object.defineProperty(process, "platform", originalPlatform); } if (originalPath === undefined) { delete process.env.PATH; } else { process.env.PATH = originalPath; } if (originalPathAlt === undefined) { delete process.env.Path; } else { process.env.Path = originalPathAlt; } if (originalPathExt === undefined) { delete process.env.PATHEXT; } else { process.env.PATHEXT = originalPathExt; } if (originalPathExtAlt === undefined) { delete process.env.Pathext; } else { process.env.Pathext = originalPathExtAlt; } if (tempDir) { await fs.rm(tempDir, { recursive: true, force: true }); tempDir = ""; } }); it("unwraps cmd shim with %dp0% token", async () => { const scriptPath = path.join(tempDir, "shim-dist", "lobster-cli.cjs"); const shimPath = path.join(tempDir, "shim", "lobster.cmd"); await fs.mkdir(path.dirname(scriptPath), { recursive: true }); await fs.mkdir(path.dirname(shimPath), { recursive: true }); await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8"); await fs.writeFile( shimPath, `@echo off\r\n"%dp0%\\..\\shim-dist\\lobster-cli.cjs" %*\r\n`, "utf8", ); const target = resolveWindowsLobsterSpawn(shimPath, ["run", "noop"], process.env); expect(target.command).toBe(process.execPath); expect(target.argv).toEqual([scriptPath, "run", "noop"]); expect(target.windowsHide).toBe(true); }); it("unwraps cmd shim with %~dp0% token", async () => { const scriptPath = path.join(tempDir, "shim-dist", "lobster-cli.cjs"); const shimPath = path.join(tempDir, "shim", "lobster.cmd"); await fs.mkdir(path.dirname(scriptPath), { recursive: true }); await fs.mkdir(path.dirname(shimPath), { recursive: true }); await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8"); await fs.writeFile( shimPath, `@echo off\r\n"%~dp0%\\..\\shim-dist\\lobster-cli.cjs" %*\r\n`, "utf8", ); const target = resolveWindowsLobsterSpawn(shimPath, ["run", "noop"], process.env); expect(target.command).toBe(process.execPath); expect(target.argv).toEqual([scriptPath, "run", "noop"]); expect(target.windowsHide).toBe(true); }); it("ignores node.exe shim entries and picks lobster script", async () => { const shimDir = path.join(tempDir, "shim-with-node"); const scriptPath = path.join(tempDir, "shim-dist-node", "lobster-cli.cjs"); const shimPath = path.join(shimDir, "lobster.cmd"); await fs.mkdir(path.dirname(scriptPath), { recursive: true }); await fs.mkdir(shimDir, { recursive: true }); await fs.writeFile(path.join(shimDir, "node.exe"), "", "utf8"); await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8"); await fs.writeFile( shimPath, `@echo off\r\n"%~dp0%\\node.exe" "%~dp0%\\..\\shim-dist-node\\lobster-cli.cjs" %*\r\n`, "utf8", ); const target = resolveWindowsLobsterSpawn(shimPath, ["run", "noop"], process.env); expect(target.command).toBe(process.execPath); expect(target.argv).toEqual([scriptPath, "run", "noop"]); expect(target.windowsHide).toBe(true); }); it("resolves lobster.cmd from PATH and unwraps npm layout shim", async () => { const binDir = path.join(tempDir, "node_modules", ".bin"); const packageDir = path.join(tempDir, "node_modules", "lobster"); const scriptPath = path.join(packageDir, "dist", "cli.js"); const shimPath = path.join(binDir, "lobster.cmd"); await fs.mkdir(path.dirname(scriptPath), { recursive: true }); await fs.mkdir(binDir, { recursive: true }); await fs.writeFile(shimPath, "@echo off\r\n", "utf8"); await fs.writeFile( path.join(packageDir, "package.json"), JSON.stringify({ name: "lobster", version: "0.0.0", bin: { lobster: "dist/cli.js" } }), "utf8", ); await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8"); const env = { ...process.env, PATH: `${binDir};${process.env.PATH ?? ""}`, PATHEXT: ".CMD;.EXE", }; const target = resolveWindowsLobsterSpawn("lobster", ["run", "noop"], env); expect(target.command).toBe(process.execPath); expect(target.argv).toEqual([scriptPath, "run", "noop"]); expect(target.windowsHide).toBe(true); }); it("fails fast when wrapper cannot be resolved without shell execution", async () => { const badShimPath = path.join(tempDir, "bad-shim", "lobster.cmd"); await fs.mkdir(path.dirname(badShimPath), { recursive: true }); await fs.writeFile(badShimPath, "@echo off\r\nREM no entrypoint\r\n", "utf8"); expect(() => resolveWindowsLobsterSpawn(badShimPath, ["run", "noop"], process.env)).toThrow( /without shell execution/, ); }); });