diff --git a/packages/desktop/scripts/dev-build-contract.test.mjs b/packages/desktop/scripts/dev-build-contract.test.mjs index 7c6994a64e..f9b3a34b0d 100644 --- a/packages/desktop/scripts/dev-build-contract.test.mjs +++ b/packages/desktop/scripts/dev-build-contract.test.mjs @@ -19,9 +19,17 @@ import { describe, expect, test } from "vitest"; const desktopDir = path.resolve(import.meta.dirname, ".."); const repoRoot = path.resolve(desktopDir, "../.."); const execFileAsync = promisify(execFile); -const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm"; +const npmCommand = process.platform === "win32" ? process.execPath : "npm"; +const npmPrefixArgs = + process.platform === "win32" ? [requireEnvironmentVariable("npm_execpath")] : []; const prerequisite = "npm run dev:prerequisites"; +function requireEnvironmentVariable(name) { + const value = process.env[name]; + if (!value) throw new Error(`${name} is required to invoke npm on Windows`); + return value; +} + describe("desktop dev build contract", () => { test("runs one prerequisite before either platform dev entry point", async () => { const packageJson = JSON.parse(await readFile(path.join(desktopDir, "package.json"), "utf8")); @@ -127,10 +135,14 @@ async function createIsolatedBuildCheckout() { async function runPrerequisite(isolatedRoot) { try { - await execFileAsync(npmCommand, ["run", "dev:prerequisites", "--workspace=@getpaseo/desktop"], { - cwd: isolatedRoot, - timeout: 60_000, - }); + await execFileAsync( + npmCommand, + [...npmPrefixArgs, "run", "dev:prerequisites", "--workspace=@getpaseo/desktop"], + { + cwd: isolatedRoot, + timeout: 60_000, + }, + ); } catch (error) { throw new Error(`${error.stdout ?? ""}\n${error.stderr ?? ""}`, { cause: error }); } diff --git a/packages/workspace-helper/test/standalone.test.mjs b/packages/workspace-helper/test/standalone.test.mjs index 655ebb97f5..14e6def7a6 100644 --- a/packages/workspace-helper/test/standalone.test.mjs +++ b/packages/workspace-helper/test/standalone.test.mjs @@ -7,19 +7,31 @@ import assert from "node:assert/strict"; import { promisify } from "node:util"; const run = promisify(execFile); -const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm"; +const npmCommand = process.platform === "win32" ? process.execPath : "npm"; +const npmPrefixArgs = + process.platform === "win32" ? [requireEnvironmentVariable("npm_execpath")] : []; const packageRoot = path.resolve(import.meta.dirname, ".."); +function requireEnvironmentVariable(name) { + const value = process.env[name]; + if (!value) throw new Error(`${name} is required to invoke npm on Windows`); + return value; +} + +function runNpm(args, options) { + return run(npmCommand, [...npmPrefixArgs, ...args], options); +} + test("packed helper works from a fresh project without monorepo source fallback", async (t) => { const root = await mkdtemp(path.join(tmpdir(), "paseo-helper-standalone-")); t.after(() => rm(root, { recursive: true, force: true })); const packDirectory = path.join(root, "packs"); const project = path.join(root, "project"); await Promise.all([mkdir(packDirectory), mkdir(project)]); - await run(npmCommand, ["run", "build"], { cwd: packageRoot }); + await runNpm(["run", "build"], { cwd: packageRoot }); const packed = JSON.parse( ( - await run(npmCommand, ["pack", "--json", "--pack-destination", packDirectory], { + await runNpm(["pack", "--json", "--pack-destination", packDirectory], { cwd: packageRoot, }) ).stdout, @@ -31,7 +43,7 @@ test("packed helper works from a fresh project without monorepo source fallback" dependencies: { "@getpaseo/workspace-helper": `file:${path.join(packDirectory, packed)}` }, }), ); - await run(npmCommand, ["install", "--ignore-scripts"], { cwd: project }); + await runNpm(["install", "--ignore-scripts"], { cwd: project }); await writeFile(path.join(project, "notes.txt"), "before\n"); const imported = JSON.parse( diff --git a/packages/workspace-runtime-contract/test/contract.test.mjs b/packages/workspace-runtime-contract/test/contract.test.mjs index da50e41de3..fb222d0d92 100644 --- a/packages/workspace-runtime-contract/test/contract.test.mjs +++ b/packages/workspace-runtime-contract/test/contract.test.mjs @@ -33,10 +33,22 @@ import { } from "../dist/index.js"; const run = promisify(execFile); -const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm"; +const npmCommand = process.platform === "win32" ? process.execPath : "npm"; +const npmPrefixArgs = + process.platform === "win32" ? [requireEnvironmentVariable("npm_execpath")] : []; const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const examples = JSON.parse(await readFile(path.join(packageRoot, "examples/v1.json"), "utf8")); +function requireEnvironmentVariable(name) { + const value = process.env[name]; + if (!value) throw new Error(`${name} is required to invoke npm on Windows`); + return value; +} + +function runNpm(args, options) { + return run(npmCommand, [...npmPrefixArgs, ...args], options); +} + test("documented lifecycle, fd3, control, and fd4 examples are exact newline-terminated bytes", () => { for (const [name, schema] of [ ["describeResponse", CommandRuntimeDescribeResponseSchema], @@ -522,7 +534,7 @@ test("every export condition resolves from a packed standalone install", async ( t.after(() => rm(root, { recursive: true, force: true })); const pack = JSON.parse( ( - await run(npmCommand, ["pack", "--json", "--ignore-scripts", "--pack-destination", root], { + await runNpm(["pack", "--json", "--ignore-scripts", "--pack-destination", root], { cwd: packageRoot, }) ).stdout, @@ -530,7 +542,7 @@ test("every export condition resolves from a packed standalone install", async ( const archive = path.join(root, pack[0].filename); const installRoot = path.join(root, "standalone"); await mkdir(installRoot); - await run(npmCommand, ["install", "--ignore-scripts", "--no-package-lock", archive], { + await runNpm(["install", "--ignore-scripts", "--no-package-lock", archive], { cwd: installRoot, }); const installed = path.join(installRoot, "node_modules/@getpaseo/workspace-runtime-contract");