test: fix last bare child_process polluter in issue.test.ts

The long-body draft-save test registered a bare `mock.module(
'node:child_process', ...)` inside the test body. Without spread+flag,
that stub leaked process-globally into every later test file in the run.

Apply the same pattern used in issue-gh / issue-template / share-* :
spread real child_process, route execFile/execFileSync through a
`useIssueLongBodyCpStubs` flag, flip on at start of test and off in
the finally block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
unraid
2026-05-09 16:05:52 +08:00
parent 8cd0e90ca6
commit 2bf521ddbe

View File

@@ -50,6 +50,11 @@ let _dynamicSessionId = `issue-test-${randomUUID()}`
// the combined suite (alphabetical: 'autofix-pr' < 'issue') and expects // the combined suite (alphabetical: 'autofix-pr' < 'issue') and expects
// '/mock/cwd'. Issue's beforeAll switches this on, afterAll switches off. // '/mock/cwd'. Issue's beforeAll switches this on, afterAll switches off.
let useIssueDynamicState = false let useIssueDynamicState = false
// Default OFF — the long-body draft-save test below flips this on for its
// body (so execFile/execFileSync return ENOENT + a fake GitHub remote URL)
// then flips off in finally. Without the flag the child_process stub leaked
// process-globally into every later test file via Bun's mock.module cache.
let useIssueLongBodyCpStubs = false
mock.module('src/bootstrap/state.js', () => ({ mock.module('src/bootstrap/state.js', () => ({
...stateMock(), ...stateMock(),
getSessionId: () => getSessionId: () =>
@@ -541,26 +546,40 @@ describe('issue command — with title', () => {
// Force the fallback URL branch with a *parsed* GitHub remote so the // Force the fallback URL branch with a *parsed* GitHub remote so the
// draft-path output (lines 392-393) is reached: git remote returns a // draft-path output (lines 392-393) is reached: git remote returns a
// GitHub URL but `gh --version` fails so hasGh is false. // GitHub URL but `gh --version` fails so hasGh is false.
mock.module('node:child_process', () => ({ //
execFile: ( // Spread+flag pattern: the previous bare `mock.module(...)` here leaked
_cmd: string, // a stub child_process to every later test file in the same `bun test`
_args: string[], // run (mock.module is process-global, last-write-wins). Now we register
_opts: unknown, // a flag-gated mock that delegates to real child_process by default, and
cb: (err: Error | null, stdout: string, stderr: string) => void, // only flips on for THIS test's body.
) => cb(new Error('ENOENT'), '', ''), mock.module('node:child_process', () => {
execFileSync: (cmd: string) => { // eslint-disable-next-line @typescript-eslint/no-require-imports
if (cmd === 'git') const real = require('node:child_process') as Record<string, unknown>
return Buffer.from('https://github.com/owner/repo.git\n') return {
throw new Error('ENOENT') ...real,
}, default: real,
exec: () => {}, execFile: ((...args: unknown[]) => {
execSync: () => Buffer.from(''), if (useIssueLongBodyCpStubs) {
spawn: () => ({}), const cb = args[3] as
spawnSync: () => ({ status: 0, stdout: Buffer.from('') }), | ((e: Error | null, s: string, e2: string) => void)
fork: () => ({}), | undefined
ChildProcess: class {}, if (cb) cb(new Error('ENOENT'), '', '')
_forkChild: () => {}, return
})) }
return (real.execFile as (...a: unknown[]) => unknown)(...args)
}) as typeof real.execFile,
execFileSync: ((...args: unknown[]) => {
if (useIssueLongBodyCpStubs) {
const cmd = args[0] as string
if (cmd === 'git')
return Buffer.from('https://github.com/owner/repo.git\n')
throw new Error('ENOENT')
}
return (real.execFileSync as (...a: unknown[]) => unknown)(...args)
}) as typeof real.execFileSync,
}
})
useIssueLongBodyCpStubs = true
Array.prototype.slice = function ( Array.prototype.slice = function (
this: unknown[], this: unknown[],
start?: number, start?: number,
@@ -586,6 +605,7 @@ describe('issue command — with title', () => {
} finally { } finally {
Array.prototype.slice = origSlice Array.prototype.slice = origSlice
setOriginalCwd(origCwd) setOriginalCwd(origCwd)
useIssueLongBodyCpStubs = false
} }
}) })
}) })