import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { resolveCliSpawnInvocation } from "./qmd-process.js"; describe("resolveCliSpawnInvocation", () => { let tempDir = ""; let platformSpy: { mockRestore(): void } | null = null; const originalPath = process.env.PATH; const originalPathExt = process.env.PATHEXT; beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-qmd-win-spawn-")); platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue("win32"); }); afterEach(async () => { platformSpy?.mockRestore(); process.env.PATH = originalPath; process.env.PATHEXT = originalPathExt; if (tempDir) { await fs.rm(tempDir, { recursive: true, force: true }); tempDir = ""; } }); it("unwraps npm cmd shims to a direct node entrypoint", async () => { const binDir = path.join(tempDir, "node_modules", ".bin"); const packageDir = path.join(tempDir, "node_modules", "qmd"); const scriptPath = path.join(packageDir, "dist", "cli.js"); await fs.mkdir(path.dirname(scriptPath), { recursive: true }); await fs.mkdir(binDir, { recursive: true }); await fs.writeFile(path.join(binDir, "qmd.cmd"), "@echo off\r\n", "utf8"); await fs.writeFile( path.join(packageDir, "package.json"), JSON.stringify({ name: "qmd", version: "0.0.0", bin: { qmd: "dist/cli.js" } }), "utf8", ); await fs.writeFile(scriptPath, "module.exports = {};\n", "utf8"); process.env.PATH = `${binDir};${originalPath ?? ""}`; process.env.PATHEXT = ".CMD;.EXE"; const invocation = resolveCliSpawnInvocation({ command: "qmd", args: ["query", "hello"], env: process.env, packageName: "qmd", }); expect(invocation.command).toBe(process.execPath); expect(invocation.argv).toEqual([scriptPath, "query", "hello"]); expect(invocation.shell).not.toBe(true); expect(invocation.windowsHide).toBe(true); }); it("fails closed when a Windows cmd shim cannot be resolved without shell execution", async () => { const binDir = path.join(tempDir, "bad-bin"); await fs.mkdir(binDir, { recursive: true }); await fs.writeFile(path.join(binDir, "qmd.cmd"), "@echo off\r\nREM no entrypoint\r\n", "utf8"); process.env.PATH = `${binDir};${originalPath ?? ""}`; process.env.PATHEXT = ".CMD;.EXE"; expect(() => resolveCliSpawnInvocation({ command: "qmd", args: ["query", "hello"], env: process.env, packageName: "qmd", }), ).toThrow(/without shell execution/); }); it("keeps bare commands bare when no Windows wrapper exists on PATH", () => { process.env.PATH = originalPath ?? ""; process.env.PATHEXT = ".CMD;.EXE"; const invocation = resolveCliSpawnInvocation({ command: "qmd", args: ["query", "hello"], env: process.env, packageName: "qmd", }); expect(invocation.command).toBe("qmd"); expect(invocation.argv).toEqual(["query", "hello"]); expect(invocation.shell).not.toBe(true); }); });