diff --git a/src/server/electron.ts b/src/server/electron.ts index df0b35bbce..12b94f4351 100644 --- a/src/server/electron.ts +++ b/src/server/electron.ts @@ -71,7 +71,10 @@ export class ElectronApplication extends EventEmitter { super(); this._apiLogger = logger.api; this._browserContext = browser._defaultContext as CRBrowserContext; - this._browserContext.on(Events.BrowserContext.Close, () => this.emit(ElectronEvents.ElectronApplication.Close)); + this._browserContext.on(Events.BrowserContext.Close, () => { + // Emit application closed after context closed. + Promise.resolve().then(() => this.emit(ElectronEvents.ElectronApplication.Close)); + }); this._browserContext.on(Events.BrowserContext.Page, event => this._onPage(event)); this._nodeConnection = nodeConnection; this._nodeSession = nodeConnection.rootSession; @@ -125,8 +128,10 @@ export class ElectronApplication extends EventEmitter { } async close() { + const closed = this.waitForEvent(ElectronEvents.ElectronApplication.Close); await this.evaluate(({ app }) => app.quit()); this._nodeConnection.close(); + await closed; } async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise { @@ -188,10 +193,7 @@ export class Electron { cwd: options.cwd, tempDirectories: [], attemptToGracefullyClose: () => app!.close(), - onExit: (exitCode, signal) => { - if (app) - app.emit(ElectronEvents.ElectronApplication.Close, exitCode, signal); - }, + onExit: (exitCode, signal) => {}, }); const nodeMatch = await waitForLine(progress, launchedProcess, launchedProcess.stderr, /^Debugger listening on (ws:\/\/.*)$/); diff --git a/test/electron/electron.jest.js b/test/electron/electron.jest.js index b80da4025c..f0e972391b 100644 --- a/test/electron/electron.jest.js +++ b/test/electron/electron.jest.js @@ -41,6 +41,20 @@ registerFixture('window', async ({application}, test) => { }); describe.skip(!CHROMIUM)('Electron', function() { + it('should fire close event', async ({ playwright }) => { + const electronPath = path.join(__dirname, '..', '..', 'node_modules', '.bin', electronName); + const application = await playwright.electron.launch(electronPath, { + args: [path.join(__dirname, 'testApp.js')], + }); + const events = []; + application.on('close', () => events.push('application')); + application.context().on('close', () => events.push('context')); + await application.close(); + expect(events.join('|')).toBe('context|application'); + // Give it some time to fire more events - there should not be any. + await new Promise(f => setTimeout(f, 1000)); + expect(events.join('|')).toBe('context|application'); + }); it('should script application', async ({ application }) => { const appPath = await application.evaluate(async ({ app }) => app.getAppPath()); expect(appPath).toContain('electron');