From bf22e30a0ae05953dcadc809abce7e472020dce3 Mon Sep 17 00:00:00 2001 From: Thorsten Lorenz Date: Fri, 12 Feb 2021 09:10:30 -0500 Subject: [PATCH 1/5] init: fixed startup delay issue This change fixes an issue that caused the startup to be delayed by 500ms. We used `app.on('ready')` without checking `app.isReady()`, however the 'ready' event may already have fired at this point and thus we never resolved the Promise waiting for it. Using `app.whenReady` fixes this and now that Promise resolves before the delay expires. Related links: https://www.electronjs.org/docs/api/app#event-ready https://www.electronjs.org/docs/api/app#appwhenready --- packages/server/lib/modes/interactive-e2e.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/server/lib/modes/interactive-e2e.js b/packages/server/lib/modes/interactive-e2e.js index 71406a72c4dd..18930d8ebbfe 100644 --- a/packages/server/lib/modes/interactive-e2e.js +++ b/packages/server/lib/modes/interactive-e2e.js @@ -113,16 +113,10 @@ module.exports = { }, run (options) { - const waitForReady = () => { - return new Promise((resolve, reject) => { - return app.on('ready', resolve) - }) - } - electronApp.allowRendererProcessReuse() return Promise.any([ - waitForReady(), + app.whenReady(), Promise.delay(500), ]) .then(() => { From 86d5406654ca7ba4a56c676f1b644ffa428f60ff Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Fri, 12 Feb 2021 10:15:12 -0500 Subject: [PATCH 2/5] skip the promise.delay --- packages/server/lib/modes/interactive-e2e.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/server/lib/modes/interactive-e2e.js b/packages/server/lib/modes/interactive-e2e.js index 18930d8ebbfe..f548dde0fd12 100644 --- a/packages/server/lib/modes/interactive-e2e.js +++ b/packages/server/lib/modes/interactive-e2e.js @@ -3,7 +3,6 @@ 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') @@ -112,15 +111,11 @@ module.exports = { }) }, - run (options) { + async run (options) { electronApp.allowRendererProcessReuse() - return Promise.any([ - app.whenReady(), - Promise.delay(500), - ]) - .then(() => { - return this.ready(options) - }) + await app.whenReady() + + return this.ready(options) }, } From 5533bbba9ef9c8f494623172e2c02d09b1f48d4e Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Fri, 12 Feb 2021 10:39:32 -0500 Subject: [PATCH 3/5] fix unit/integration specs --- packages/server/test/integration/cypress_spec.js | 1 + packages/server/test/unit/modes/interactive_spec.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/server/test/integration/cypress_spec.js b/packages/server/test/integration/cypress_spec.js index 033173944791..22252fb3c7a2 100644 --- a/packages/server/test/integration/cypress_spec.js +++ b/packages/server/test/integration/cypress_spec.js @@ -124,6 +124,7 @@ describe('lib/cypress', () => { sinon.stub(videoCapture, 'start').resolves({}) sinon.stub(plugins, 'init').resolves(undefined) sinon.stub(electronApp, 'isRunning').returns(true) + sinon.stub(electronApp, 'whenReady').resolves() sinon.stub(extension, 'setHostAndPath').resolves() sinon.stub(launcher, 'detect').resolves(TYPICAL_BROWSERS) sinon.stub(process, 'exit') 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', () => { From 3c46bb87a0aaf7037638b2592abe9b1b77ea3d63 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Fri, 12 Feb 2021 10:57:59 -0500 Subject: [PATCH 4/5] same for run + open-ct --- packages/server/lib/modes/interactive-e2e.js | 3 --- packages/server/lib/modes/run.js | 17 +++++++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/server/lib/modes/interactive-e2e.js b/packages/server/lib/modes/interactive-e2e.js index f548dde0fd12..572108c1db49 100644 --- a/packages/server/lib/modes/interactive-e2e.js +++ b/packages/server/lib/modes/interactive-e2e.js @@ -4,7 +4,6 @@ const EE = require('events') const { app } = require('electron') const image = require('electron').nativeImage 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,8 +111,6 @@ module.exports = { }, async run (options) { - electronApp.allowRendererProcessReuse() - await app.whenReady() 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) }, } From 7d66091b18fa039a0552d83036894bae1ec39ca1 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Fri, 12 Feb 2021 10:58:08 -0500 Subject: [PATCH 5/5] snapshots and mocks --- .../__snapshots__/spec_writer_spec.ts.js | 68 ------------------- packages/server/lib/util/electron-app.js | 40 ----------- .../server/test/integration/cypress_spec.js | 1 - .../test/support/helpers/electron_stub.js | 1 + 4 files changed, 1 insertion(+), 109 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/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/integration/cypress_spec.js b/packages/server/test/integration/cypress_spec.js index 22252fb3c7a2..033173944791 100644 --- a/packages/server/test/integration/cypress_spec.js +++ b/packages/server/test/integration/cypress_spec.js @@ -124,7 +124,6 @@ describe('lib/cypress', () => { sinon.stub(videoCapture, 'start').resolves({}) sinon.stub(plugins, 'init').resolves(undefined) sinon.stub(electronApp, 'isRunning').returns(true) - sinon.stub(electronApp, 'whenReady').resolves() sinon.stub(extension, 'setHostAndPath').resolves() sinon.stub(launcher, 'detect').resolves(TYPICAL_BROWSERS) sinon.stub(process, 'exit') 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 () {},