test(e2e): retry the crash probe's main-process reads through the transient-evaluate helper (#24479)

expect.poll does not retry a thrown read, so one spurious 'Resulting promise was
garbage collected' from Electron's main evaluate failed the crash-recovery test.
This commit is contained in:
Brennan Benson
2026-10-01 18:06:42 -07:00
committed by GitHub
parent 4e919f3b5a
commit 0d2300ca8e
@@ -17,6 +17,7 @@
import type { ElectronApplication } from '@stablyai/playwright-test'
import { test, expect } from './helpers/orca-app'
import { retryTransientMainEvaluate } from './helpers/electron-main-evaluate-retry'
import { ensureTerminalVisible, waitForActiveWorktree, waitForSessionReady } from './helpers/store'
import {
discoverActivePtyId,
@@ -59,23 +60,27 @@ declare global {
* a previous arm write only to their own superseded probe object.
*/
async function armMainProcessCrashProbe(electronApp: ElectronApplication): Promise<void> {
await electronApp.evaluate(({ BrowserWindow }) => {
const probe: CrashProbe = { processGone: null, recoveredLoads: 0 }
globalThis.__crashProbe = probe
for (const win of BrowserWindow.getAllWindows()) {
win.webContents.on('render-process-gone', (_event, details) => {
probe.processGone = { reason: details.reason, exitCode: details.exitCode ?? -1 }
})
win.webContents.on('did-finish-load', () => {
probe.recoveredLoads += 1
})
}
})
// Safe to repeat: re-arming supersedes the probe a collected attempt may have installed.
await retryTransientMainEvaluate(() =>
electronApp.evaluate(({ BrowserWindow }) => {
const probe: CrashProbe = { processGone: null, recoveredLoads: 0 }
globalThis.__crashProbe = probe
for (const win of BrowserWindow.getAllWindows()) {
win.webContents.on('render-process-gone', (_event, details) => {
probe.processGone = { reason: details.reason, exitCode: details.exitCode ?? -1 }
})
win.webContents.on('did-finish-load', () => {
probe.recoveredLoads += 1
})
}
})
)
}
async function readMainProcessCrashProbe(electronApp: ElectronApplication): Promise<CrashProbe> {
return electronApp.evaluate(
() => globalThis.__crashProbe ?? { processGone: null, recoveredLoads: 0 }
// Why: expect.poll does not retry a thrown read, and Electron's main evaluate can be collected spuriously.
return retryTransientMainEvaluate(() =>
electronApp.evaluate(() => globalThis.__crashProbe ?? { processGone: null, recoveredLoads: 0 })
)
}