'use strict' const test = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs') const path = require('node:path') const ELECTRON_DIR = __dirname function readElectronFile(name) { return fs.readFileSync(path.join(ELECTRON_DIR, name), 'utf8').replace(/\r\n/g, '\n') } function requireHiddenChildOptions(source, needle) { const match = needle instanceof RegExp ? needle.exec(source) : null const index = needle instanceof RegExp ? (match?.index ?? -1) : source.indexOf(needle) assert.notEqual(index, -1, `missing call site: ${needle}`) const snippet = source.slice(index, index + 700) assert.match( snippet, /hiddenWindowsChildOptions\(/, `expected ${needle} to wrap child-process options with hiddenWindowsChildOptions` ) } test('desktop background child processes opt into hidden Windows consoles', () => { const source = readElectronFile('main.cjs') assert.match(source, /function hiddenWindowsChildOptions\(options = \{\}\)/) requireHiddenChildOptions(source, "execFileSync(\n 'reg'") requireHiddenChildOptions(source, /execFileSync\(\s*pyExe/) requireHiddenChildOptions(source, /spawn\(\s*resolveGitBinary\(\)/) requireHiddenChildOptions(source, "execFileSync('taskkill'") requireHiddenChildOptions(source, /spawn\(\s*command,\s*args/) requireHiddenChildOptions(source, "spawn('curl'") requireHiddenChildOptions(source, /spawn\(\s*backend\.command,\s*backend\.args/) requireHiddenChildOptions(source, /hermesProcess = spawn\(\s*backend\.command,\s*backend\.args/) requireHiddenChildOptions(source, /spawn\(\s*py,\s*\['-m', 'hermes_cli\.main', 'uninstall', '--gui-summary'\]/) assert.match(source, /function unwrapWindowsVenvHermesCommand\(command, backendArgs\)/) assert.match(source, /function getVenvSitePackagesEntries\(venvRoot\)/) assert.match(source, /path\.join\(venvRoot, 'Lib', 'site-packages'\)/) assert.match(source, /args: \['-m', 'hermes_cli\.main', \.\.\.backendArgs\]/) }) test('desktop backend launches console python so child consoles are inherited, not pythonw', () => { const source = readElectronFile('main.cjs') // The flash fix is structural: the backend runs as a console-subsystem // python.exe under hiddenWindowsChildOptions() (-> CREATE_NO_WINDOW), so it // owns ONE windowless console that every descendant spawn inherits. Launching // it as GUI-subsystem pythonw.exe is what made each child allocate (and flash) // its own console, so the backend command must never be pythonw. assert.doesNotMatch(source, /pythonw\.exe'\)/, 'backend must not be launched via pythonw.exe') assert.doesNotMatch( source, /function getNoConsoleVenvPython\b/, 'pythonw-conversion helper should be gone; console python is launched directly' ) assert.doesNotMatch( source, /function applyWindowsNoConsoleSpawnHints\b/, 'pythonw spawn-hint rewriter should be gone' ) // Console python restores stdout, so the port is announced on the normal // HERMES_DASHBOARD_READY stdout line — no ready-file side channel is set. assert.doesNotMatch(source, /readyFile: true/, 'no backend should opt into the pythonw ready-file path') // Both desktop backend launches must still go through hiddenWindowsChildOptions // so the single backend console is created windowless. requireHiddenChildOptions(source, /spawn\(\s*backend\.command,\s*backend\.args/) requireHiddenChildOptions(source, /hermesProcess = spawn\(\s*backend\.command,\s*backend\.args/) }) test('intentional or interactive desktop child processes stay documented', () => { const source = readElectronFile('main.cjs') assert.match(source, /windowsHide: false/) assert.match(source, /handOffWindowsBootstrapRecovery/) assert.match(source, /'--repair', '--branch'/) assert.match(source, /'--update', '--branch'/) assert.match(source, /nodePty\.spawn\(command, args/) assert.match(source, /spawn\('cmd\.exe', \['\/c', 'start'/) }) test('bootstrap PowerShell runner hides Windows console children', () => { const source = readElectronFile('bootstrap-runner.cjs') assert.match(source, /function hiddenWindowsChildOptions\(options = \{\}\)/) requireHiddenChildOptions(source, /spawn\(\s*ps,\s*fullArgs/) })