100

How to check if element is present or not, so that certain steps can be performed if element is present. Else certain different steps can be performed if element is not present.

I tried something like below but it didn't work:

Cypress.Commands.add('deleteSometheingFunction', () => {
  cy.get('body').then($body => {
    if ($body.find(selectors.ruleCard).length) {
      let count = 0;
      cy.get(selectors.ruleCard)
        .each(() => count++)
        .then(() => {
          while (count-- > 0) {
            cy.get('body')
            // ...
            // ...
          }
        });
    }
  });
  });

I am looking for a simple solution, which can be incorporated with simple javascript if else block or then() section of the promise

Something similar to Webdriver protocol's below implementions:

  1. driver.findElements(By.yourLocator).size() > 0
  2. check for presenece of element in wait

Kindly advise. Thanks

2

12 Answers 12

135

I'll just add that if you decide to do if condition by checking the .length property of cy.find command, you need to respect the asynchronous nature of cypress.

Example: Following condition evaluates as false despite appDrawerOpener button exists

    if (cy.find("button[data-cy=appDrawerOpener]").length > 0)    //evaluates as false

But this one evaluates as true because $body variable is already resolved as you're in .then() part of the promise:

    cy.get("body").then($body => {
        if ($body.find("button[data-cy=appDrawerOpener]").length > 0) {   
            //evaluates as true
        }
    });

Read more in Cypress documentation on conditional testing

Sign up to request clarification or add additional context in comments.

3 Comments

The if statement .length does not work any more
I don't understand how your solution if different from the one in the question. In the question also the Author as used cy.get('body').then( <find with $body tag>) you have also done the same. Can you please explain why your solution is correct?
This solution has a .length > 0 as opposed to just checking for the property itself.
14

it has been questioned before: Conditional statement in cypress

Thus you can basically try this:

cy.get('header').then(($a) => { 
        if ($a.text().includes('Account')) {
            cy.contains('Account')
            .click({force:true})
        } else if ($a.text().includes('Sign')) { 
            cy.contains('Sign In')
            .click({force:true})  
        } else {
            cy.get('.navUser-item--account .navUser-action').click({force:true})
        }
    })

Comments

11

cypress all steps are async ,, so that you should make common function in commands file or page object file,,..

    export function checkIfEleExists(ele){
    return new Promise((resolve,reject)=>{
        /// here if  ele exists or not
        cy.get('body').find( ele ).its('length').then(res=>{
            if(res > 0){
                //// do task that you want to perform
                cy.get(ele).select('100').wait(2000);
                resolve();
            }else{
                reject();
            }
        });
    })
}


// here check if select[aria-label="rows per page"] exists
cy.checkIfEleExists('select[aria-label="rows per page"]')
.then(e=>{
        //// now do what if that element is in ,,..
        })
.catch(e=>{
    ////// if not exists...
    })

Comments

7

I found a solution, hope it helps!

You can use this:

cy.window().then((win) => {
        const identifiedElement = win.document.querySelector(element)
        cy.log('Object value = ' + identifiedElement)
    });

You can add this to your commands.js file in Cypress

Cypress.Commands.add('isElementExist', (element) => {

    cy.window().then((win) => {
        const identifiedElement = win.document.querySelector(element)
        cy.log('Object value = ' + identifiedElement)
    });
})

2 Comments

Failed to execute 'querySelector' on 'Document': '[object Object]' is not a valid selector.
This solution is the one that works, I've tried the other ones but none of them works
4

Cypress official document has offered a solution addressing the exact issue.

How to check Element existence

// click the button causing the new
// elements to appear
cy.get('button').click()
cy.get('body')
  .then(($body) => {
    // synchronously query from body
    // to find which element was created
    if ($body.find('input').length) {
      // input was found, do something else here
      return 'input'
    }

    // else assume it was textarea
    return 'textarea'
  })
  .then((selector) => {
    // selector is a string that represents
    // the selector we could use to find it
    cy.get(selector).type(`found the element by selector ${selector}`)
  })

