diff --git a/apps/electron-backend-e2e/src/electron-test-fixtures.ts b/apps/electron-backend-e2e/src/electron-test-fixtures.ts index fb45b4925..48038d7d2 100644 --- a/apps/electron-backend-e2e/src/electron-test-fixtures.ts +++ b/apps/electron-backend-e2e/src/electron-test-fixtures.ts @@ -157,6 +157,7 @@ export async function launchElectronApp( NODE_ENV: 'test', }, }); + attachElectronProcessDiagnostics(electronApp); const mainWindow = await findMainWindow(electronApp); await waitForAppReady(mainWindow); @@ -170,6 +171,28 @@ export async function launchElectronApp( }; } +function attachElectronProcessDiagnostics(electronApp: ElectronApplication): void { + if (!process.env['CI']) { + return; + } + + const childProcess = electronApp.process(); + + childProcess.stdout?.on('data', (chunk: Buffer) => { + console.log(`[electron stdout] ${chunk.toString().trimEnd()}`); + }); + childProcess.stderr?.on('data', (chunk: Buffer) => { + console.error(`[electron stderr] ${chunk.toString().trimEnd()}`); + }); + childProcess.once('exit', (code, signal) => { + console.log( + `[electron process exit] code=${code ?? ''} signal=${ + signal ?? '' + }` + ); + }); +} + export async function closeElectronApp( app: LaunchedElectronApp ): Promise { diff --git a/apps/electron-backend/src/main.ts b/apps/electron-backend/src/main.ts index d630b351b..518fe9baf 100644 --- a/apps/electron-backend/src/main.ts +++ b/apps/electron-backend/src/main.ts @@ -93,13 +93,6 @@ export default class Main { }); AppUpdateEvents.bootstrapAppUpdateEvents(appUpdateService); - // Initialize database before other events - await initDatabase(); - - if (isStartupTraceEnabled()) { - trace('startup', 'init-database:done'); - } - ElectronEvents.bootstrapElectronEvents(); WindowEvents.bootstrapWindowEvents(); EmbeddedMpvEvents.bootstrapEmbeddedMpvEvents(); @@ -117,11 +110,6 @@ export default class Main { if (App.mainWindow) { setDownloadsMainWindow(App.mainWindow); } - await resetStaleDownloads(); - - if (isStartupTraceEnabled()) { - trace('startup', 'reset-stale-downloads:done'); - } // Load the renderer only after IPC handlers are registered. On slower // Linux CI hosts the renderer can otherwise invoke Electron bridge IPC @@ -129,6 +117,22 @@ export default class Main { await App.loadMainWindow(); void appUpdateService.checkForUpdatesOnStartup(); + // Initialize the database after the first renderer load is underway so + // Linux Electron E2E can observe a BrowserWindow even when SQLite + // startup or download recovery is slow. IPC handlers call getDatabase() + // lazily and share the same initialization promise. + await initDatabase(); + + if (isStartupTraceEnabled()) { + trace('startup', 'init-database:done'); + } + + await resetStaleDownloads(); + + if (isStartupTraceEnabled()) { + trace('startup', 'reset-stale-downloads:done'); + } + if (isStartupTraceEnabled()) { trace('startup', 'bootstrap-events:done'); }