hermes-agent/apps/desktop/electron/windows-child-options.ts
ethernet 4527943e91 test(desktop): extract hiddenWindowsChildOptions + stopBackendChild for real unit tests
windows-child-process.test.ts regexed main.ts and bootstrap-runner.ts
source text to check that spawn/execFileSync call sites wrapped their
options with hiddenWindowsChildOptions(), and that backend teardown
chose the right kill strategy.

Extract both into dependency-free sibling modules:
- windows-child-options.ts: hiddenWindowsChildOptions(options,
isWindows)
  now takes isWindows as an injectable param (defaults to the real
  platform check). main.ts and bootstrap-runner.ts both import the same
  implementation instead of each defining their own copy.
- backend-child.ts: stopBackendChild(child, deps) with
forceKillProcessTree
  and isWindows injected, so the SIGTERM-vs-tree-kill branching is
directly
  testable with a fake child + a spy.

windows-child-options.test.ts replaces windows-child-process.test.ts,
calling the real functions with fake spawn/execFileSync-shaped objects
and asserting on the actual returned options / kill call.
2026-07-13 17:22:17 -04:00

37 lines
1.6 KiB
TypeScript

/**
* windows-child-options.ts
*
* Shared helper for opting Windows child processes (spawn/execFileSync) into
* a hidden console. Windows spawns a visible console window per child by
* default; every desktop-launched helper process (git, curl, taskkill, the
* backend itself, the bootstrap PowerShell runner, ...) needs `windowsHide:
* true` so the user doesn't see consoles flashing on screen.
*
* Extracted into its own dependency-free module (no electron import) so it
* can be unit-tested directly for both platforms without reading source
* text, and so main.ts and bootstrap-runner.ts share exactly one
* implementation instead of each defining their own copy.
*/
import type { ExecFileSyncOptionsWithStringEncoding } from 'node:child_process'
/**
* Merge `windowsHide: true` into `options` when running on Windows, unless
* the caller already specified a `windowsHide` value (which is preserved
* as-is, including an explicit `false` for cases that intentionally want a
* visible/interactive console). No-op on non-Windows platforms.
*
* @param options - spawn/execFileSync options to (possibly) augment.
* @param isWindows - defaults to the real platform check; injectable for
* tests so both branches can be exercised without mocking process.platform.
*/
export function hiddenWindowsChildOptions(
options: any = {},
isWindows: boolean = process.platform === 'win32'
): ExecFileSyncOptionsWithStringEncoding {
if (!isWindows || Object.prototype.hasOwnProperty.call(options, 'windowsHide')) {
return options as any
}
return { ...options, windowsHide: true } as any
}