Comments

4

For me the following command is working for testing a VS code extension inside Code server:

Cypress.Commands.add('elementExists', (selector) => {
  return cy.window().then($window => $window.document.querySelector(selector));
});

And I'm using it like this in my E2E test for a Code Server extension:

cy.visit("http://localhost:8080");
cy.wait(10000); // just an example here, better use iframe loaded & Promise.all
cy.elementExists("a[title='Yes, I trust the authors']").then((confirmBtn) => {
    if(confirmBtn) {
        cy.wrap(confirmBtn).click();
    }
});

Just ensure that you're calling this check once everything is loaded.

If you're using Tyepscript, add the following to your global type definitions:

declare global {
  namespace Cypress {
    interface Chainable<Subject> {
      /**
       * Check if element exits
       * 
       *  @example cy.elementExists("#your-id").then($el => 'do something with the element');
       */
      elementExists(element: string): Chainable<Subject>
    }
  }
}

Aside

VS Code server relies heavily on Iframes which can be hard to test. The following blog post will give you an idea - Testing iframes with Cypress.

The above code is needed to dismiss the "trust modal" if it's shown. Once the feature disable-workspace-trust is released it could be disabled as CLI option.

Comments

3

This command throws no error if element does not exist. If it does, it returns the actual element.

cypress/support/commands.js

elementExists(selector) {
  cy.get('body').then(($body) => {
    if ($body.find(selector).length) {
      return cy.get(selector)
    } else {
      // Throws no error when element not found
      assert.isOk('OK', 'Element does not exist.')
    }
  })
},

Usage:

cy.elementExists('#someSelectorId').then(($element) => {
  // your code if element exists
})

1 Comment

That's not how you write a custom command, if that's your intention.
3

This solution worked for me:

cy.get('body').then($body => {
    if ($body.find("mat-option[aria-selected='true']").length) {
        //Do something if exist
    }
    else{
        //do if not exist
    }
})

Comments

1

I had the same issue like button can appear in the webpage or not. I fixed it using the below code.

export function clickIfExist(element) {
cy.get('body').then((body) => {
cy.wait(5000).then(() => {
  if (body.find(element).length > 0) {
    cy.log('Element found, proceeding with test')
    cy.get(element).click()
  } else {
    cy.log('Element not found, skipping test')
  }
})
})
}

Comments

1

The best way would be to check if either of two, three, etc. elements exist on a page, and decide what to do with it if it's found.

This way you can proceed with the scenario immediately without extra pausing time.

Here is working example (tested on Cypress 12.13.0):

cy.get('.deactivate-session-button, .start-work-buttons-area').then(el => {
  if (el.text() == 'End other sessions') cy.wrap(el).click()
})
cy.get('.start-work-buttons-area')

If the element was found with text "End other sessions" (it's a button) it will be clicked. If not, it means you're already logged in and can proceed to your next steps.

Hope it helps!

Comments

1

In case somebody is looking for a way to use cy.contains to find an element and interact with it based on the result. See this post for more details about conditional testing.

Use case for me was that user is prompted with options, but when there are too many options, an extra click on a 'show more' button needs to be done before the 'desired option' could be clicked.

Command:

Cypress.Commands.add('clickElementWhenFound', (
    content: string,
) => {
    cy.contains(content)
        // prevent previous line assertion from triggering
        .should((_) => {})
        .then(($element) => {
            if (!($element || []).length) {
                /** Do something when element was not found */
            } else {
                cy.contains(content).click();
            }
        });
});

Usage:

// Click button with 'Submit' text if it exists
cy.clickElementWhenFound('Submit');

1 Comment

Your URL is broken
-2

Using async/await gives a clean syntax:

const $el = await cy.find("selector")
if ($el.length > 0) {
  ...

More info here: https://medium.com/@NicholasBoll/cypress-io-using-async-and-await-4034e9bab207

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.