From 934f2f0d048cc94533d384ef262da35e33125ce1 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 7 Jun 2026 17:32:12 -0700 Subject: [PATCH] FN-6004: add execFile to engine child_process test mocks Update engine tests so child_process mocks cover execFile alongside exec. - add execFile mock implementations and promisify support in branch/worktree tests that rely on child_process behavior - extend simpler child_process mocks in integration, sandbox, and worktree tests to export execFile stubs - keep existing exec and execSync mock behavior unchanged while restoring compatibility with code that now imports execFile Files changed: packages/engine/src/__tests__/branch-autocorrect.test.ts | 9 ++++++++- .../engine/src/__tests__/branch-conflicts-self-owned.test.ts | 9 ++++++++- packages/engine/src/__tests__/branch-conflicts.test.ts | 9 ++++++++- packages/engine/src/__tests__/integration-branch.test.ts | 1 + .../engine/src/__tests__/sandbox/bubblewrap-detect.test.ts | 1 + .../engine/src/__tests__/sandbox/sandbox-exec-backend.test.ts | 1 + .../engine/src/__tests__/sandbox/sandbox-exec-detect.test.ts | 1 + .../engine/src/__tests__/worktree-acquisition-backend.test.ts | 2 +- .../src/__tests__/worktree-acquisition-worktrunk.test.ts | 2 +- packages/engine/src/__tests__/worktree-backend.test.ts | 2 +- .../engine/src/__tests__/worktree-hooks-cross-platform.test.ts | 2 +- packages/engine/src/__tests__/worktree-pool.test.ts | 10 ++++++++-- packages/engine/src/__tests__/worktree-stale-lock.test.ts | 2 +- .../engine/src/__tests__/worktree-stale-registration.test.ts | 2 +- 14 files changed, 42 insertions(+), 11 deletions(-) Fusion-Task-Id: FN-6004 Fusion-Task-Lineage: f87fb103-fe5d-4fc9-a640-9991c06e6448 --- .../engine/src/__tests__/branch-autocorrect.test.ts | 9 ++++++++- .../src/__tests__/branch-conflicts-self-owned.test.ts | 9 ++++++++- packages/engine/src/__tests__/branch-conflicts.test.ts | 9 ++++++++- .../engine/src/__tests__/integration-branch.test.ts | 1 + .../src/__tests__/sandbox/bubblewrap-detect.test.ts | 1 + .../src/__tests__/sandbox/sandbox-exec-backend.test.ts | 1 + .../src/__tests__/sandbox/sandbox-exec-detect.test.ts | 1 + .../src/__tests__/worktree-acquisition-backend.test.ts | 2 +- .../__tests__/worktree-acquisition-worktrunk.test.ts | 2 +- packages/engine/src/__tests__/worktree-backend.test.ts | 2 +- .../__tests__/worktree-hooks-cross-platform.test.ts | 2 +- packages/engine/src/__tests__/worktree-pool.test.ts | 10 ++++++++-- .../engine/src/__tests__/worktree-stale-lock.test.ts | 2 +- .../src/__tests__/worktree-stale-registration.test.ts | 2 +- 14 files changed, 42 insertions(+), 11 deletions(-) diff --git a/packages/engine/src/__tests__/branch-autocorrect.test.ts b/packages/engine/src/__tests__/branch-autocorrect.test.ts index 4a0a60a29f..c3042842c5 100644 --- a/packages/engine/src/__tests__/branch-autocorrect.test.ts +++ b/packages/engine/src/__tests__/branch-autocorrect.test.ts @@ -19,6 +19,10 @@ vi.mock("node:child_process", async () => { }); }); + const execFileFn: any = vi.fn((file: string, args: string[] | undefined, opts: any, cb: any) => + execFn([file, ...(Array.isArray(args) ? args : [])].join(" "), opts, cb), + ); + execFn[promisify.custom] = (cmd: string, opts?: any) => new Promise((resolve, reject) => { execFn(cmd, opts, (err: any, stdout: string, stderr: string) => { @@ -32,7 +36,10 @@ vi.mock("node:child_process", async () => { }); }); - return { exec: execFn, __execMock: execMock }; + execFileFn[promisify.custom] = (file: string, args?: string[], opts?: any) => + execFn[promisify.custom]([file, ...(Array.isArray(args) ? args : [])].join(" "), opts); + + return { exec: execFn, execFile: execFileFn, __execMock: execMock }; }); import { attemptBranchAutocorrect } from "../branch-autocorrect.js"; diff --git a/packages/engine/src/__tests__/branch-conflicts-self-owned.test.ts b/packages/engine/src/__tests__/branch-conflicts-self-owned.test.ts index 71e882ab2e..51002aabb2 100644 --- a/packages/engine/src/__tests__/branch-conflicts-self-owned.test.ts +++ b/packages/engine/src/__tests__/branch-conflicts-self-owned.test.ts @@ -20,6 +20,10 @@ vi.mock("node:child_process", async () => { } }); + const execFileFn: any = vi.fn((file: string, args: string[] | undefined, opts: any, cb: any) => + execFn([file, ...(Array.isArray(args) ? args : [])].join(" "), opts, cb), + ); + execFn[promisify.custom] = (cmd: string, opts?: any) => new Promise((resolve, reject) => { execFn(cmd, opts, (err: any, stdout: string, stderr: string) => { @@ -33,7 +37,10 @@ vi.mock("node:child_process", async () => { }); }); - return { exec: execFn, execSync: execSyncFn }; + execFileFn[promisify.custom] = (file: string, args?: string[], opts?: any) => + execFn[promisify.custom]([file, ...(Array.isArray(args) ? args : [])].join(" "), opts); + + return { exec: execFn, execSync: execSyncFn, execFile: execFileFn }; }); vi.mock("node:fs", () => ({ diff --git a/packages/engine/src/__tests__/branch-conflicts.test.ts b/packages/engine/src/__tests__/branch-conflicts.test.ts index b6a70d3d9c..33598c4f83 100644 --- a/packages/engine/src/__tests__/branch-conflicts.test.ts +++ b/packages/engine/src/__tests__/branch-conflicts.test.ts @@ -20,6 +20,10 @@ vi.mock("node:child_process", async () => { } }); + const execFileFn: any = vi.fn((file: string, args: string[] | undefined, opts: any, cb: any) => + execFn([file, ...(Array.isArray(args) ? args : [])].join(" "), opts, cb), + ); + execFn[promisify.custom] = (cmd: string, opts?: any) => new Promise((resolve, reject) => { execFn(cmd, opts, (err: any, stdout: string, stderr: string) => { @@ -33,7 +37,10 @@ vi.mock("node:child_process", async () => { }); }); - return { exec: execFn, execSync: execSyncFn }; + execFileFn[promisify.custom] = (file: string, args?: string[], opts?: any) => + execFn[promisify.custom]([file, ...(Array.isArray(args) ? args : [])].join(" "), opts); + + return { exec: execFn, execSync: execSyncFn, execFile: execFileFn }; }); vi.mock("node:fs", () => ({ diff --git a/packages/engine/src/__tests__/integration-branch.test.ts b/packages/engine/src/__tests__/integration-branch.test.ts index cf45373c6e..2ddbb3124d 100644 --- a/packages/engine/src/__tests__/integration-branch.test.ts +++ b/packages/engine/src/__tests__/integration-branch.test.ts @@ -8,6 +8,7 @@ const { execMock, execSyncMock } = vi.hoisted(() => ({ vi.mock("node:child_process", () => ({ exec: execMock, execSync: execSyncMock, + execFile: vi.fn(), })); import { diff --git a/packages/engine/src/__tests__/sandbox/bubblewrap-detect.test.ts b/packages/engine/src/__tests__/sandbox/bubblewrap-detect.test.ts index 1d071bbb6e..1fe469645b 100644 --- a/packages/engine/src/__tests__/sandbox/bubblewrap-detect.test.ts +++ b/packages/engine/src/__tests__/sandbox/bubblewrap-detect.test.ts @@ -5,6 +5,7 @@ const execMock = vi.fn(); vi.mock("node:child_process", () => ({ exec: execMock, + execFile: vi.fn(), })); const originalPlatform = process.platform; diff --git a/packages/engine/src/__tests__/sandbox/sandbox-exec-backend.test.ts b/packages/engine/src/__tests__/sandbox/sandbox-exec-backend.test.ts index f50d7efabd..0e22df3746 100644 --- a/packages/engine/src/__tests__/sandbox/sandbox-exec-backend.test.ts +++ b/packages/engine/src/__tests__/sandbox/sandbox-exec-backend.test.ts @@ -16,6 +16,7 @@ const { detectMock, policyToProfileMock, presetMock, nativeRunMock, nativePrepar vi.mock("node:child_process", () => ({ exec: execMock, + execFile: vi.fn(), })); vi.mock("../../sandbox/sandbox-exec-detect.js", () => ({ diff --git a/packages/engine/src/__tests__/sandbox/sandbox-exec-detect.test.ts b/packages/engine/src/__tests__/sandbox/sandbox-exec-detect.test.ts index 6dd8ec0bcc..30aab632ca 100644 --- a/packages/engine/src/__tests__/sandbox/sandbox-exec-detect.test.ts +++ b/packages/engine/src/__tests__/sandbox/sandbox-exec-detect.test.ts @@ -5,6 +5,7 @@ const execMock = vi.fn(); vi.mock("node:child_process", () => ({ exec: execMock, + execFile: vi.fn(), })); const originalPlatform = process.platform; diff --git a/packages/engine/src/__tests__/worktree-acquisition-backend.test.ts b/packages/engine/src/__tests__/worktree-acquisition-backend.test.ts index 16af5981ae..542e8ac348 100644 --- a/packages/engine/src/__tests__/worktree-acquisition-backend.test.ts +++ b/packages/engine/src/__tests__/worktree-acquisition-backend.test.ts @@ -22,7 +22,7 @@ const { execMock, existsSyncMock, accessMock } = vi.hoisted(() => { return { execMock: mock, existsSyncMock: vi.fn(), accessMock: vi.fn().mockResolvedValue(undefined) }; }); -vi.mock("node:child_process", () => ({ exec: execMock })); +vi.mock("node:child_process", () => ({ exec: execMock, execFile: vi.fn() })); vi.mock("node:fs", () => ({ existsSync: existsSyncMock })); vi.mock("node:fs/promises", () => ({ access: accessMock })); diff --git a/packages/engine/src/__tests__/worktree-acquisition-worktrunk.test.ts b/packages/engine/src/__tests__/worktree-acquisition-worktrunk.test.ts index 941237d1dd..2a5f623b60 100644 --- a/packages/engine/src/__tests__/worktree-acquisition-worktrunk.test.ts +++ b/packages/engine/src/__tests__/worktree-acquisition-worktrunk.test.ts @@ -6,7 +6,7 @@ const { execMock, existsSyncMock } = vi.hoisted(() => { return { execMock: mock, existsSyncMock: vi.fn() }; }); -vi.mock("node:child_process", () => ({ exec: execMock })); +vi.mock("node:child_process", () => ({ exec: execMock, execFile: vi.fn() })); vi.mock("node:fs", () => ({ existsSync: existsSyncMock })); vi.mock("../worktree-hooks.js", () => ({ installTaskWorktreeIdentityGuard: vi.fn().mockResolvedValue(undefined), diff --git a/packages/engine/src/__tests__/worktree-backend.test.ts b/packages/engine/src/__tests__/worktree-backend.test.ts index 67d13a4872..3ff2579ac3 100644 --- a/packages/engine/src/__tests__/worktree-backend.test.ts +++ b/packages/engine/src/__tests__/worktree-backend.test.ts @@ -27,7 +27,7 @@ const { execMock, accessMock, rmMock, existsSyncMock, parseIndexLockPathMock, cl }; }); -vi.mock("node:child_process", () => ({ exec: execMock })); +vi.mock("node:child_process", () => ({ exec: execMock, execFile: vi.fn() })); vi.mock("node:fs", () => ({ existsSync: existsSyncMock })); vi.mock("node:fs/promises", () => ({ access: accessMock, rm: rmMock })); vi.mock("../branch-conflicts.js", () => ({ diff --git a/packages/engine/src/__tests__/worktree-hooks-cross-platform.test.ts b/packages/engine/src/__tests__/worktree-hooks-cross-platform.test.ts index bae733c23c..032c941098 100644 --- a/packages/engine/src/__tests__/worktree-hooks-cross-platform.test.ts +++ b/packages/engine/src/__tests__/worktree-hooks-cross-platform.test.ts @@ -5,7 +5,7 @@ import { join } from "node:path"; import { describe, expect, it, vi } from "vitest"; const { execMock } = vi.hoisted(() => ({ execMock: vi.fn() })); -vi.mock("node:child_process", () => ({ exec: execMock })); +vi.mock("node:child_process", () => ({ exec: execMock, execFile: vi.fn() })); import { writeFileAtomic } from "../worktree-hooks.js"; diff --git a/packages/engine/src/__tests__/worktree-pool.test.ts b/packages/engine/src/__tests__/worktree-pool.test.ts index 93b4ee3de0..72c0dfad32 100644 --- a/packages/engine/src/__tests__/worktree-pool.test.ts +++ b/packages/engine/src/__tests__/worktree-pool.test.ts @@ -21,7 +21,11 @@ vi.mock("node:child_process", async () => { } } }); - + + const execFileFn: any = vi.fn((file: string, args: string[] | undefined, opts: any, cb: any) => + execFn([file, ...(Array.isArray(args) ? args : [])].join(" "), opts, cb), + ); + execFn[promisify.custom] = (cmd: string, opts?: any) => new Promise((resolve, reject) => { @@ -35,7 +39,9 @@ vi.mock("node:child_process", async () => { } }); }); - return { execSync: execSyncFn, exec: execFn }; + execFileFn[promisify.custom] = (file: string, args?: string[], opts?: any) => + execFn[promisify.custom]([file, ...(Array.isArray(args) ? args : [])].join(" "), opts); + return { execSync: execSyncFn, exec: execFn, execFile: execFileFn }; }); vi.mock("../worktree-desktop-artifacts.js", () => ({ diff --git a/packages/engine/src/__tests__/worktree-stale-lock.test.ts b/packages/engine/src/__tests__/worktree-stale-lock.test.ts index eed95bc89b..0802a17dde 100644 --- a/packages/engine/src/__tests__/worktree-stale-lock.test.ts +++ b/packages/engine/src/__tests__/worktree-stale-lock.test.ts @@ -10,7 +10,7 @@ const { execMock } = vi.hoisted(() => { return { execMock: mock }; }); -vi.mock("node:child_process", () => ({ exec: execMock })); +vi.mock("node:child_process", () => ({ exec: execMock, execFile: vi.fn() })); describe("worktree-stale-lock", () => { beforeEach(() => { diff --git a/packages/engine/src/__tests__/worktree-stale-registration.test.ts b/packages/engine/src/__tests__/worktree-stale-registration.test.ts index 69cab4aceb..36848221ee 100644 --- a/packages/engine/src/__tests__/worktree-stale-registration.test.ts +++ b/packages/engine/src/__tests__/worktree-stale-registration.test.ts @@ -7,7 +7,7 @@ const { execMock } = vi.hoisted(() => { return { execMock: mock }; }); -vi.mock("node:child_process", () => ({ exec: execMock })); +vi.mock("node:child_process", () => ({ exec: execMock, execFile: vi.fn() })); describe("worktree-stale-registration", () => { beforeEach(() => {