cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
47.09k stars 3.19k forks source link

`click()` doesn't retry when a button's parent element becomes actionable after being disabled. #30655

Open Ray-Frost opened 2 days ago

Ray-Frost commented 2 days ago

Current behavior

If a button's parent element, such as a fieldset, becomes actionable after being disabled, the click() associated with the button will be skipped instead of retried.

<fieldset disabled id="test-fieldset">
  <button id="test-button" type="button">
    Test click
  </button>
</fieldset>

const fieldsetTimer = setTimeout(() => {
  document.getElementById('test-fieldset').disabled = false;
}, 500);

CleanShot 2024-11-20 at 13 39 27@2x

Desired behavior

click() should automatically wait for the element to reach an actionable state as the document described

Test code to reproduce

it('Test click', function () {
  cy.get('#test-button').click();
});

Cypress Version

13.15.0

Node version

20.14.0

Operating System

MacOS 15.1

Debug Logs

No response

Other

This issue might be related to this condition, given PR #28807

ryanthemanuel commented 1 day ago

Hi @Ray-Frost, thanks for reporting this. I can recreate this as you described, the click succeeds immediately but the click event handlers never fire.

It appears that #28807 got us half way to what is ideal. It ensured that click events wouldn't fire when a parent was disabled; however, you are right we should actually retry (and eventually fail) in case the parent eventually becomes enabled. I'd also need to check, but I'm not sure this logic works properly if there are multiple levels of nesting.

In the meantime, I believe you could work around this by doing something like:

cy.get('#test-button').should('be.enabled').click()