From 10fdd7b9f837f65fdf2f06418a42d9d2b2b40f6d Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Mon, 15 Feb 2021 15:56:31 +0000 Subject: [PATCH] fix: use app.whenReady and remove delay race for electron startup (#15075) Co-authored-by: Thorsten Lorenz --- .../__snapshots__/spec_writer_spec.ts.js | 68 ------------------- packages/server/lib/modes/interactive-e2e.js | 20 +----- packages/server/lib/modes/run.js | 17 +++-- packages/server/lib/util/electron-app.js | 40 ----------- .../test/support/helpers/electron_stub.js | 1 + .../test/unit/modes/interactive_spec.js | 2 +- 6 files changed, 16 insertions(+), 132 deletions(-) diff --git a/packages/server/__snapshots__/spec_writer_spec.ts.js b/packages/server/__snapshots__/spec_writer_spec.ts.js index a893ab7c4130..829ce0ad9faf 100644 --- a/packages/server/__snapshots__/spec_writer_spec.ts.js +++ b/packages/server/__snapshots__/spec_writer_spec.ts.js @@ -97,39 +97,6 @@ describe('top level suite', () => { ` -exports['lib/util/spec_writer #appendCommandsToTest can add commands to an existing test defined with it.only 1'] = ` -describe('top level suite', () => { - describe('inner suite with describe', () => { - it('test with it', () => { - cy.get('.btn').click() - }) - - specify('test with specify', () => { - cy.get('.btn').click() - }) - - // eslint-disable-next-line mocha/no-exclusive-tests - it.only('test with it.only', () => { - cy.get('.btn').click() - /* ==== Generated with Cypress Studio ==== */ - cy.get('.input').type('typed text'); - cy.get('.btn').click(); - /* ==== End Cypress Studio ==== */ - }) - }) - - context('inner suite with context', () => { - - }) - - // eslint-disable-next-line mocha/no-exclusive-tests - describe.only('inner suite with describe.only', () => { - - }) -}) - -` - exports['lib/util/spec_writer #createNewTestInSuite can create a new test in a suite defined with describe 1'] = ` describe('top level suite', () => { describe('inner suite with describe', () => { @@ -202,41 +169,6 @@ describe('top level suite', () => { ` -exports['lib/util/spec_writer #createNewTestInSuite can create a new test in a suite defined with describe.only 1'] = ` -describe('top level suite', () => { - describe('inner suite with describe', () => { - it('test with it', () => { - cy.get('.btn').click() - }) - - specify('test with specify', () => { - cy.get('.btn').click() - }) - - // eslint-disable-next-line mocha/no-exclusive-tests - it.only('test with it.only', () => { - cy.get('.btn').click() - }) - }) - - context('inner suite with context', () => { - - }) - - // eslint-disable-next-line mocha/no-exclusive-tests - describe.only('inner suite with describe.only', () => { - /* === Test Created with Cypress Studio === */ - it('test added to describe.only', function() { - /* ==== Generated with Cypress Studio ==== */ - cy.get('.input').type('typed text'); - cy.get('.btn').click(); - /* ==== End Cypress Studio ==== */ - }); - }) -}) - -` - exports['lib/util/spec_writer #appendCommandsToTest can add commands to an existing test defined with it only 1'] = ` describe('top level suite', () => { describe('inner suite with describe', () => { diff --git a/packages/server/lib/modes/interactive-e2e.js b/packages/server/lib/modes/interactive-e2e.js index 71406a72c4dd..572108c1db49 100644 --- a/packages/server/lib/modes/interactive-e2e.js +++ b/packages/server/lib/modes/interactive-e2e.js @@ -3,9 +3,7 @@ const os = require('os') const EE = require('events') const { app } = require('electron') const image = require('electron').nativeImage -const Promise = require('bluebird') const cyIcons = require('@cypress/icons') -const electronApp = require('../util/electron-app') const savedState = require('../saved_state') const menu = require('../gui/menu') const Events = require('../gui/events') @@ -112,21 +110,9 @@ module.exports = { }) }, - run (options) { - const waitForReady = () => { - return new Promise((resolve, reject) => { - return app.on('ready', resolve) - }) - } + async run (options) { + await app.whenReady() - electronApp.allowRendererProcessReuse() - - return Promise.any([ - waitForReady(), - Promise.delay(500), - ]) - .then(() => { - return this.ready(options) - }) + return this.ready(options) }, } diff --git a/packages/server/lib/modes/run.js b/packages/server/lib/modes/run.js index 888f760ab9af..230d6c3b7256 100644 --- a/packages/server/lib/modes/run.js +++ b/packages/server/lib/modes/run.js @@ -1,5 +1,6 @@ /* eslint-disable no-console, @cypress/dev/arrow-body-multiline-braces */ const _ = require('lodash') +const { app } = require('electron') const la = require('lazy-ass') const pkg = require('@packages/root') const path = require('path') @@ -27,7 +28,6 @@ const newlines = require('../util/newlines') const terminal = require('../util/terminal') const specsUtil = require('../util/specs') const humanTime = require('../util/human_time') -const electronApp = require('../util/electron-app') const settings = require('../util/settings') const chromePolicyCheck = require('../util/chrome_policy_check') const experiments = require('../experiments') @@ -1557,11 +1557,16 @@ module.exports = { }) }, - run (options) { - return electronApp - .waitForReady() - .then(() => { - return this.ready(options) + async run (options) { + // electron >= 5.0.0 will exit the app if all browserwindows are closed, + // this is obviously undesirable in run mode + // https://github.com/cypress-io/cypress/pull/4720#issuecomment-514316695 + app.on('window-all-closed', () => { + debug('all BrowserWindows closed, not exiting') }) + + await app.whenReady() + + return this.ready(options) }, } diff --git a/packages/server/lib/util/electron-app.js b/packages/server/lib/util/electron-app.js index 462ca5019b72..29a5f0e43af0 100644 --- a/packages/server/lib/util/electron-app.js +++ b/packages/server/lib/util/electron-app.js @@ -8,53 +8,13 @@ const scale = () => { } } -const allowRendererProcessReuse = () => { - const { app } = require('electron') - - // @see https://github.com/electron/electron/issues/18397 - // NOTE: in Electron 9, this can be removed, since it will be the new default - app.allowRendererProcessReuse = true -} - -// NOTE: this function is only called in run mode -const waitForReady = () => { - const debug = require('debug')('cypress:server:electron-app') - - const Promise = require('bluebird') - const { app } = require('electron') - - allowRendererProcessReuse() - - // electron >= 5.0.0 will exit the app if all browserwindows are closed, - // this is obviously undesirable in run mode - // https://github.com/cypress-io/cypress/pull/4720#issuecomment-514316695 - app.on('window-all-closed', () => { - debug('all BrowserWindows closed, not exiting') - }) - - const onReadyEvent = () => { - return new Promise((resolve) => { - app.on('ready', resolve) - }) - } - - return Promise.any([ - onReadyEvent(), - Promise.delay(500), - ]) -} - const isRunning = () => { // are we in the electron or the node process? return Boolean(process.versions && process.versions.electron) } module.exports = { - allowRendererProcessReuse, - scale, - waitForReady, - isRunning, } diff --git a/packages/server/test/support/helpers/electron_stub.js b/packages/server/test/support/helpers/electron_stub.js index f88ab1733aa7..da4ef9681b7f 100644 --- a/packages/server/test/support/helpers/electron_stub.js +++ b/packages/server/test/support/helpers/electron_stub.js @@ -20,6 +20,7 @@ module.exports = { appendArgument () {}, }, disableHardwareAcceleration () {}, + async whenReady () {}, }, systemPreferences: { isDarkMode () {}, diff --git a/packages/server/test/unit/modes/interactive_spec.js b/packages/server/test/unit/modes/interactive_spec.js index e08200c91f62..cd774cab9625 100644 --- a/packages/server/test/unit/modes/interactive_spec.js +++ b/packages/server/test/unit/modes/interactive_spec.js @@ -167,7 +167,7 @@ describe('gui/interactive', () => { context('.run', () => { beforeEach(() => { - sinon.stub(electron.app, 'on').withArgs('ready').yieldsAsync() + sinon.stub(electron.app, 'whenReady').resolves() }) it('calls ready with options', () => {