Search code examples
conditional-statementscypress

Cypress test for element existence conditionally with retry


I read the caveats in the docs on Cypress conditional testing, but nevertheless need to apply it to a particular test for certain reasons.

I have a function to do it, but there are certain selectors that do not work due to lack of retry in this function.

How can I implement retry in conditional testing and avoid flaky tests?

Is it even possible, or does one thing cancel out the other?

export function elementExists(selector: string): boolean {
  try {
    return Cypress.$(selector).length > 0;
  } catch (error) {
    return false;
}

Solution

  • The "standard" way to test existence of an element is pretty simple, but it does not return true/false. It fails the test if element is not found.

    cy.get(selector).should('exist')
    

    Internally the .should() retries the element until command timeout is finished - then fails the test.

    If you make your function recursive, you can do the same but instead of failing, return true/false.

    function elementExists(selector, attempt = 0) {
    
      const interval = 100;  // 100ms between tries
      if (attempt * interval > Cypress.config('defaultCommandTimeout')) {
        cy.log(selector, 'not found')
        return cy.wrap(false, {log:false})      
      }
    
      return cy.get('body', {log:false}).then(($body) => {
        const element = $body.find(selector)
        if (element.length) {
          cy.log(selector, 'found')
          return cy.wrap(true, {log:false}) 
        } else {
          cy.wait(interval, {log:false})  
          return elementExists(selector, ++attempt)
        }
      })
    }
    
    elementExists(selector).then(exists => {
      if (exists) {
        ...
      }
    })