Capture daemon startup logs before window ready in e2e test (#10040)
The daemon health-check guard logs during main-process startup, which can complete before the renderer window resolves. Moved stderr listening to the launch options so early logs aren't missed. Also made the assertion regex pattern-based instead of exact-string matching to tolerate benign log rewording, and added a check that the replace path stayed off.
This commit is contained in:
parent
3708c4f6ce
commit
5b7fdd7ef5
|
|
@ -83,11 +83,13 @@ test('preserves a live daemon PTY when the daemon is too slow for the startup he
|
|||
}
|
||||
}, RESUME_DAEMON_AFTER_MS)
|
||||
try {
|
||||
const secondLaunch = await session.launch()
|
||||
secondApp = secondLaunch.app
|
||||
secondApp.process().stderr?.on('data', (chunk: Buffer) => {
|
||||
stderrLines.push(chunk.toString())
|
||||
// Why: capture stderr from process start — the daemon guard logs its
|
||||
// preservation decision during main-process startup, which can complete
|
||||
// before firstWindow resolves, so a post-launch listener would miss it.
|
||||
const secondLaunch = await session.launch({
|
||||
onStderr: (chunk) => stderrLines.push(chunk)
|
||||
})
|
||||
secondApp = secondLaunch.app
|
||||
|
||||
await waitForSessionReady(secondLaunch.page)
|
||||
await expect
|
||||
|
|
@ -101,11 +103,15 @@ test('preserves a live daemon PTY when the daemon is too slow for the startup he
|
|||
await waitForPaneCount(secondLaunch.page, 1, 30_000)
|
||||
await waitForTerminalOutput(secondLaunch.page, marker, 20_000)
|
||||
|
||||
// The guard path must actually have run: the daemon failed the health
|
||||
// check and was preserved because its live session was verified.
|
||||
// The guard path must actually have run and chosen preserve over replace:
|
||||
// the daemon failed the health check yet was kept because its live session
|
||||
// was verified. Match the stable "preserve…daemon…health check" concepts
|
||||
// (not the exact wording) so a benign log reword doesn't flake, and
|
||||
// confirm the replace path stayed off.
|
||||
await expect
|
||||
.poll(() => stderrLines.join(''), { timeout: 10_000 })
|
||||
.toContain('Preserving daemon that failed the health check')
|
||||
.toMatch(/preserv\w*\s+daemon[^\n]*health check/i)
|
||||
expect(stderrLines.join('')).not.toMatch(/\breplacing daemon\b/i)
|
||||
expect(readDaemonPid(session.userDataDir)).toBe(daemonPid)
|
||||
// Why: a killed daemon cold-restores scrollback from history, so the
|
||||
// marker text alone cannot distinguish a live session from a dead one.
|
||||
|
|
|
|||
|
|
@ -34,9 +34,19 @@ type LaunchedOrca = {
|
|||
page: Page
|
||||
}
|
||||
|
||||
type LaunchOptions = {
|
||||
/**
|
||||
* Called for each chunk the relaunched main process writes to stderr. The
|
||||
* listener is attached before `firstWindow()` resolves so main-process
|
||||
* startup logs (e.g. the daemon health-check guard) can't be emitted before
|
||||
* the test starts capturing.
|
||||
*/
|
||||
onStderr?: (chunk: string) => void
|
||||
}
|
||||
|
||||
type RestartSession = {
|
||||
userDataDir: string
|
||||
launch: () => Promise<LaunchedOrca>
|
||||
launch: (options?: LaunchOptions) => Promise<LaunchedOrca>
|
||||
/** Gracefully close a launch, letting beforeunload flush session state. */
|
||||
close: (app: ElectronApplication) => Promise<void>
|
||||
/** Remove the shared userDataDir after the test is done. */
|
||||
|
|
@ -137,7 +147,7 @@ export function createRestartSession(
|
|||
`${JSON.stringify(getE2ECompletedOnboardingProfile(), null, 2)}\n`
|
||||
)
|
||||
|
||||
const launch = async (): Promise<LaunchedOrca> => {
|
||||
const launch = async (options?: LaunchOptions): Promise<LaunchedOrca> => {
|
||||
runtimeWsPort ??= await reserveRestartRuntimeWsPort()
|
||||
const app = await electron.launch({
|
||||
args: getOrcaElectronLaunchArgs(mainPath, headful),
|
||||
|
|
@ -146,6 +156,12 @@ export function createRestartSession(
|
|||
ORCA_E2E_RUNTIME_WS_PORT: String(runtimeWsPort)
|
||||
}
|
||||
})
|
||||
// Why: attach before firstWindow — the main-process daemon guard can emit
|
||||
// its decision line during startup, before the renderer window is ready.
|
||||
if (options?.onStderr) {
|
||||
const onStderr = options.onStderr
|
||||
app.process().stderr?.on('data', (chunk: Buffer) => onStderr(chunk.toString()))
|
||||
}
|
||||
try {
|
||||
const resolvedHome = await app.evaluate(({ app }) => app.getPath('home'))
|
||||
assertElectronResolvedIsolatedHome(resolvedHome, homeIsolation)
|
||||
|
|
|
|||
Loading…
Reference in New Issue