Skip to content

Commit 8f5c241

Browse files
authored
fix: update stop button to immediately update UI (#31984)
1 parent 954847c commit 8f5c241

File tree

4 files changed

+44
-22
lines changed

4 files changed

+44
-22
lines changed

cli/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
2+
## 14.5.2
3+
4+
_Released 7/15/2025 (PENDING)_
5+
6+
**Bugfixes:**
7+
8+
- Fixed a regression introduced in [`14.5.0`](https://docs.cypress.io/guides/references/changelog#14-5-0) where the Stop button would not immediately stop the spec timer. Addresses [#31920](https://github.com/cypress-io/cypress/issues/31920).
9+
210
## 14.5.1
311

412
_Released 7/01/2025_

packages/app/cypress/e2e/runner/runner.ui.cy.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,15 @@ describe('src/cypress/runner', () => {
289289
it('user can stop test execution', () => {
290290
loadSpec({
291291
filePath: 'runner/stop-execution.runner.cy.js',
292-
passCount: 0,
293-
failCount: 1,
294292
})
295293

294+
// Click the stop button to stop execution
295+
cy.get('.stop').click()
296+
297+
// Verify the UI updates immediately - stop button disappears, restart appears
298+
cy.get('.stop', { timeout: 100 }).should('not.exist')
299+
cy.get('.restart', { timeout: 100 }).should('be.visible')
300+
296301
cy.get('.runnable-err-message').should('not.contain', 'ran afterEach even though specs were stopped')
297302
cy.get('.runnable-err-message').should('contain', 'Cypress test was stopped while running this command.')
298303
})

packages/driver/src/cypress/runner.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ const isRootSuite = (suite) => {
393393
return suite && suite.root
394394
}
395395

396-
const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, getTests, cy) => {
396+
const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, getTests, cy, abort) => {
397397
// bail if our _runner doesn't have a hook.
398398
// useful in tests
399399
if (!_runner.hook) {
@@ -557,22 +557,11 @@ const overrideRunnerHook = (Cypress, _runner, getTestById, getTest, setTest, get
557557
testAfterRun(test, Cypress)
558558
await testAfterRunAsync(test, Cypress)
559559

560-
// if the user has stopped the run, we need to abort,
560+
// if the user has stopped the run and we are in run mode, we need to abort,
561561
// this needs to happen after the test:after:run events have fired
562562
// to ensure protocol can properly handle the abort
563-
if (_runner.stopped) {
564-
// abort the run
565-
_runner.abort()
566-
567-
// emit the final 'end' event
568-
// since our reporter depends on this event
569-
// and mocha may never fire this because our
570-
// runnable may never finish
571-
_runner.emit('end')
572-
573-
// remove all the listeners
574-
// so no more events fire
575-
_runner.removeAllListeners()
563+
if (_runner.stopped && isRunMode) {
564+
abort()
576565
}
577566
})]
578567

@@ -1407,7 +1396,22 @@ export default {
14071396

14081397
const getOnlySuiteId = () => _onlySuiteId
14091398

1410-
overrideRunnerHook(Cypress, _runner, getTestById, getTest, setTest, getTests, cy)
1399+
const abort = () => {
1400+
// abort the run
1401+
_runner.abort()
1402+
1403+
// emit the final 'end' event
1404+
// since our reporter depends on this event
1405+
// and mocha may never fire this because our
1406+
// runnable may never finish
1407+
_runner.emit('end')
1408+
1409+
// remove all the listeners
1410+
// so no more events fire
1411+
_runner.removeAllListeners()
1412+
}
1413+
1414+
overrideRunnerHook(Cypress, _runner, getTestById, getTest, setTest, getTests, cy, abort)
14111415

14121416
// this forces mocha to enqueue a duplicate test in the case of test retries
14131417
const replacePreviousAttemptWith = (test) => {
@@ -1934,6 +1938,12 @@ export default {
19341938
}
19351939

19361940
_runner.stopped = true
1941+
1942+
// if we are in open mode, abort the run immediately
1943+
// since we want the user feedback to be immediate
1944+
if (Cypress.config('isInteractive')) {
1945+
abort()
1946+
}
19371947
},
19381948

19391949
getDisplayPropsForLog: LogUtils.getDisplayProps,

system-tests/project-fixtures/runner-specs/cypress/e2e/runner/stop-execution.runner.cy.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
describe('stop execution', () => {
22
it('test stops while running', () => {
3-
cy.timeout(200)
3+
// ensure the timeout is long enough so we can verify the
4+
// UI changes but not too long so we can verify the error message
5+
cy.timeout(2000)
46
cy.get('.not-exist')
5-
setTimeout(() => {
6-
cy.$$('button.stop', parent.document).click()
7-
}, 100)
87
})
98

109
afterEach(function () {

0 commit comments

Comments
 (0)