Search code examples
cypress

Cypress - wait for button to be clickable


I know it works most of the time, but on a web page I tested, on following line

cy.get('button[title="Query"]').click()

Cypress runner passed get but hung on the click action till timeout. If I modify the code to

cy.get('button[title="Query"]').as('query')
cy.wait(500)
cy.get('@query').click()

The test succeeds.

Obviously arbitrary wait is a bad practice. Automatic waiting, retry-ability - as claimed by Cypress as features, are suppose to prevent above scenario from happening but failed in my case.

Furthermore, Cypress has no should('be.clickable') assertion. How could I instruct Cypress to wait for a button to be clickable before clicking it, or if clicking hung, then retry with a interval until success?


Solution

  • The issue could be caused by race condition between cypress script and app code before cy.get in a way that, at the time of clicking, the app page state is still in transition such that the button is visible and enabled but the intended event listener hasn't been attached to the button yet. It is more likely so if following code also works

    cy.wait(500).get('button[title="Query"]').click()
    

    A better alternative than waiting for arbitrary length is to add assertions for other DOM elements to make sure button is in a click-ready state. In my case, the button is in a tab. I clicked the tab before clicking the button. So make sure the tab is selected and elements in the tab are rendered first

    cy.get('li[aria-label="Service Selected"]')
    cy.get('table.xxx thead tr :nth-child(3)').should('include.text', 'foo')
    cy.get('button[title="Query"]').click()