diff --git a/packages/driver/src/cypress/runner.js b/packages/driver/src/cypress/runner.js index c77a4e8b872b..ab8f6a6625c8 100644 --- a/packages/driver/src/cypress/runner.js +++ b/packages/driver/src/cypress/runner.js @@ -832,7 +832,6 @@ const create = (specWindow, mocha, Cypress, cy) => { } // hold onto the _runnables for faster lookup later - let _stopped = false let _test = null let _tests = [] let _testsById = {} @@ -932,8 +931,13 @@ const create = (specWindow, mocha, Cypress, cy) => { return _runner.run((failures) => { // if we happen to make it all the way through - // the run, then just set _stopped to true here - _stopped = true + // the run, then just set _runner.stopped to true here + _runner.stopped = true + + // remove all the listeners + // so no more events fire + // since a test failure may 'leak' after a run completes + _runner.removeAllListeners() // TODO this functions is not correctly // synchronized with the 'end' event that @@ -1183,11 +1187,11 @@ const create = (specWindow, mocha, Cypress, cy) => { }, stop () { - if (_stopped) { + if (_runner.stopped) { return } - _stopped = true + _runner.stopped = true // abort the run _runner.abort() @@ -1200,7 +1204,7 @@ const create = (specWindow, mocha, Cypress, cy) => { // remove all the listeners // so no more events fire - return _runner.removeAllListeners() + _runner.removeAllListeners() }, getDisplayPropsForLog: $Log.getDisplayProps, diff --git a/packages/runner/cypress/integration/reporter.hooks.spec.js b/packages/runner/cypress/integration/reporter.hooks.spec.js index 9b58c767b7e1..90ea52a664c0 100644 --- a/packages/runner/cypress/integration/reporter.hooks.spec.js +++ b/packages/runner/cypress/integration/reporter.hooks.spec.js @@ -119,4 +119,35 @@ describe('hooks', function () { }) }) }) + + // https://github.com/cypress-io/cypress/issues/8189 + it('can rerun without timeout error leaking into next run (due to run restart)', () => { + runIsolatedCypress(() => { + const top = window.parent + + top.count = top.count || 0 + + Cypress.config('defaultCommandTimeout', 50) + afterEach(function () { + assert(true, `run ${top.count}`) + }) + + describe('s1', () => { + it('foo', () => { + cy.once('test:after:run', () => { + if (!top.count) { + requestAnimationFrame(() => { + window.parent.eventManager.reporterBus.emit('runner:restart') + }) + } + + top.count++ + }) + }) + }) + }) + + // wait until spec has run twice (due to one reload) + cy.window().its('count').should('eq', 2) + }) }) diff --git a/packages/runner/cypress/support/helpers.js b/packages/runner/cypress/support/helpers.js index a1d0d0c39f13..5ecabd962046 100644 --- a/packages/runner/cypress/support/helpers.js +++ b/packages/runner/cypress/support/helpers.js @@ -188,9 +188,14 @@ function createCypress () { }) }) - cy.spy(cy.state('window').console, 'log').as('console_log') - cy.spy(cy.state('window').console, 'error').as('console_error') - + // TODO: clean this up, sinon doesn't like wrapping things multiple times + // and this catches that error + try { + cy.spy(cy.state('window').console, 'log').as('console_log') + cy.spy(cy.state('window').console, 'error').as('console_error') + } catch (_e) { + // console was already wrapped, noop + } onInitializedListeners.forEach((fn) => fn(autCypress)) onInitializedListeners = []