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

Cypress fails to uncheck all checked checkboxes #26208

Closed
mhssmnn opened this issue Mar 24, 2023 · 9 comments
Closed

Cypress fails to uncheck all checked checkboxes #26208

mhssmnn opened this issue Mar 24, 2023 · 9 comments
Labels
pkg/driver This is due to an issue in the packages/driver directory stale no activity on this issue for a long period type: bug v12.0.0 🐛

Comments

@mhssmnn
Copy link

mhssmnn commented Mar 24, 2023

Current behavior

Currently running the following command only unchecks some of the checkboxes:

cy.get('input[type="checkbox"]:checked').uncheck();

Screen Shot 2023-03-24 at 2 34 58 PM

Desired behavior

Cypress should uncheck all checkboxes, as it did in at least v10.2

Test code to reproduce

Here is the failing code:

cy.get('input[type="checkbox"]:checked').uncheck();
cy.get('input[type="checkbox"]:checked').should('not.exist');

And a test repo:

https://github.com/mhssmnn/cypress-issue-checkboxes-repro

Cypress Version

12.7.0

Node version

v18.11.0

Operating System

macOS 12.3.1

Debug Logs

cypress:server:reporter got mocha event 'fail' with args: [ { _testConfig: { testConfigList: [], unverifiedTestConfig: {}, applied: 'complete' }, id: 'r3', order: 1, title: 'unchecks all the checked check boxes so no checks are left', err: { message: 'Timed out retrying after 4200ms: `cy.uncheck()` failed because the page updated while this command was executing. Cypress tried to locate elements based on this query:\n' + '\n' + '> cy.get(input[type="checkbox"]:checked)\n' + '\n' + 'We initially found matching element(s), but while waiting for them to become actionable, they disappeared from the page. Common situations why this happens:\n' + '  - Your JS framework re-rendered asynchronously\n' + '  - Your app code reacted to an event firing and removed the element\n' + '\n' + 'You can typically solve this by breaking up a chain. For example, rewrite:\n' + '\n' + "> `cy.get('button').click().click()`\n" + '\n' + 'to\n' + '\n' + "> `cy.get('button').as('btn').click()`\n" + "> `cy.get('@btn').click()`\n" + '\n' + 'https://on.cypress.io/element-has-detached-from-dom', name: 'CypressError', stack: 'CypressError: Timed out retrying after 4200ms: `cy.uncheck()` failed because the page updated while this command was executing. Cypress tried to locate elements based on this query:\n' + '\n' + '> cy.get(input[type="checkbox"]:checked)\n' + '\n' + 'We initially found matching element(s), but while waiting for them to become actionable, they disappeared from the page. Common situations why this happens:\n' + '  - Your JS framework re-rendered asynchronously\n' + '  - Your app code reacted to an event firing and removed the element\n' + '\n' + 'You can typically solve this by breaking up a chain. For example, rewrite:\n' + '\n' + "> `cy.get('button').click().click()`\n" + '\n' + 'to\n' + '\n' + "> `cy.get('button').as('btn').click()`\n" + "> `cy.get('@btn').click()`\n" + '\n' + 'https://on.cypress.io/element-has-detached-from-dom\n' + '    at retryActionability (http://localhost:8080/__cypress/runner/cypress_runner.js:130623:82)\n' + '    at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)\n' + '    at Promise.attempt.Promise.try (http://localhost:8080/__cypress/runner/cypress_runner.js:6188:29)\n' + '    at whenStable (http://localhost:8080/__cypress/runner/cypress_runner.js:146732:65)\n' + '    at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:146173:14)\n' + '    at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)\n' + '    at Promise._settlePromiseFromHandler (http://localhost:8080/__cypress/runner/cypress_runner.js:6849:31)\n' + '    at Promise._settlePromise (http://localhost:8080/__cypress/runner/cypress_runner.js:6906:18)\n' + '    at Promise._settlePromise0 (http://localhost:8080/__cypress/runner/cypress_runner.js:6951:10)\n' + '    at Promise._settlePromises (http://localhost:8080/__cypress/runner/cypress_runner.js:7031:18)\n' + '    at Promise._fulfill (http://localhost:8080/__cypress/runner/cypress_runner.js:6975:18)\n' + '    at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:8589:46)\n' + 'From Your Spec Code:\n' + '    at Context.eval (webpack:///./cypress/e2e/spec.cy.js:4:45)', parsedStack: [Array], codeFrame: [Object] }, state: 'failed', pending: false, body: '() => {\n' + "    cy.visit('/page.html');\n" + `    cy.get('input[type="checkbox"]:checked').uncheck();\n` + `    cy.get('input[type="checkbox"]:checked').should('not.exist');\n` + '  }', type: 'test', duration: 7600, wallClockStartedAt: '2023-03-24T01:43:43.038Z', timings: { lifecycle: 197, test: [Object] }, file: null, invocationDetails: { function: 'Suite.eval', fileUrl: 'http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js', originalFile: 'webpack:///./cypress/e2e/spec.cy.js', relativeFile: 'cypress/e2e/spec.cy.js', absoluteFile: '/Users/markhaussmann/Projects/cypress-issue-checkboxes-repro/cypress/e2e/spec.cy.js', line: 2, column: 2, whitespace: '    ', stack: 'Error\n' + '    at Suite.eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:100:3)\n' + '    at ./cypress/e2e/spec.cy.js (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:99:1)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at 0 (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:116:18)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:84:18)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:87:10)\n' + '    at eval (<anonymous>)' }, currentRetry: 0, retries: 0, _slow: 10000 } ] +8s
    1) unchecks all the checked check boxes so no checks are left
  cypress:server:project onMocha test end +16ms
  cypress:server:reporter got mocha event 'test end' with args: [ { _testConfig: { testConfigList: [], unverifiedTestConfig: {}, applied: 'complete' }, id: 'r3', order: 1, title: 'unchecks all the checked check boxes so no checks are left', err: { message: 'Timed out retrying after 4200ms: `cy.uncheck()` failed because the page updated while this command was executing. Cypress tried to locate elements based on this query:\n' + '\n' + '> cy.get(input[type="checkbox"]:checked)\n' + '\n' + 'We initially found matching element(s), but while waiting for them to become actionable, they disappeared from the page. Common situations why this happens:\n' + '  - Your JS framework re-rendered asynchronously\n' + '  - Your app code reacted to an event firing and removed the element\n' + '\n' + 'You can typically solve this by breaking up a chain. For example, rewrite:\n' + '\n' + "> `cy.get('button').click().click()`\n" + '\n' + 'to\n' + '\n' + "> `cy.get('button').as('btn').click()`\n" + "> `cy.get('@btn').click()`\n" + '\n' + 'https://on.cypress.io/element-has-detached-from-dom', name: 'CypressError', stack: 'CypressError: Timed out retrying after 4200ms: `cy.uncheck()` failed because the page updated while this command was executing. Cypress tried to locate elements based on this query:\n' + '\n' + '> cy.get(input[type="checkbox"]:checked)\n' + '\n' + 'We initially found matching element(s), but while waiting for them to become actionable, they disappeared from the page. Common situations why this happens:\n' + '  - Your JS framework re-rendered asynchronously\n' + '  - Your app code reacted to an event firing and removed the element\n' + '\n' + 'You can typically solve this by breaking up a chain. For example, rewrite:\n' + '\n' + "> `cy.get('button').click().click()`\n" + '\n' + 'to\n' + '\n' + "> `cy.get('button').as('btn').click()`\n" + "> `cy.get('@btn').click()`\n" + '\n' + 'https://on.cypress.io/element-has-detached-from-dom\n' + '    at retryActionability (http://localhost:8080/__cypress/runner/cypress_runner.js:130623:82)\n' + '    at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)\n' + '    at Promise.attempt.Promise.try (http://localhost:8080/__cypress/runner/cypress_runner.js:6188:29)\n' + '    at whenStable (http://localhost:8080/__cypress/runner/cypress_runner.js:146732:65)\n' + '    at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:146173:14)\n' + '    at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)\n' + '    at Promise._settlePromiseFromHandler (http://localhost:8080/__cypress/runner/cypress_runner.js:6849:31)\n' + '    at Promise._settlePromise (http://localhost:8080/__cypress/runner/cypress_runner.js:6906:18)\n' + '    at Promise._settlePromise0 (http://localhost:8080/__cypress/runner/cypress_runner.js:6951:10)\n' + '    at Promise._settlePromises (http://localhost:8080/__cypress/runner/cypress_runner.js:7031:18)\n' + '    at Promise._fulfill (http://localhost:8080/__cypress/runner/cypress_runner.js:6975:18)\n' + '    at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:8589:46)\n' + 'From Your Spec Code:\n' + '    at Context.eval (webpack:///./cypress/e2e/spec.cy.js:4:45)', parsedStack: [Array], codeFrame: [Object] }, state: 'failed', pending: false, body: '() => {\n' + "    cy.visit('/page.html');\n" + `    cy.get('input[type="checkbox"]:checked').uncheck();\n` + `    cy.get('input[type="checkbox"]:checked').should('not.exist');\n` + '  }', type: 'test', duration: 7600, wallClockStartedAt: '2023-03-24T01:43:43.038Z', timings: { lifecycle: 197, test: [Object] }, file: null, invocationDetails: { function: 'Suite.eval', fileUrl: 'http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js', originalFile: 'webpack:///./cypress/e2e/spec.cy.js', relativeFile: 'cypress/e2e/spec.cy.js', absoluteFile: '/Users/markhaussmann/Projects/cypress-issue-checkboxes-repro/cypress/e2e/spec.cy.js', line: 2, column: 2, whitespace: '    ', stack: 'Error\n' + '    at Suite.eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:100:3)\n' + '    at ./cypress/e2e/spec.cy.js (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:99:1)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at 0 (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:116:18)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:84:18)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:87:10)\n' + '    at eval (<anonymous>)' }, final: true, currentRetry: 0, retries: 0, _slow: 10000 } ] +17ms

  cypress:server:project onMocha suite end +289ms
  cypress:server:reporter got mocha event 'suite end' with args: [ { id: 'r2', title: 'issue reproduction', root: false, pending: false, type: 'suite', file: null, invocationDetails: { function: './cypress/e2e/spec.cy.js', fileUrl: 'http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js', originalFile: 'webpack:///./cypress/e2e/spec.cy.js', relativeFile: 'cypress/e2e/spec.cy.js', absoluteFile: '/Users/markhaussmann/Projects/cypress-issue-checkboxes-repro/cypress/e2e/spec.cy.js', line: 1, column: 0, whitespace: '    ', stack: 'Error\n' + '    at ./cypress/e2e/spec.cy.js (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:99:1)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at 0 (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:116:18)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:84:18)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:87:10)\n' + '    at eval (<anonymous>)' }, retries: -1, _slow: 10000 } ] +288ms
  cypress:server:project onMocha test:after:run +8ms
  cypress:server:reporter got mocha event 'test:after:run' with args: [ { _testConfig: { testConfigList: [], unverifiedTestConfig: {}, applied: 'complete' }, id: 'r3', order: 1, title: 'unchecks all the checked check boxes so no checks are left', err: { message: 'Timed out retrying after 4200ms: `cy.uncheck()` failed because the page updated while this command was executing. Cypress tried to locate elements based on this query:\n' + '\n' + '> cy.get(input[type="checkbox"]:checked)\n' + '\n' + 'We initially found matching element(s), but while waiting for them to become actionable, they disappeared from the page. Common situations why this happens:\n' + '  - Your JS framework re-rendered asynchronously\n' + '  - Your app code reacted to an event firing and removed the element\n' + '\n' + 'You can typically solve this by breaking up a chain. For example, rewrite:\n' + '\n' + "> `cy.get('button').click().click()`\n" + '\n' + 'to\n' + '\n' + "> `cy.get('button').as('btn').click()`\n" + "> `cy.get('@btn').click()`\n" + '\n' + 'https://on.cypress.io/element-has-detached-from-dom', name: 'CypressError', stack: 'CypressError: Timed out retrying after 4200ms: `cy.uncheck()` failed because the page updated while this command was executing. Cypress tried to locate elements based on this query:\n' + '\n' + '> cy.get(input[type="checkbox"]:checked)\n' + '\n' + 'We initially found matching element(s), but while waiting for them to become actionable, they disappeared from the page. Common situations why this happens:\n' + '  - Your JS framework re-rendered asynchronously\n' + '  - Your app code reacted to an event firing and removed the element\n' + '\n' + 'You can typically solve this by breaking up a chain. For example, rewrite:\n' + '\n' + "> `cy.get('button').click().click()`\n" + '\n' + 'to\n' + '\n' + "> `cy.get('button').as('btn').click()`\n" + "> `cy.get('@btn').click()`\n" + '\n' + 'https://on.cypress.io/element-has-detached-from-dom\n' + '    at retryActionability (http://localhost:8080/__cypress/runner/cypress_runner.js:130623:82)\n' + '    at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)\n' + '    at Promise.attempt.Promise.try (http://localhost:8080/__cypress/runner/cypress_runner.js:6188:29)\n' + '    at whenStable (http://localhost:8080/__cypress/runner/cypress_runner.js:146732:65)\n' + '    at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:146173:14)\n' + '    at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)\n' + '    at Promise._settlePromiseFromHandler (http://localhost:8080/__cypress/runner/cypress_runner.js:6849:31)\n' + '    at Promise._settlePromise (http://localhost:8080/__cypress/runner/cypress_runner.js:6906:18)\n' + '    at Promise._settlePromise0 (http://localhost:8080/__cypress/runner/cypress_runner.js:6951:10)\n' + '    at Promise._settlePromises (http://localhost:8080/__cypress/runner/cypress_runner.js:7031:18)\n' + '    at Promise._fulfill (http://localhost:8080/__cypress/runner/cypress_runner.js:6975:18)\n' + '    at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:8589:46)\n' + 'From Your Spec Code:\n' + '    at Context.eval (webpack:///./cypress/e2e/spec.cy.js:4:45)', parsedStack: [Array], codeFrame: [Object] }, state: 'failed', pending: false, body: '() => {\n' + "    cy.visit('/page.html');\n" + `    cy.get('input[type="checkbox"]:checked').uncheck();\n` + `    cy.get('input[type="checkbox"]:checked').should('not.exist');\n` + '  }', type: 'test', duration: 7600, wallClockStartedAt: '2023-03-24T01:43:43.038Z', wallClockDuration: 7627, timings: { lifecycle: 197, test: [Object] }, file: null, invocationDetails: { function: 'Suite.eval', fileUrl: 'http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js', originalFile: 'webpack:///./cypress/e2e/spec.cy.js', relativeFile: 'cypress/e2e/spec.cy.js', absoluteFile: '/Users/markhaussmann/Projects/cypress-issue-checkboxes-repro/cypress/e2e/spec.cy.js', line: 2, column: 2, whitespace: '    ', stack: 'Error\n' + '    at Suite.eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:100:3)\n' + '    at ./cypress/e2e/spec.cy.js (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:99:1)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at 0 (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:116:18)\n' + '    at __webpack_require__ (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:20:30)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:84:18)\n' + '    at eval (http://localhost:8080/__cypress/tests?p=cypress/e2e/spec.cy.js:87:10)\n' + '    at eval (<anonymous>)' }, final: true, currentRetry: 0, retries: 0, _slow: 10000 } ] +8ms

  0 passing (8s)
  1 failing

  1) issue reproduction
       unchecks all the checked check boxes so no checks are left:
     CypressError: Timed out retrying after 4200ms: `cy.uncheck()` failed because the page updated while this command was executing. Cypress tried to locate elements based on this query:

