Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: actionability not retrying in after hooks where the test failed #30831

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
## 14.0.1

_Released 1/28/2024 (PENDING)_

**Bugfixes:**

- Actions performed in `after` hooks, like `.click()` and `.type()` will now correctly retry and perform the action when a test fails. Fixes [#2831](https://github.com/cypress-io/cypress/issues/2831).

## 14.0.0

_Released 1/7/2024 (PENDING)_
Expand Down
46 changes: 46 additions & 0 deletions packages/driver/cypress/e2e/commands/actions/click.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,52 @@ describe('src/cy/commands/actions/click', () => {
cy.get('#dom').invoke('css', 'scrollBehavior').then((scrollBehavior) => expect(scrollBehavior).to.eq('smooth'))
})
})

describe('retries in after hook when failures', () => {
it('clicks element in hook', (done) => {
cy.on('fail', (err) => {
expect(err.message).contain('expected true to be false')
done()
})

expect(true).to.be.false
})

after(() => {
const onClick = cy.stub()

const $button = cy.$$('#button')

$button.on('click', onClick)

cy.get('#button').click().then(() => {
expect(onClick).to.be.calledOnce
})
})
})

describe('retries in afterEach hook when failures', () => {
it('clicks element in hook', (done) => {
cy.on('fail', (err) => {
expect(err.message).contain('expected true to be false')
done()
})

expect(true).to.be.false
})

afterEach(() => {
const onClick = cy.stub()

const $button = cy.$$('#button')

$button.on('click', onClick)

cy.get('#button').click().then(() => {
expect(onClick).to.be.calledOnce
})
})
})
})

describe('assertion verification', () => {
Expand Down
46 changes: 46 additions & 0 deletions packages/driver/cypress/e2e/commands/actions/type.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,52 @@ describe('src/cy/commands/actions/type - #type', () => {

cy.get(':text:first').type('foo', { scrollBehavior: false, timeout: 200 })
})

describe('retries in after hook when failures', () => {
it('types in element in hook', (done) => {
cy.on('fail', (err) => {
expect(err.message).contain('expected true to be false')
done()
})

expect(true).to.be.false
})

after(() => {
const input = cy.$$('input:text:first')

input.val('')

expect(input).to.have.value('')

cy.get('input:text:first').type('foo').then(($input) => {
expect($input).to.have.value('foo')
})
})
})

describe('retries in afterEach hook when failures', () => {
it('types in element in hook', (done) => {
cy.on('fail', (err) => {
expect(err.message).contain('expected true to be false')
done()
})

expect(true).to.be.false
})

afterEach(() => {
const input = cy.$$('input:text:first')

input.val('')

expect(input).to.have.value('')

cy.get('input:text:first').type('foo').then(($input) => {
expect($input).to.have.value('foo')
})
})
})
})

describe('input types where no extra formatting required', () => {
Expand Down
5 changes: 2 additions & 3 deletions packages/driver/src/cy/retries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ export const create = (Cypress: ICypress, state: StateFunc, timeout: $Cy['timeou
const ended = () => {
// we should NOT retry if
// 1. our promise has been canceled
// 2. or we have an error
// 3. or if the runnables has changed
// 2. or if the runnables has changed

// although bluebird SHOULD cancel these retries
// since they're all connected - apparently they
Expand All @@ -116,7 +115,7 @@ export const create = (Cypress: ICypress, state: StateFunc, timeout: $Cy['timeou
// bug in bluebird with not propagating cancellations
// fast enough in a series of promises
// https://github.com/petkaantonov/bluebird/issues/1424
return state('canceled') || state('error') || runnableHasChanged()
return state('canceled') || runnableHasChanged()
}

return Promise
Expand Down
Loading