Skip to content

Commit 1804d35

Browse files
erikeichmullererikeichjennifer-shehanemabela416
authored
misc: Next button visibility and behaviour during stepping. Fixes #32476 (#32536)
* fix: Next button visibility and behaviour during stepping. Fixes #32476 * docs: add changelog entry for Next button fix * test: update header tests for Next button visibility testing * fix: updated next button behaviour and testing * docs: add PR reference to changelog entry for #32476 * docs: update changelog entryfor #32476 * fix: reset hasBeenPaused on run:start; replace isResumed with hasBeenPaused; update controls * Update changelog entry * Update packages/reporter/cypress/e2e/header.cy.ts Co-authored-by: mabela416 <[email protected]> --------- Co-authored-by: eriei013 <[email protected]> Co-authored-by: Jennifer Shehane <[email protected]> Co-authored-by: mabela416 <[email protected]>
1 parent 6e8dc8e commit 1804d35

File tree

5 files changed

+94
-5
lines changed

5 files changed

+94
-5
lines changed

cli/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ _Released 10/7/2025 (PENDING)_
2020
- Added a dropdown menu in the Command Log that includes actions like Open in IDE and Add New Test in Studio, along with test preferences such as Auto-Scroll. Addresses [#32556](https://github.com/cypress-io/cypress/issues/32556) and [#32558](https://github.com/cypress-io/cypress/issues/32558). Addressed in [#32611](https://github.com/cypress-io/cypress/pull/32611).
2121
- Updated the Studio test editing header to include a Back button. This change ensures the Specs button remains functional for expanding or collapsing the specs panel. Addresses [#32556](https://github.com/cypress-io/cypress/issues/32556) and [#32558](https://github.com/cypress-io/cypress/issues/32558). Addressed in [#32611](https://github.com/cypress-io/cypress/pull/32611).
2222
- Fixed the Studio panel resizing when dragging. Addressed in [#32584](https://github.com/cypress-io/cypress/pull/32584).
23+
- The Next button now maintains consistent visibility during stepping sessions when using `cy.pause`, staying visible but disabled when no immediate next command is available, providing clear visual feedback to users about stepping state. Addresses [#32476](https://github.com/cypress-io/cypress/issues/32476). Addressed in [#32536](https://github.com/cypress-io/cypress/pull/32536).
2324

2425
**Dependency Updates:**
2526

packages/reporter/cypress/e2e/header.cy.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,79 @@ describe('header', () => {
200200
cy.get('.restart').should('not.exist')
201201
})
202202

203-
it('does not display next button', () => {
203+
it('does not display the next button', () => {
204204
cy.get('.next').should('not.exist')
205205
})
206206
})
207207
})
208208

209+
describe('when running after resume', () => {
210+
beforeEach(() => {
211+
runner.emit('run:start')
212+
runner.emit('paused')
213+
cy.get('.play').click()
214+
})
215+
216+
it('displays next button as disabled when running after resume', () => {
217+
cy.get('.next').should('be.visible').and('be.disabled')
218+
})
219+
220+
it('shows "Step (not available)" tooltip when running after resume', () => {
221+
cy.get('.next').trigger('mouseover', { force: true })
222+
cy.get('.cy-tooltip').should('have.text', 'Step (not available)')
223+
})
224+
225+
it('does not emit runner:next when disabled button is clicked', () => {
226+
cy.spy(runner, 'emit')
227+
cy.get('.next').click({ force: true })
228+
cy.wrap(runner.emit).should('not.be.calledWith', 'runner:next')
229+
})
230+
231+
it('displays stop button when running after resume', () => {
232+
cy.get('.stop').should('be.visible')
233+
})
234+
})
235+
236+
describe('when paused without next command', () => {
237+
beforeEach(() => {
238+
runner.emit('paused')
239+
})
240+
241+
it('displays play button', () => {
242+
cy.get('.play').should('be.visible')
243+
})
244+
245+
it('displays tooltip for play button', () => {
246+
cy.get('.play').trigger('mouseover')
247+
cy.get('.cy-tooltip').should('have.text', 'Resume C')
248+
})
249+
250+
it('emits runner:resume when play button is clicked', () => {
251+
cy.spy(runner, 'emit')
252+
cy.get('.play').click()
253+
cy.wrap(runner.emit).should('be.calledWith', 'runner:resume')
254+
})
255+
256+
it('displays next button', () => {
257+
cy.get('.next').should('be.visible').and('be.disabled')
258+
})
259+
260+
it('shows "Step (not available)" tooltip when next button is disabled', () => {
261+
cy.get('.next').trigger('mouseover', { force: true })
262+
cy.get('.cy-tooltip').should('have.text', 'Step (not available)')
263+
})
264+
265+
it('does not emit runner:next when disabled next button is clicked', () => {
266+
cy.spy(runner, 'emit')
267+
cy.get('.next').click({ force: true })
268+
cy.wrap(runner.emit).should('not.be.calledWith', 'runner:next')
269+
})
270+
271+
it('does not display stop button', () => {
272+
cy.get('.stop').should('not.exist')
273+
})
274+
})
275+
209276
describe('when paused with next command', () => {
210277
beforeEach(() => {
211278
runner.emit('paused', 'find')

packages/reporter/src/header/controls.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,26 @@ const Controls: React.FC<Props> = observer(({ events = defaultEvents, appState }
5353
</div>
5454
</Tooltip>
5555
)}
56-
{!!appState.nextCommandName && (
57-
<Tooltip placement='bottom' title={<p>Next <span className='kbd'>[N]:</span>{appState.nextCommandName}</p>} className='cy-tooltip'>
56+
{(appState.isPaused || (appState.isRunning && appState.hasBeenPaused)) && (
57+
<Tooltip
58+
placement='bottom'
59+
title={appState.nextCommandName ? <p>Next <span className='kbd'>[N]:</span>{appState.nextCommandName}</p> : <p>Step (not available)</p>}
60+
className='cy-tooltip'
61+
>
5862
<div>
59-
<Button size='20' variant='outline-dark' aria-label={`Next '${appState.nextCommandName}'`} className='next' onClick={emit('next')}>
60-
<IconActionNext size='16' strokeColor={iconStrokeColor} fillColor={iconFillColor} />
63+
<Button
64+
size='20'
65+
variant='outline-dark'
66+
aria-label={appState.nextCommandName ? `Next '${appState.nextCommandName}'` : 'Next (not available)'}
67+
className='next disabled:hover:border-white/20 disabled:focus:border-white/20'
68+
disabled={!appState.nextCommandName}
69+
onClick={appState.nextCommandName ? emit('next') : () => { }}
70+
>
71+
<IconActionNext
72+
size='16'
73+
strokeColor={(appState.nextCommandName) ? iconStrokeColor : 'gray-700'}
74+
fillColor={iconFillColor}
75+
/>
6176
</Button>
6277
</div>
6378
</Tooltip>

packages/reporter/src/lib/app-state.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ interface DefaultAppState {
88
pinnedSnapshotId: number | string | null
99
studioActive: boolean
1010
studioSingleTestActive: boolean
11+
hasBeenPaused: boolean
1112
}
1213

1314
// these are used for the `reset` method
@@ -19,6 +20,7 @@ const defaults: DefaultAppState = {
1920
pinnedSnapshotId: null,
2021
studioActive: false,
2122
studioSingleTestActive: false,
23+
hasBeenPaused: false,
2224
}
2325

2426
class AppState {
@@ -32,6 +34,7 @@ class AppState {
3234
studioActive = defaults.studioActive
3335
studioSingleTestActive = defaults.studioSingleTestActive
3436
isStopped = false
37+
hasBeenPaused = defaults.hasBeenPaused
3538
_resetAutoScrollingEnabledTo = true;
3639
[key: string]: any
3740

@@ -46,6 +49,7 @@ class AppState {
4649
pinnedSnapshotId: observable,
4750
studioActive: observable,
4851
studioSingleTestActive: observable,
52+
hasBeenPaused: observable,
4953
})
5054
}
5155

@@ -57,6 +61,7 @@ class AppState {
5761
pause (nextCommandName?: string) {
5862
this.isPaused = true
5963
this.nextCommandName = nextCommandName
64+
this.hasBeenPaused = true
6065
}
6166

6267
resume () {

packages/reporter/src/lib/events.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ const events: Events = {
7979
runner.on('run:start', action('run:start', () => {
8080
if (runnablesStore.hasTests) {
8181
appState.startRunning()
82+
appState.hasBeenPaused = false
8283
}
8384
}))
8485

0 commit comments

Comments
 (0)