I'm having an issue with my Cypress test where I use cy.wait()
to ensure a dropdown menu is fully loaded before interacting with it. However, I know that using cy.wait()
is not a best practice. Here's the relevant part of my code - I'm using TypeScript:
cy.get(this.searchBarDropdownOptions).within(() => {
// searchBarDropdownOptions = ".cdk-overlay-connected-position-bounding-box";
cy.wait(1000);
cy.contains("li", siteName).click();
cy.wait(1000);
cy.contains("li", location).click();
cy.wait(1000);
cy.contains("li", connectionStatus).click();
cy.wait(1000);
cy.contains("li", offline).click();
});
Problem:
The test fails because the dropdown menu is not always loaded and visible when Cypress tries to interact with it. I want to replace cy.wait()
with a more reliable method, such as assertions, to wait for the elements to be visible.
Question:
How can I replace cy.wait()
with assertions or a better approach to ensure the dropdown menu is fully loaded and visible before interacting with it?
What I've Tried:
I've already tried the following methods, but none of them worked reliably:
- Using
{ timeout: 1000 }
cy.get('li').contains(...).should('be.visible')
cy.get('li').contains(...).should('exist')
cy.waitUntil(() => ...)
I'm having an issue with my Cypress test where I use cy.wait()
to ensure a dropdown menu is fully loaded before interacting with it. However, I know that using cy.wait()
is not a best practice. Here's the relevant part of my code - I'm using TypeScript:
cy.get(this.searchBarDropdownOptions).within(() => {
// searchBarDropdownOptions = ".cdk-overlay-connected-position-bounding-box";
cy.wait(1000);
cy.contains("li", siteName).click();
cy.wait(1000);
cy.contains("li", location).click();
cy.wait(1000);
cy.contains("li", connectionStatus).click();
cy.wait(1000);
cy.contains("li", offline).click();
});
Problem:
The test fails because the dropdown menu is not always loaded and visible when Cypress tries to interact with it. I want to replace cy.wait()
with a more reliable method, such as assertions, to wait for the elements to be visible.
Question:
How can I replace cy.wait()
with assertions or a better approach to ensure the dropdown menu is fully loaded and visible before interacting with it?
What I've Tried:
I've already tried the following methods, but none of them worked reliably:
- Using
{ timeout: 1000 }
cy.get('li').contains(...).should('be.visible')
cy.get('li').contains(...).should('exist')
cy.waitUntil(() => ...)
- Please provide a minimal reproducible example. – jabaa Commented Feb 6 at 10:24
1 Answer
Reset to default 2If the menu list is not populated when the page is loaded, then an API call is used to add values to the list.
On page load the list has 0 items, or perhaps 1 placeholder item is present. When the API finishes it has 4 items (presuming your test is checking all the items).
So, you can just assert the list has the correct number before using the click()
action.
Something like this is the alternative to waiting a period of time. The {timeout}
option is only needed if things are really slow, normally 4 seconds provided by defualt is adequate.
It's also important to assert something the is the result if the first click()
, otherwise the page can be out of sync on the second click.
cy.get(this.searchBarDropdownOptions).within(() => {
// wait for the options
cy.get('li', {timeout:10_000}).should('have.length', 4);
// now click one
cy.contains("li", siteName).click()
// now assert something that occurs after the click
cy.get('#sitename').should('contain', 'This is the site name')
// now click the next
cy.contains("li", location).click()
//etc
Notes
Using { timeout: 1000 }
- that makes it worse, the normal timeout is 4000 so don't reduce the timeout.