From 9f3420df6a4916574b38612c1e8f0e09f6e7dcc1 Mon Sep 17 00:00:00 2001 From: Ryan Manuel Date: Thu, 22 May 2025 20:57:40 -0500 Subject: [PATCH 1/8] fix: ensure that Cypress.stop fires all end events appropriately --- packages/driver/src/cypress/runner.ts | 28 ++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/driver/src/cypress/runner.ts b/packages/driver/src/cypress/runner.ts index d4c1b77ff9f9..0c7e1337fa52 100644 --- a/packages/driver/src/cypress/runner.ts +++ b/packages/driver/src/cypress/runner.ts @@ -556,6 +556,21 @@ const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, get testAfterRun(test, Cypress) await testAfterRunAsync(test, Cypress) + + if (_runner.stopped) { + // abort the run + _runner.abort() + + // emit the final 'end' event + // since our reporter depends on this event + // and mocha may never fire this because our + // runnable may never finish + _runner.emit('end') + + // remove all the listeners + // so no more events fire + _runner.removeAllListeners() + } })] return newArgs @@ -1916,19 +1931,6 @@ export default { } _runner.stopped = true - - // abort the run - _runner.abort() - - // emit the final 'end' event - // since our reporter depends on this event - // and mocha may never fire this because our - // runnable may never finish - _runner.emit('end') - - // remove all the listeners - // so no more events fire - _runner.removeAllListeners() }, getDisplayPropsForLog: LogUtils.getDisplayProps, From 097260c0d0e8c9cad08ed4096d2680e45f70a6d5 Mon Sep 17 00:00:00 2001 From: Ryan Manuel Date: Fri, 23 May 2025 07:27:54 -0500 Subject: [PATCH 2/8] improvement --- packages/driver/src/cypress/runner.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/driver/src/cypress/runner.ts b/packages/driver/src/cypress/runner.ts index 0c7e1337fa52..a209d8c3422c 100644 --- a/packages/driver/src/cypress/runner.ts +++ b/packages/driver/src/cypress/runner.ts @@ -1931,6 +1931,23 @@ export default { } _runner.stopped = true + + // if the current runnable is a test, then we need to abort the run + // immediately. Otherwise, we will wait for our hook logic to finish + if (_runner.currentRunnable.type === 'test') { + // abort the run + _runner.abort() + + // emit the final 'end' event + // since our reporter depends on this event + // and mocha may never fire this because our + // runnable may never finish + _runner.emit('end') + + // remove all the listeners + // so no more events fire + _runner.removeAllListeners() + } }, getDisplayPropsForLog: LogUtils.getDisplayProps, From 1c9f3e90590f345ddb0ba08a4d15301adb518c4f Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Wed, 4 Jun 2025 11:23:06 -0600 Subject: [PATCH 3/8] add system-tests --- .../__snapshots__/cypress-stop.spec.ts.js | 265 ++++++++++++++++++ .../projects/cypres-stop/cypress.config.js | 5 + .../cypress/e2e/cypress-stop-after.cy.js | 18 ++ .../cypress/e2e/cypress-stop-afterEach.cy.js | 22 ++ .../cypress/e2e/cypress-stop-before.cy.js | 22 ++ .../cypress/e2e/cypress-stop-beforeEach.cy.js | 22 ++ .../cypress/e2e/cypress-stop-test.cy.js | 15 + .../cypres-stop/cypress/support/e2e.js | 21 ++ .../projects/cypres-stop/package.json | 3 + system-tests/test/cypress-stop.spec.ts | 95 +++++++ 10 files changed, 488 insertions(+) create mode 100644 system-tests/__snapshots__/cypress-stop.spec.ts.js create mode 100644 system-tests/projects/cypres-stop/cypress.config.js create mode 100644 system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-after.cy.js create mode 100644 system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-afterEach.cy.js create mode 100644 system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-before.cy.js create mode 100644 system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-beforeEach.cy.js create mode 100644 system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js create mode 100644 system-tests/projects/cypres-stop/cypress/support/e2e.js create mode 100644 system-tests/projects/cypres-stop/package.json create mode 100644 system-tests/test/cypress-stop.spec.ts diff --git a/system-tests/__snapshots__/cypress-stop.spec.ts.js b/system-tests/__snapshots__/cypress-stop.spec.ts.js new file mode 100644 index 000000000000..3a91c02d6e1d --- /dev/null +++ b/system-tests/__snapshots__/cypress-stop.spec.ts.js @@ -0,0 +1,265 @@ +exports['e2e Cypress.stop() / stops execution when called in before'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 1 found (cypress-stop-before.cy.js) │ + │ Searched: cypress/e2e/cypress-stop-before.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: cypress-stop-before.cy.js (1 of 1) + + + Cypress.stop() in before + + 0 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 2 │ + │ Passing: 0 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 2 │ + │ Screenshots: 0 │ + │ Video: false │ + │ Duration: X seconds │ + │ Spec Ran: cypress-stop-before.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✔ cypress-stop-before.cy.js XX:XX 2 - - - 2 │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✔ All specs passed! XX:XX 2 - - - 2 + + +` + +exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 1 found (cypress-stop-beforeEach.cy.js) │ + │ Searched: cypress/e2e/cypress-stop-beforeEach.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: cypress-stop-beforeEach.cy.js (1 of 1) + + + Cypress.stop() in beforeEach + + 0 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 2 │ + │ Passing: 0 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 2 │ + │ Screenshots: 0 │ + │ Video: false │ + │ Duration: X seconds │ + │ Spec Ran: cypress-stop-beforeEach.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✔ cypress-stop-beforeEach.cy.js XX:XX 2 - - - 2 │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✔ All specs passed! XX:XX 2 - - - 2 + + +` + +exports['e2e Cypress.stop() / stops execution when called in test'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 1 found (cypress-stop-test.cy.js) │ + │ Searched: cypress/e2e/cypress-stop-test.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: cypress-stop-test.cy.js (1 of 1) + + + Cypress.stop() in test + ✓ should run this test + + 1 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 3 │ + │ Passing: 1 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 2 │ + │ Screenshots: 0 │ + │ Video: false │ + │ Duration: X seconds │ + │ Spec Ran: cypress-stop-test.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✔ cypress-stop-test.cy.js XX:XX 3 1 - - 2 │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✔ All specs passed! XX:XX 3 1 - - 2 + + +` + +exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 1 found (cypress-stop-afterEach.cy.js) │ + │ Searched: cypress/e2e/cypress-stop-afterEach.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: cypress-stop-afterEach.cy.js (1 of 1) + + + Cypress.stop() in afterEach + + 0 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 2 │ + │ Passing: 0 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 2 │ + │ Screenshots: 0 │ + │ Video: false │ + │ Duration: X seconds │ + │ Spec Ran: cypress-stop-afterEach.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✔ cypress-stop-afterEach.cy.js XX:XX 2 - - - 2 │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✔ All specs passed! XX:XX 2 - - - 2 + + +` + +exports['e2e Cypress.stop() / stops execution when called in after'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 1 found (cypress-stop-after.cy.js) │ + │ Searched: cypress/e2e/cypress-stop-after.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: cypress-stop-after.cy.js (1 of 1) + + + Cypress.stop() in after + + 0 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 1 │ + │ Passing: 0 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 1 │ + │ Screenshots: 0 │ + │ Video: false │ + │ Duration: X seconds │ + │ Spec Ran: cypress-stop-after.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✔ cypress-stop-after.cy.js XX:XX 1 - - - 1 │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✔ All specs passed! XX:XX 1 - - - 1 + + +` diff --git a/system-tests/projects/cypres-stop/cypress.config.js b/system-tests/projects/cypres-stop/cypress.config.js new file mode 100644 index 000000000000..b0bbee46eb89 --- /dev/null +++ b/system-tests/projects/cypres-stop/cypress.config.js @@ -0,0 +1,5 @@ +module.exports = { + e2e: { + setupNodeEvents (on, config) {}, + }, +} diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-after.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-after.cy.js new file mode 100644 index 000000000000..76acacb63a23 --- /dev/null +++ b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-after.cy.js @@ -0,0 +1,18 @@ +describe('Cypress.stop() in after', () => { + after(() => { + console.log('after 1') + }) + + after(() => { + Cypress.stop() + console.log('after 2') + }) + + after(() => { + console.log('after 3') + }) + + it('should run this test', () => { + cy.url().should('equal', 'about:blank') + }) +}) diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-afterEach.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-afterEach.cy.js new file mode 100644 index 000000000000..39d763b8cdf1 --- /dev/null +++ b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-afterEach.cy.js @@ -0,0 +1,22 @@ +describe('Cypress.stop() in afterEach', () => { + afterEach(() => { + console.log('afterEach 1') + }) + + afterEach(() => { + Cypress.stop() + console.log('afterEach 2') + }) + + afterEach(() => { + console.log('afterEach 3') + }) + + it('should run this test', () => { + cy.url().should('equal', 'about:blank') + }) + + it('should not run this test', () => { + throw new Error('This test should not run') + }) +}) diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-before.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-before.cy.js new file mode 100644 index 000000000000..c76714040330 --- /dev/null +++ b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-before.cy.js @@ -0,0 +1,22 @@ +describe('Cypress.stop() in before', () => { + before(() => { + console.log('before 1') + }) + + before(() => { + Cypress.stop() + console.log('before 2') + }) + + before(() => { + console.log('before 3') + }) + + it('should not run this test', () => { + throw new Error('This test should not run') + }) + + it('should also not run this test', () => { + throw new Error('This test should not run') + }) +}) diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-beforeEach.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-beforeEach.cy.js new file mode 100644 index 000000000000..7de0784a106a --- /dev/null +++ b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-beforeEach.cy.js @@ -0,0 +1,22 @@ +describe('Cypress.stop() in beforeEach', () => { + beforeEach(() => { + console.log('beforeEach 1') + }) + + beforeEach(() => { + Cypress.stop() + console.log('beforeEach 2') + }) + + beforeEach(() => { + console.log('beforeEach 3') + }) + + it('should not run this test', () => { + throw new Error('This test should not run') + }) + + it('should also not run this test', () => { + throw new Error('This test should not run') + }) +}) diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js new file mode 100644 index 000000000000..cbe1ad94044e --- /dev/null +++ b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js @@ -0,0 +1,15 @@ +describe('Cypress.stop() in test', () => { + it('should run this test', () => { + console.log('test 1') + }) + + it('should stop during test execution', () => { + cy.url().should('equal', 'about:blank') + Cypress.stop() + console.log('test 2') + }) + + it('should not run this test', () => { + throw new Error('This test should not run') + }) +}) diff --git a/system-tests/projects/cypres-stop/cypress/support/e2e.js b/system-tests/projects/cypres-stop/cypress/support/e2e.js new file mode 100644 index 000000000000..f3dd37c68021 --- /dev/null +++ b/system-tests/projects/cypres-stop/cypress/support/e2e.js @@ -0,0 +1,21 @@ +Cypress.on('test:before:run:async', () => { + console.log('test:before:run:async') +}) + +Cypress.on('test:before:run', () => { + console.log('test:before:run') +}) + +Cypress.on('test:before:after:run:async', async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + console.log('test:before:after:run:async') +}) + +Cypress.on('test:after:run', () => { + console.log('test:after:run') +}) + +Cypress.on('test:after:run:async', async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + console.log('test:after:run:async') +}) diff --git a/system-tests/projects/cypres-stop/package.json b/system-tests/projects/cypres-stop/package.json new file mode 100644 index 000000000000..f9ba6239dbc5 --- /dev/null +++ b/system-tests/projects/cypres-stop/package.json @@ -0,0 +1,3 @@ +{ + "projectFixtureDirectory": "runner-specs" +} \ No newline at end of file diff --git a/system-tests/test/cypress-stop.spec.ts b/system-tests/test/cypress-stop.spec.ts new file mode 100644 index 000000000000..2ed7aa82f34f --- /dev/null +++ b/system-tests/test/cypress-stop.spec.ts @@ -0,0 +1,95 @@ +import systemTests from '../lib/system-tests' + +describe('e2e Cypress.stop()', () => { + systemTests.setup() + + systemTests.it('stops execution when called in before', { + project: 'cypres-stop', + spec: 'cypress-stop-before.cy.js', + snapshot: true, + expectedExitCode: 0, + browser: 'electron', + processEnv: { + ELECTRON_ENABLE_LOGGING: 1, + }, + onStderr: (stderr) => { + expect(stderr).to.include('before 1') + expect(stderr).to.include('before 2') + expect(stderr).to.not.include('before 3') + + return stderr + }, + }) + + systemTests.it('stops execution when called in beforeEach', { + project: 'cypres-stop', + spec: 'cypress-stop-beforeEach.cy.js', + snapshot: true, + expectedExitCode: 0, + browser: 'electron', + processEnv: { + ELECTRON_ENABLE_LOGGING: 1, + }, + onStderr: (stderr) => { + expect(stderr).to.include('beforeEach 1') + expect(stderr).to.include('beforeEach 2') + expect(stderr).to.not.include('beforeEach 3') + + return stderr + }, + }) + + systemTests.it('stops execution when called in test', { + project: 'cypres-stop', + spec: 'cypress-stop-test.cy.js', + snapshot: true, + expectedExitCode: 0, + browser: 'electron', + processEnv: { + ELECTRON_ENABLE_LOGGING: 1, + }, + onStderr: (stderr) => { + expect(stderr).to.include('test 1') + expect(stderr).to.include('test 2') + expect(stderr).to.not.include('test 3') + + return stderr + }, + }) + + systemTests.it('stops execution when called in afterEach', { + project: 'cypres-stop', + spec: 'cypress-stop-afterEach.cy.js', + snapshot: true, + expectedExitCode: 0, + browser: 'electron', + processEnv: { + ELECTRON_ENABLE_LOGGING: 1, + }, + onStderr: (stderr) => { + expect(stderr).to.include('afterEach 1') + expect(stderr).to.include('afterEach 2') + expect(stderr).to.not.include('afterEach 3') + + return stderr + }, + }) + + systemTests.it('stops execution when called in after', { + project: 'cypres-stop', + spec: 'cypress-stop-after.cy.js', + snapshot: true, + expectedExitCode: 0, + browser: 'electron', + processEnv: { + ELECTRON_ENABLE_LOGGING: 1, + }, + onStderr: (stderr) => { + expect(stderr).to.include('after 1') + expect(stderr).to.include('after 2') + expect(stderr).to.not.include('after 3') + + return stderr + }, + }) +}) From a1382794a6f0279aabbb1c54d8a261e38bba535e Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Wed, 4 Jun 2025 12:20:22 -0600 Subject: [PATCH 4/8] abort before/beforeEach --- packages/driver/src/cypress/runner.ts | 12 +++- .../__snapshots__/cypress-stop.spec.ts.js | 23 +++---- .../cypress/e2e/cypress-stop-test.cy.js | 2 +- .../cypres-stop/cypress/support/e2e.js | 3 +- system-tests/test/cypress-stop.spec.ts | 60 +++++++++++++++++++ 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/packages/driver/src/cypress/runner.ts b/packages/driver/src/cypress/runner.ts index a209d8c3422c..8a5412cd96e2 100644 --- a/packages/driver/src/cypress/runner.ts +++ b/packages/driver/src/cypress/runner.ts @@ -1932,9 +1932,15 @@ export default { _runner.stopped = true - // if the current runnable is a test, then we need to abort the run - // immediately. Otherwise, we will wait for our hook logic to finish - if (_runner.currentRunnable.type === 'test') { + // if the current runnable is a test or a before or beforeEach hook, + // then we need to abort the run immediately. Otherwise, we will wait + // for the after/afterEach hook logic to finish + const isTest = _runner.currentRunnable.type === 'test' + const isHook = _runner.currentRunnable.type === 'hook' + const hookName = isHook && getHookName(_runner.currentRunnable) + const shouldAbortImmediately = isTest || (isHook && (hookName === 'before all' || hookName === 'before each')) + + if (shouldAbortImmediately) { // abort the run _runner.abort() diff --git a/system-tests/__snapshots__/cypress-stop.spec.ts.js b/system-tests/__snapshots__/cypress-stop.spec.ts.js index 3a91c02d6e1d..0f0f6a2f7f4f 100644 --- a/system-tests/__snapshots__/cypress-stop.spec.ts.js +++ b/system-tests/__snapshots__/cypress-stop.spec.ts.js @@ -178,18 +178,19 @@ exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` Cypress.stop() in afterEach + ✓ should run this test - 0 passing + 1 passing (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Tests: 2 │ - │ Passing: 0 │ + │ Passing: 1 │ │ Failing: 0 │ │ Pending: 0 │ - │ Skipped: 2 │ + │ Skipped: 1 │ │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ @@ -204,9 +205,9 @@ exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ cypress-stop-afterEach.cy.js XX:XX 2 - - - 2 │ + │ ✔ cypress-stop-afterEach.cy.js XX:XX 2 1 - - 1 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 2 - - - 2 + ✔ All specs passed! XX:XX 2 1 - - 1 ` @@ -231,18 +232,20 @@ exports['e2e Cypress.stop() / stops execution when called in after'] = ` Cypress.stop() in after + ✓ should run this test - 0 passing + + 1 passing (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Tests: 1 │ - │ Passing: 0 │ + │ Passing: 1 │ │ Failing: 0 │ │ Pending: 0 │ - │ Skipped: 1 │ + │ Skipped: 0 │ │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ @@ -257,9 +260,9 @@ exports['e2e Cypress.stop() / stops execution when called in after'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ cypress-stop-after.cy.js XX:XX 1 - - - 1 │ + │ ✔ cypress-stop-after.cy.js XX:XX 1 1 - - - │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 1 - - - 1 + ✔ All specs passed! XX:XX 1 1 - - - ` diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js index cbe1ad94044e..2353fabf2019 100644 --- a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js +++ b/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js @@ -4,12 +4,12 @@ describe('Cypress.stop() in test', () => { }) it('should stop during test execution', () => { - cy.url().should('equal', 'about:blank') Cypress.stop() console.log('test 2') }) it('should not run this test', () => { + console.log('test 3') throw new Error('This test should not run') }) }) diff --git a/system-tests/projects/cypres-stop/cypress/support/e2e.js b/system-tests/projects/cypres-stop/cypress/support/e2e.js index f3dd37c68021..77429ccfaa1c 100644 --- a/system-tests/projects/cypres-stop/cypress/support/e2e.js +++ b/system-tests/projects/cypres-stop/cypress/support/e2e.js @@ -1,4 +1,5 @@ -Cypress.on('test:before:run:async', () => { +Cypress.on('test:before:run:async', async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)) console.log('test:before:run:async') }) diff --git a/system-tests/test/cypress-stop.spec.ts b/system-tests/test/cypress-stop.spec.ts index 2ed7aa82f34f..c5dd2aca0e57 100644 --- a/system-tests/test/cypress-stop.spec.ts +++ b/system-tests/test/cypress-stop.spec.ts @@ -17,6 +17,18 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('before 2') expect(stderr).to.not.include('before 3') + const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length + const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length + const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length + const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length + const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + + expect(beforeRunCount).to.equal(1) + expect(beforeRunAsyncCount).to.equal(1) + expect(beforeAfterRunAsyncCount).to.equal(0) + expect(afterRunCount).to.equal(0) + expect(afterRunAsyncCount).to.equal(0) + return stderr }, }) @@ -35,6 +47,18 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('beforeEach 2') expect(stderr).to.not.include('beforeEach 3') + const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length + const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length + const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length + const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length + const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + + expect(beforeRunCount).to.equal(1) + expect(beforeRunAsyncCount).to.equal(1) + expect(beforeAfterRunAsyncCount).to.equal(0) + expect(afterRunCount).to.equal(0) + expect(afterRunAsyncCount).to.equal(0) + return stderr }, }) @@ -53,6 +77,18 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('test 2') expect(stderr).to.not.include('test 3') + const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length + const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length + const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length + const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length + const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + + expect(beforeRunCount).to.equal(2) + expect(beforeRunAsyncCount).to.equal(2) + expect(beforeAfterRunAsyncCount).to.equal(1) + expect(afterRunCount).to.equal(1) + expect(afterRunAsyncCount).to.equal(1) + return stderr }, }) @@ -71,6 +107,18 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('afterEach 2') expect(stderr).to.not.include('afterEach 3') + const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length + const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length + const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length + const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length + const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + + expect(beforeRunCount).to.equal(1) + expect(beforeRunAsyncCount).to.equal(1) + expect(beforeAfterRunAsyncCount).to.equal(1) + expect(afterRunCount).to.equal(1) + expect(afterRunAsyncCount).to.equal(1) + return stderr }, }) @@ -89,6 +137,18 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('after 2') expect(stderr).to.not.include('after 3') + const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length + const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length + const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length + const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length + const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + + expect(beforeRunCount).to.equal(1) + expect(beforeRunAsyncCount).to.equal(1) + expect(beforeAfterRunAsyncCount).to.equal(1) + expect(afterRunCount).to.equal(1) + expect(afterRunAsyncCount).to.equal(1) + return stderr }, }) From 9ebb0655be5790748d9b7900f9513a4241c348c2 Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Wed, 4 Jun 2025 12:23:12 -0600 Subject: [PATCH 5/8] rename --- .../__snapshots__/cypress-stop.spec.ts.js | 50 +++++++++---------- .../{cypress-stop-after.cy.js => after.cy.js} | 0 ...s-stop-afterEach.cy.js => afterEach.cy.js} | 0 ...cypress-stop-before.cy.js => before.cy.js} | 0 ...stop-beforeEach.cy.js => beforeEach.cy.js} | 0 .../{cypress-stop-test.cy.js => test.cy.js} | 0 system-tests/test/cypress-stop.spec.ts | 10 ++-- 7 files changed, 30 insertions(+), 30 deletions(-) rename system-tests/projects/cypres-stop/cypress/e2e/{cypress-stop-after.cy.js => after.cy.js} (100%) rename system-tests/projects/cypres-stop/cypress/e2e/{cypress-stop-afterEach.cy.js => afterEach.cy.js} (100%) rename system-tests/projects/cypres-stop/cypress/e2e/{cypress-stop-before.cy.js => before.cy.js} (100%) rename system-tests/projects/cypres-stop/cypress/e2e/{cypress-stop-beforeEach.cy.js => beforeEach.cy.js} (100%) rename system-tests/projects/cypres-stop/cypress/e2e/{cypress-stop-test.cy.js => test.cy.js} (100%) diff --git a/system-tests/__snapshots__/cypress-stop.spec.ts.js b/system-tests/__snapshots__/cypress-stop.spec.ts.js index 0f0f6a2f7f4f..ea4f0beccdcc 100644 --- a/system-tests/__snapshots__/cypress-stop.spec.ts.js +++ b/system-tests/__snapshots__/cypress-stop.spec.ts.js @@ -7,14 +7,14 @@ exports['e2e Cypress.stop() / stops execution when called in before'] = ` ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Cypress: 1.2.3 │ │ Browser: FooBrowser 88 │ - │ Specs: 1 found (cypress-stop-before.cy.js) │ - │ Searched: cypress/e2e/cypress-stop-before.cy.js │ + │ Specs: 1 found (before.cy.js) │ + │ Searched: cypress/e2e/before.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ──────────────────────────────────────────────────────────────────────────────────────────────────── - Running: cypress-stop-before.cy.js (1 of 1) + Running: before.cy.js (1 of 1) Cypress.stop() in before @@ -33,7 +33,7 @@ exports['e2e Cypress.stop() / stops execution when called in before'] = ` │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ - │ Spec Ran: cypress-stop-before.cy.js │ + │ Spec Ran: before.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ @@ -44,7 +44,7 @@ exports['e2e Cypress.stop() / stops execution when called in before'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ cypress-stop-before.cy.js XX:XX 2 - - - 2 │ + │ ✔ before.cy.js XX:XX 2 - - - 2 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ✔ All specs passed! XX:XX 2 - - - 2 @@ -60,14 +60,14 @@ exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Cypress: 1.2.3 │ │ Browser: FooBrowser 88 │ - │ Specs: 1 found (cypress-stop-beforeEach.cy.js) │ - │ Searched: cypress/e2e/cypress-stop-beforeEach.cy.js │ + │ Specs: 1 found (beforeEach.cy.js) │ + │ Searched: cypress/e2e/beforeEach.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ──────────────────────────────────────────────────────────────────────────────────────────────────── - Running: cypress-stop-beforeEach.cy.js (1 of 1) + Running: beforeEach.cy.js (1 of 1) Cypress.stop() in beforeEach @@ -86,7 +86,7 @@ exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ - │ Spec Ran: cypress-stop-beforeEach.cy.js │ + │ Spec Ran: beforeEach.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ @@ -97,7 +97,7 @@ exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ cypress-stop-beforeEach.cy.js XX:XX 2 - - - 2 │ + │ ✔ beforeEach.cy.js XX:XX 2 - - - 2 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ✔ All specs passed! XX:XX 2 - - - 2 @@ -113,14 +113,14 @@ exports['e2e Cypress.stop() / stops execution when called in test'] = ` ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Cypress: 1.2.3 │ │ Browser: FooBrowser 88 │ - │ Specs: 1 found (cypress-stop-test.cy.js) │ - │ Searched: cypress/e2e/cypress-stop-test.cy.js │ + │ Specs: 1 found (test.cy.js) │ + │ Searched: cypress/e2e/test.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ──────────────────────────────────────────────────────────────────────────────────────────────────── - Running: cypress-stop-test.cy.js (1 of 1) + Running: test.cy.js (1 of 1) Cypress.stop() in test @@ -140,7 +140,7 @@ exports['e2e Cypress.stop() / stops execution when called in test'] = ` │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ - │ Spec Ran: cypress-stop-test.cy.js │ + │ Spec Ran: test.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ @@ -151,7 +151,7 @@ exports['e2e Cypress.stop() / stops execution when called in test'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ cypress-stop-test.cy.js XX:XX 3 1 - - 2 │ + │ ✔ test.cy.js XX:XX 3 1 - - 2 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ✔ All specs passed! XX:XX 3 1 - - 2 @@ -167,14 +167,14 @@ exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Cypress: 1.2.3 │ │ Browser: FooBrowser 88 │ - │ Specs: 1 found (cypress-stop-afterEach.cy.js) │ - │ Searched: cypress/e2e/cypress-stop-afterEach.cy.js │ + │ Specs: 1 found (afterEach.cy.js) │ + │ Searched: cypress/e2e/afterEach.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ──────────────────────────────────────────────────────────────────────────────────────────────────── - Running: cypress-stop-afterEach.cy.js (1 of 1) + Running: afterEach.cy.js (1 of 1) Cypress.stop() in afterEach @@ -194,7 +194,7 @@ exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ - │ Spec Ran: cypress-stop-afterEach.cy.js │ + │ Spec Ran: afterEach.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ @@ -205,7 +205,7 @@ exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ cypress-stop-afterEach.cy.js XX:XX 2 1 - - 1 │ + │ ✔ afterEach.cy.js XX:XX 2 1 - - 1 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ✔ All specs passed! XX:XX 2 1 - - 1 @@ -221,14 +221,14 @@ exports['e2e Cypress.stop() / stops execution when called in after'] = ` ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Cypress: 1.2.3 │ │ Browser: FooBrowser 88 │ - │ Specs: 1 found (cypress-stop-after.cy.js) │ - │ Searched: cypress/e2e/cypress-stop-after.cy.js │ + │ Specs: 1 found (after.cy.js) │ + │ Searched: cypress/e2e/after.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ──────────────────────────────────────────────────────────────────────────────────────────────────── - Running: cypress-stop-after.cy.js (1 of 1) + Running: after.cy.js (1 of 1) Cypress.stop() in after @@ -249,7 +249,7 @@ exports['e2e Cypress.stop() / stops execution when called in after'] = ` │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ - │ Spec Ran: cypress-stop-after.cy.js │ + │ Spec Ran: after.cy.js │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ @@ -260,7 +260,7 @@ exports['e2e Cypress.stop() / stops execution when called in after'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ cypress-stop-after.cy.js XX:XX 1 1 - - - │ + │ ✔ after.cy.js XX:XX 1 1 - - - │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ ✔ All specs passed! XX:XX 1 1 - - - diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-after.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/after.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-after.cy.js rename to system-tests/projects/cypres-stop/cypress/e2e/after.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-afterEach.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/afterEach.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-afterEach.cy.js rename to system-tests/projects/cypres-stop/cypress/e2e/afterEach.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-before.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/before.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-before.cy.js rename to system-tests/projects/cypres-stop/cypress/e2e/before.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-beforeEach.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/beforeEach.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-beforeEach.cy.js rename to system-tests/projects/cypres-stop/cypress/e2e/beforeEach.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/test.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/cypress-stop-test.cy.js rename to system-tests/projects/cypres-stop/cypress/e2e/test.cy.js diff --git a/system-tests/test/cypress-stop.spec.ts b/system-tests/test/cypress-stop.spec.ts index c5dd2aca0e57..5fe446398587 100644 --- a/system-tests/test/cypress-stop.spec.ts +++ b/system-tests/test/cypress-stop.spec.ts @@ -5,7 +5,7 @@ describe('e2e Cypress.stop()', () => { systemTests.it('stops execution when called in before', { project: 'cypres-stop', - spec: 'cypress-stop-before.cy.js', + spec: 'before.cy.js', snapshot: true, expectedExitCode: 0, browser: 'electron', @@ -35,7 +35,7 @@ describe('e2e Cypress.stop()', () => { systemTests.it('stops execution when called in beforeEach', { project: 'cypres-stop', - spec: 'cypress-stop-beforeEach.cy.js', + spec: 'beforeEach.cy.js', snapshot: true, expectedExitCode: 0, browser: 'electron', @@ -65,7 +65,7 @@ describe('e2e Cypress.stop()', () => { systemTests.it('stops execution when called in test', { project: 'cypres-stop', - spec: 'cypress-stop-test.cy.js', + spec: 'test.cy.js', snapshot: true, expectedExitCode: 0, browser: 'electron', @@ -95,7 +95,7 @@ describe('e2e Cypress.stop()', () => { systemTests.it('stops execution when called in afterEach', { project: 'cypres-stop', - spec: 'cypress-stop-afterEach.cy.js', + spec: 'afterEach.cy.js', snapshot: true, expectedExitCode: 0, browser: 'electron', @@ -125,7 +125,7 @@ describe('e2e Cypress.stop()', () => { systemTests.it('stops execution when called in after', { project: 'cypres-stop', - spec: 'cypress-stop-after.cy.js', + spec: 'after.cy.js', snapshot: true, expectedExitCode: 0, browser: 'electron', From 81f69b8dd8f1434c845b5f8a11f24342b0cda74c Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Thu, 5 Jun 2025 07:59:00 -0600 Subject: [PATCH 6/8] always wait --- packages/driver/src/cypress/runner.ts | 23 --- .../__snapshots__/cypress-stop.spec.ts.js | 33 ++-- .../cypres-stop/cypress/e2e/test.cy.js | 5 +- .../cypres-stop/cypress/support/e2e.js | 16 ++ system-tests/test/cypress-stop.spec.ts | 149 ++++++++++++------ 5 files changed, 135 insertions(+), 91 deletions(-) diff --git a/packages/driver/src/cypress/runner.ts b/packages/driver/src/cypress/runner.ts index 8a5412cd96e2..0c7e1337fa52 100644 --- a/packages/driver/src/cypress/runner.ts +++ b/packages/driver/src/cypress/runner.ts @@ -1931,29 +1931,6 @@ export default { } _runner.stopped = true - - // if the current runnable is a test or a before or beforeEach hook, - // then we need to abort the run immediately. Otherwise, we will wait - // for the after/afterEach hook logic to finish - const isTest = _runner.currentRunnable.type === 'test' - const isHook = _runner.currentRunnable.type === 'hook' - const hookName = isHook && getHookName(_runner.currentRunnable) - const shouldAbortImmediately = isTest || (isHook && (hookName === 'before all' || hookName === 'before each')) - - if (shouldAbortImmediately) { - // abort the run - _runner.abort() - - // emit the final 'end' event - // since our reporter depends on this event - // and mocha may never fire this because our - // runnable may never finish - _runner.emit('end') - - // remove all the listeners - // so no more events fire - _runner.removeAllListeners() - } }, getDisplayPropsForLog: LogUtils.getDisplayProps, diff --git a/system-tests/__snapshots__/cypress-stop.spec.ts.js b/system-tests/__snapshots__/cypress-stop.spec.ts.js index ea4f0beccdcc..360cad587369 100644 --- a/system-tests/__snapshots__/cypress-stop.spec.ts.js +++ b/system-tests/__snapshots__/cypress-stop.spec.ts.js @@ -18,18 +18,19 @@ exports['e2e Cypress.stop() / stops execution when called in before'] = ` Cypress.stop() in before + ✓ should not run this test (NaNms) - 0 passing + 1 passing (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Tests: 2 │ - │ Passing: 0 │ + │ Passing: 1 │ │ Failing: 0 │ │ Pending: 0 │ - │ Skipped: 2 │ + │ Skipped: 1 │ │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ @@ -44,9 +45,9 @@ exports['e2e Cypress.stop() / stops execution when called in before'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ before.cy.js XX:XX 2 - - - 2 │ + │ ✔ before.cy.js XX:XX 2 1 - - 1 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 2 - - - 2 + ✔ All specs passed! XX:XX 2 1 - - 1 ` @@ -71,18 +72,19 @@ exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` Cypress.stop() in beforeEach + ✓ should not run this test (NaNms) - 0 passing + 1 passing (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Tests: 2 │ - │ Passing: 0 │ + │ Passing: 1 │ │ Failing: 0 │ │ Pending: 0 │ - │ Skipped: 2 │ + │ Skipped: 1 │ │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ @@ -97,9 +99,9 @@ exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ beforeEach.cy.js XX:XX 2 - - - 2 │ + │ ✔ beforeEach.cy.js XX:XX 2 1 - - 1 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 2 - - - 2 + ✔ All specs passed! XX:XX 2 1 - - 1 ` @@ -125,18 +127,19 @@ exports['e2e Cypress.stop() / stops execution when called in test'] = ` Cypress.stop() in test ✓ should run this test + ✓ should stop during test execution - 1 passing + 2 passing (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Tests: 3 │ - │ Passing: 1 │ + │ Passing: 2 │ │ Failing: 0 │ │ Pending: 0 │ - │ Skipped: 2 │ + │ Skipped: 1 │ │ Screenshots: 0 │ │ Video: false │ │ Duration: X seconds │ @@ -151,9 +154,9 @@ exports['e2e Cypress.stop() / stops execution when called in test'] = ` Spec Tests Passing Failing Pending Skipped ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ test.cy.js XX:XX 3 1 - - 2 │ + │ ✔ test.cy.js XX:XX 3 2 - - 1 │ └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 3 1 - - 2 + ✔ All specs passed! XX:XX 3 2 - - 1 ` diff --git a/system-tests/projects/cypres-stop/cypress/e2e/test.cy.js b/system-tests/projects/cypres-stop/cypress/e2e/test.cy.js index 2353fabf2019..43d03066ddcc 100644 --- a/system-tests/projects/cypres-stop/cypress/e2e/test.cy.js +++ b/system-tests/projects/cypres-stop/cypress/e2e/test.cy.js @@ -4,8 +4,11 @@ describe('Cypress.stop() in test', () => { }) it('should stop during test execution', () => { - Cypress.stop() + return Cypress.stop() + + // eslint-disable-next-line no-unreachable console.log('test 2') + throw new Error('This code should not run') }) it('should not run this test', () => { diff --git a/system-tests/projects/cypres-stop/cypress/support/e2e.js b/system-tests/projects/cypres-stop/cypress/support/e2e.js index 77429ccfaa1c..59c84cbfd93f 100644 --- a/system-tests/projects/cypres-stop/cypress/support/e2e.js +++ b/system-tests/projects/cypres-stop/cypress/support/e2e.js @@ -1,3 +1,19 @@ +before(() => { + console.log('global before') +}) + +beforeEach(() => { + console.log('global beforeEach') +}) + +afterEach(() => { + console.log('global afterEach') +}) + +after(() => { + console.log('global after') +}) + Cypress.on('test:before:run:async', async () => { await new Promise((resolve) => setTimeout(resolve, 1000)) console.log('test:before:run:async') diff --git a/system-tests/test/cypress-stop.spec.ts b/system-tests/test/cypress-stop.spec.ts index 5fe446398587..b2a2c16ad861 100644 --- a/system-tests/test/cypress-stop.spec.ts +++ b/system-tests/test/cypress-stop.spec.ts @@ -1,6 +1,36 @@ import systemTests from '../lib/system-tests' describe('e2e Cypress.stop()', () => { + const getRunnableEventCounts = (stderr: string) => { + const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length + const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length + const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length + const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length + const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + + return { + beforeRunCount, + beforeRunAsyncCount, + beforeAfterRunAsyncCount, + afterRunCount, + afterRunAsyncCount, + } + } + + const getGlobalHooks = (stderr: string) => { + const globalBeforeCalled = (stderr.match(/global before(?!Each)/g) || []).length > 0 + const globalBeforeEachCalled = (stderr.match(/global beforeEach/g) || []).length > 0 + const globalAfterEachCalled = (stderr.match(/global afterEach/g) || []).length > 0 + const globalAfterCalled = (stderr.match(/global after(?!Each)/g) || []).length > 0 + + return { + globalBeforeCalled, + globalBeforeEachCalled, + globalAfterEachCalled, + globalAfterCalled, + } + } + systemTests.setup() systemTests.it('stops execution when called in before', { @@ -17,17 +47,20 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('before 2') expect(stderr).to.not.include('before 3') - const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length - const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length - const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length - const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length - const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + const { globalBeforeCalled, globalBeforeEachCalled, globalAfterEachCalled, globalAfterCalled } = getGlobalHooks(stderr) + + expect(globalBeforeCalled, 'globalBeforeCalled').to.be.true + expect(globalBeforeEachCalled, 'globalBeforeEachCalled').to.be.false + expect(globalAfterEachCalled, 'globalAfterEachCalled').to.be.false + expect(globalAfterCalled, 'globalAfterCalled').to.be.false + + const { beforeRunCount, beforeRunAsyncCount, beforeAfterRunAsyncCount, afterRunCount, afterRunAsyncCount } = getRunnableEventCounts(stderr) - expect(beforeRunCount).to.equal(1) - expect(beforeRunAsyncCount).to.equal(1) - expect(beforeAfterRunAsyncCount).to.equal(0) - expect(afterRunCount).to.equal(0) - expect(afterRunAsyncCount).to.equal(0) + expect(beforeRunCount, 'beforeRunCount').to.equal(1) + expect(beforeRunAsyncCount, 'beforeRunAsyncCount').to.equal(1) + expect(beforeAfterRunAsyncCount, 'beforeAfterRunAsyncCount').to.equal(1) + expect(afterRunCount, 'afterRunCount').to.equal(1) + expect(afterRunAsyncCount, 'afterRunAsyncCount').to.equal(1) return stderr }, @@ -47,17 +80,20 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('beforeEach 2') expect(stderr).to.not.include('beforeEach 3') - const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length - const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length - const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length - const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length - const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + const { globalBeforeCalled, globalBeforeEachCalled, globalAfterEachCalled, globalAfterCalled } = getGlobalHooks(stderr) - expect(beforeRunCount).to.equal(1) - expect(beforeRunAsyncCount).to.equal(1) - expect(beforeAfterRunAsyncCount).to.equal(0) - expect(afterRunCount).to.equal(0) - expect(afterRunAsyncCount).to.equal(0) + expect(globalBeforeCalled, 'globalBeforeCalled').to.be.true + expect(globalBeforeEachCalled, 'globalBeforeEachCalled').to.be.true + expect(globalAfterEachCalled, 'globalAfterEachCalled').to.be.false + expect(globalAfterCalled, 'globalAfterCalled').to.be.false + + const { beforeRunCount, beforeRunAsyncCount, beforeAfterRunAsyncCount, afterRunCount, afterRunAsyncCount } = getRunnableEventCounts(stderr) + + expect(beforeRunCount, 'beforeRunCount').to.equal(1) + expect(beforeRunAsyncCount, 'beforeRunAsyncCount').to.equal(1) + expect(beforeAfterRunAsyncCount, 'beforeAfterRunAsyncCount').to.equal(1) + expect(afterRunCount, 'afterRunCount').to.equal(1) + expect(afterRunAsyncCount, 'afterRunAsyncCount').to.equal(1) return stderr }, @@ -74,20 +110,23 @@ describe('e2e Cypress.stop()', () => { }, onStderr: (stderr) => { expect(stderr).to.include('test 1') - expect(stderr).to.include('test 2') + expect(stderr).to.not.include('test 2') expect(stderr).to.not.include('test 3') - const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length - const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length - const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length - const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length - const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + const { globalBeforeCalled, globalBeforeEachCalled, globalAfterEachCalled, globalAfterCalled } = getGlobalHooks(stderr) + + expect(globalBeforeCalled, 'globalBeforeCalled').to.be.true + expect(globalBeforeEachCalled, 'globalBeforeEachCalled').to.be.true + expect(globalAfterEachCalled, 'globalAfterEachCalled').to.be.true + expect(globalAfterCalled, 'globalAfterCalled').to.be.false - expect(beforeRunCount).to.equal(2) - expect(beforeRunAsyncCount).to.equal(2) - expect(beforeAfterRunAsyncCount).to.equal(1) - expect(afterRunCount).to.equal(1) - expect(afterRunAsyncCount).to.equal(1) + const { beforeRunCount, beforeRunAsyncCount, beforeAfterRunAsyncCount, afterRunCount, afterRunAsyncCount } = getRunnableEventCounts(stderr) + + expect(beforeRunCount, 'beforeRunCount').to.equal(2) + expect(beforeRunAsyncCount, 'beforeRunAsyncCount').to.equal(2) + expect(beforeAfterRunAsyncCount, 'beforeAfterRunAsyncCount').to.equal(2) + expect(afterRunCount, 'afterRunCount').to.equal(2) + expect(afterRunAsyncCount, 'afterRunAsyncCount').to.equal(2) return stderr }, @@ -107,17 +146,20 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('afterEach 2') expect(stderr).to.not.include('afterEach 3') - const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length - const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length - const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length - const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length - const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length + const { globalBeforeCalled, globalBeforeEachCalled, globalAfterEachCalled, globalAfterCalled } = getGlobalHooks(stderr) + + expect(globalBeforeCalled, 'globalBeforeCalled').to.be.true + expect(globalBeforeEachCalled, 'globalBeforeEachCalled').to.be.true + expect(globalAfterEachCalled, 'globalAfterEachCalled').to.be.false + expect(globalAfterCalled, 'globalAfterCalled').to.be.false + + const { beforeRunCount, beforeRunAsyncCount, beforeAfterRunAsyncCount, afterRunCount, afterRunAsyncCount } = getRunnableEventCounts(stderr) - expect(beforeRunCount).to.equal(1) - expect(beforeRunAsyncCount).to.equal(1) - expect(beforeAfterRunAsyncCount).to.equal(1) - expect(afterRunCount).to.equal(1) - expect(afterRunAsyncCount).to.equal(1) + expect(beforeRunCount, 'beforeRunCount').to.equal(1) + expect(beforeRunAsyncCount, 'beforeRunAsyncCount').to.equal(1) + expect(beforeAfterRunAsyncCount, 'beforeAfterRunAsyncCount').to.equal(1) + expect(afterRunCount, 'afterRunCount').to.equal(1) + expect(afterRunAsyncCount, 'afterRunAsyncCount').to.equal(1) return stderr }, @@ -137,17 +179,20 @@ describe('e2e Cypress.stop()', () => { expect(stderr).to.include('after 2') expect(stderr).to.not.include('after 3') - const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length - const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length - const beforeAfterRunAsyncCount = (stderr.match(/test:before:after:run:async/g) || []).length - const afterRunCount = (stderr.match(/test:after:run(?!:async)/g) || []).length - const afterRunAsyncCount = (stderr.match(/test:after:run:async/g) || []).length - - expect(beforeRunCount).to.equal(1) - expect(beforeRunAsyncCount).to.equal(1) - expect(beforeAfterRunAsyncCount).to.equal(1) - expect(afterRunCount).to.equal(1) - expect(afterRunAsyncCount).to.equal(1) + const { globalBeforeCalled, globalBeforeEachCalled, globalAfterEachCalled, globalAfterCalled } = getGlobalHooks(stderr) + + expect(globalBeforeCalled, 'globalBeforeCalled').to.be.true + expect(globalBeforeEachCalled, 'globalBeforeEachCalled').to.be.true + expect(globalAfterEachCalled, 'globalAfterEachCalled').to.be.true + expect(globalAfterCalled, 'globalAfterCalled').to.be.false + + const { beforeRunCount, beforeRunAsyncCount, beforeAfterRunAsyncCount, afterRunCount, afterRunAsyncCount } = getRunnableEventCounts(stderr) + + expect(beforeRunCount, 'beforeRunCount').to.equal(1) + expect(beforeRunAsyncCount, 'beforeRunAsyncCount').to.equal(1) + expect(beforeAfterRunAsyncCount, 'beforeAfterRunAsyncCount').to.equal(1) + expect(afterRunCount, 'afterRunCount').to.equal(1) + expect(afterRunAsyncCount, 'afterRunAsyncCount').to.equal(1) return stderr }, From 4be318af9651893b9b7f1f5e14c6d96396be4f2e Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Thu, 5 Jun 2025 08:33:48 -0600 Subject: [PATCH 7/8] update changelog --- cli/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index ce813922fd19..49da6eb71390 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -7,6 +7,10 @@ _Released 6/17/2025 (PENDING)_ - Install Cypress `win32-x64` binary on Windows `win32-arm64` systems. Cypress runs in emulation. Addresses [#30252](https://github.com/cypress-io/cypress/issues/30252). +**Bugfixes:** + +- Fixed an issue when using `Cypress.stop()` where a run may be aborted prior to receiving the required runner events causing Test Replay to not be available. Addresses [#31781](https://github.com/cypress-io/cypress/issues/31781). + ## 14.4.1 _Released 6/3/2025_ From e21348663355672c968bb8645557e7a5517763d8 Mon Sep 17 00:00:00 2001 From: Matthew Schile Date: Thu, 5 Jun 2025 10:00:15 -0600 Subject: [PATCH 8/8] updates --- packages/driver/src/cypress/runner.ts | 3 +++ system-tests/__snapshots__/cypress-stop.spec.ts.js | 10 +++++----- system-tests/projects/cypres-stop/package.json | 3 --- .../{cypres-stop => cypress-stop}/cypress.config.js | 0 .../cypress/e2e/after.cy.js | 0 .../cypress/e2e/afterEach.cy.js | 0 .../cypress/e2e/before.cy.js | 0 .../cypress/e2e/beforeEach.cy.js | 0 .../cypress/e2e/test.cy.js | 0 .../cypress/support/e2e.js | 0 system-tests/test/cypress-stop.spec.ts | 12 ++++++------ 11 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 system-tests/projects/cypres-stop/package.json rename system-tests/projects/{cypres-stop => cypress-stop}/cypress.config.js (100%) rename system-tests/projects/{cypres-stop => cypress-stop}/cypress/e2e/after.cy.js (100%) rename system-tests/projects/{cypres-stop => cypress-stop}/cypress/e2e/afterEach.cy.js (100%) rename system-tests/projects/{cypres-stop => cypress-stop}/cypress/e2e/before.cy.js (100%) rename system-tests/projects/{cypres-stop => cypress-stop}/cypress/e2e/beforeEach.cy.js (100%) rename system-tests/projects/{cypres-stop => cypress-stop}/cypress/e2e/test.cy.js (100%) rename system-tests/projects/{cypres-stop => cypress-stop}/cypress/support/e2e.js (100%) diff --git a/packages/driver/src/cypress/runner.ts b/packages/driver/src/cypress/runner.ts index 0c7e1337fa52..8e14610ac4dc 100644 --- a/packages/driver/src/cypress/runner.ts +++ b/packages/driver/src/cypress/runner.ts @@ -557,6 +557,9 @@ const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, get testAfterRun(test, Cypress) await testAfterRunAsync(test, Cypress) + // if the user has stopped the run, we need to abort, + // this needs to happen after the test:after:run events have fired + // to ensure protocol can properly handle the abort if (_runner.stopped) { // abort the run _runner.abort() diff --git a/system-tests/__snapshots__/cypress-stop.spec.ts.js b/system-tests/__snapshots__/cypress-stop.spec.ts.js index 360cad587369..b3de360c787f 100644 --- a/system-tests/__snapshots__/cypress-stop.spec.ts.js +++ b/system-tests/__snapshots__/cypress-stop.spec.ts.js @@ -1,4 +1,4 @@ -exports['e2e Cypress.stop() / stops execution when called in before'] = ` +exports['Cypress.stop() / stops execution when called in before'] = ` ==================================================================================================== @@ -52,7 +52,7 @@ exports['e2e Cypress.stop() / stops execution when called in before'] = ` ` -exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` +exports['Cypress.stop() / stops execution when called in beforeEach'] = ` ==================================================================================================== @@ -106,7 +106,7 @@ exports['e2e Cypress.stop() / stops execution when called in beforeEach'] = ` ` -exports['e2e Cypress.stop() / stops execution when called in test'] = ` +exports['Cypress.stop() / stops execution when called in test'] = ` ==================================================================================================== @@ -161,7 +161,7 @@ exports['e2e Cypress.stop() / stops execution when called in test'] = ` ` -exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` +exports['Cypress.stop() / stops execution when called in afterEach'] = ` ==================================================================================================== @@ -215,7 +215,7 @@ exports['e2e Cypress.stop() / stops execution when called in afterEach'] = ` ` -exports['e2e Cypress.stop() / stops execution when called in after'] = ` +exports['Cypress.stop() / stops execution when called in after'] = ` ==================================================================================================== diff --git a/system-tests/projects/cypres-stop/package.json b/system-tests/projects/cypres-stop/package.json deleted file mode 100644 index f9ba6239dbc5..000000000000 --- a/system-tests/projects/cypres-stop/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "projectFixtureDirectory": "runner-specs" -} \ No newline at end of file diff --git a/system-tests/projects/cypres-stop/cypress.config.js b/system-tests/projects/cypress-stop/cypress.config.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress.config.js rename to system-tests/projects/cypress-stop/cypress.config.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/after.cy.js b/system-tests/projects/cypress-stop/cypress/e2e/after.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/after.cy.js rename to system-tests/projects/cypress-stop/cypress/e2e/after.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/afterEach.cy.js b/system-tests/projects/cypress-stop/cypress/e2e/afterEach.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/afterEach.cy.js rename to system-tests/projects/cypress-stop/cypress/e2e/afterEach.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/before.cy.js b/system-tests/projects/cypress-stop/cypress/e2e/before.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/before.cy.js rename to system-tests/projects/cypress-stop/cypress/e2e/before.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/beforeEach.cy.js b/system-tests/projects/cypress-stop/cypress/e2e/beforeEach.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/beforeEach.cy.js rename to system-tests/projects/cypress-stop/cypress/e2e/beforeEach.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/e2e/test.cy.js b/system-tests/projects/cypress-stop/cypress/e2e/test.cy.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/e2e/test.cy.js rename to system-tests/projects/cypress-stop/cypress/e2e/test.cy.js diff --git a/system-tests/projects/cypres-stop/cypress/support/e2e.js b/system-tests/projects/cypress-stop/cypress/support/e2e.js similarity index 100% rename from system-tests/projects/cypres-stop/cypress/support/e2e.js rename to system-tests/projects/cypress-stop/cypress/support/e2e.js diff --git a/system-tests/test/cypress-stop.spec.ts b/system-tests/test/cypress-stop.spec.ts index b2a2c16ad861..1052e9b39f91 100644 --- a/system-tests/test/cypress-stop.spec.ts +++ b/system-tests/test/cypress-stop.spec.ts @@ -1,6 +1,6 @@ import systemTests from '../lib/system-tests' -describe('e2e Cypress.stop()', () => { +describe('Cypress.stop()', () => { const getRunnableEventCounts = (stderr: string) => { const beforeRunCount = (stderr.match(/test:before:run(?!:async)/g) || []).length const beforeRunAsyncCount = (stderr.match(/test:before:run:async/g) || []).length @@ -34,7 +34,7 @@ describe('e2e Cypress.stop()', () => { systemTests.setup() systemTests.it('stops execution when called in before', { - project: 'cypres-stop', + project: 'cypress-stop', spec: 'before.cy.js', snapshot: true, expectedExitCode: 0, @@ -67,7 +67,7 @@ describe('e2e Cypress.stop()', () => { }) systemTests.it('stops execution when called in beforeEach', { - project: 'cypres-stop', + project: 'cypress-stop', spec: 'beforeEach.cy.js', snapshot: true, expectedExitCode: 0, @@ -100,7 +100,7 @@ describe('e2e Cypress.stop()', () => { }) systemTests.it('stops execution when called in test', { - project: 'cypres-stop', + project: 'cypress-stop', spec: 'test.cy.js', snapshot: true, expectedExitCode: 0, @@ -133,7 +133,7 @@ describe('e2e Cypress.stop()', () => { }) systemTests.it('stops execution when called in afterEach', { - project: 'cypres-stop', + project: 'cypress-stop', spec: 'afterEach.cy.js', snapshot: true, expectedExitCode: 0, @@ -166,7 +166,7 @@ describe('e2e Cypress.stop()', () => { }) systemTests.it('stops execution when called in after', { - project: 'cypres-stop', + project: 'cypress-stop', spec: 'after.cy.js', snapshot: true, expectedExitCode: 0,