> cy.get(input[type="checkbox"]:checked)

We initially found matching element(s), but while waiting for them to become actionable, they disappeared from the page. Common situations why this happens:
  - Your JS framework re-rendered asynchronously
  - Your app code reacted to an event firing and removed the element

You can typically solve this by breaking up a chain. For example, rewrite:

> `cy.get('button').click().click()`

to

> `cy.get('button').as('btn').click()`
> `cy.get('@btn').click()`

https://on.cypress.io/element-has-detached-from-dom
      at retryActionability (http://localhost:8080/__cypress/runner/cypress_runner.js:130623:82)
      at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)
      at Promise.attempt.Promise.try (http://localhost:8080/__cypress/runner/cypress_runner.js:6188:29)
      at whenStable (http://localhost:8080/__cypress/runner/cypress_runner.js:146732:65)
      at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:146173:14)
      at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:8914:23)
      at Promise._settlePromiseFromHandler (http://localhost:8080/__cypress/runner/cypress_runner.js:6849:31)
      at Promise._settlePromise (http://localhost:8080/__cypress/runner/cypress_runner.js:6906:18)
      at Promise._settlePromise0 (http://localhost:8080/__cypress/runner/cypress_runner.js:6951:10)
      at Promise._settlePromises (http://localhost:8080/__cypress/runner/cypress_runner.js:7031:18)
      at Promise._fulfill (http://localhost:8080/__cypress/runner/cypress_runner.js:6975:18)
      at <unknown> (http://localhost:8080/__cypress/runner/cypress_runner.js:8589:46)
  From Your Spec Code:
      at Context.eval (webpack:///./cypress/e2e/spec.cy.js:4:45)

Other

No response

@lmiller1990
Copy link
Contributor

I reproduced with the repository provided. Definitely a bug, we should fix this.

Would you be interested in making a PR by any chance?

@lmiller1990 lmiller1990 added the pkg/driver This is due to an issue in the packages/driver directory label Mar 27, 2023
@mhssmnn
Copy link
Author

mhssmnn commented Mar 27, 2023

I'd love to, but I wouldn't know where to start. 🤷

@lmiller1990
Copy link
Contributor

If you'd like to give it a try

You can let me know if you need more help/tips - I don't know exactly how to fix this off the top of my head, but that should point you in the right direction.

@mhssmnn
Copy link
Author

mhssmnn commented Mar 28, 2023

I've created a PR with the failing test so far.

After some investigation, I think the issue stems from changes made in #24628.

Specifically the changes that requery the DOM:

it('requeries if the DOM rerenders during actionability', () => {
cy.$$('[name=colors]').first().prop('disabled', true)
const listener = _.after(3, () => {
cy.$$('[name=colors]').first().prop('disabled', false)
const parent = cy.$$('[name=colors]').parent()
parent.replaceWith(parent[0].outerHTML)
cy.off('command:retry', listener)
})
cy.on('command:retry', listener)
cy.get('[name=colors]').check().then(($inputs) => {
$inputs.each((i, el) => {
expect($(el)).to.be.checked
})
})
})

So if :checked is used in a selector, when the DOM is re-queried after a un/check event the selector will be dealing with a subset of the original elements. That will render the index of this line incorrect:

subjectFn: () => cy.getSubjectFromChain(subjectChain).eq(index),

@lmiller1990
Copy link
Contributor

Ahh #24628 is a likely candidate for a breaking change, it rejiggered the internals quite a bit. Great detective work.

@lmiller1990 lmiller1990 removed their assignment Jun 28, 2023
@cypress-app-bot
Copy link
Collaborator

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label Sep 25, 2023
@jennifer-shehane jennifer-shehane added type: bug and removed stale no activity on this issue for a long period labels Oct 4, 2023
@AviMol
Copy link

AviMol commented Mar 3, 2024

I'm with cy13 and still facing this issue

@cypress-app-bot
Copy link
Collaborator

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label Aug 31, 2024
@cypress-app-bot
Copy link
Collaborator

This issue has been closed due to inactivity.

@cypress-app-bot cypress-app-bot closed this as not planned Won't fix, can't repro, duplicate, stale Sep 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg/driver This is due to an issue in the packages/driver directory stale no activity on this issue for a long period type: bug v12.0.0 🐛
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants