如何使用 Cypress.io 检查元素是否存在

如何检查元素是否存在,以便在元素存在时执行某些步骤。否则,如果元素不存在,可以执行某些不同的步骤。

我试了下面这样的方法,但是没有用:

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')
// ...
// ...
}
});
}
});
});

我正在寻找一个简单的解决方案,它可以与简单的 javascript 结合 如果其他 块或者 那么(())节的承诺

类似于 WebDriver 协议下面的实现:

  1. driver.findElements(By.yourLocator).size() > 0
  2. 检查是否有待检元件

好心建议,谢谢

136715 次浏览

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})
}
})

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.

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

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...
})

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

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)
});
})

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
})

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}`)
})

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.

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');