How to Wait for Element to Disappear in Cypress

If element exists wait for it to disappear

Because of the timing aspect it can be tricky to get this test right.

Controlling Triggers

You really need to know what controls the spinner - usually it's a call to API. You can then delay that call (or rather it's response) to "force" the spinner to appear.

To do that, use an intercept

cy.intercept(url-for-api-call, 
(req) => {
req.on('response', (res) => res.delay(100)) // enough delay so that spinner appears
}
)

// whatever action triggers the spinner, e.g click a button

cy.getByTestId('loader-spinner') // existence is implied in this command
// if the spinner does not appear
// the test will fail here

cy.getByTestId('loader-spinner').should('not.exist') // gone after delay finishes

Two scenarios

First off, I don't think your two scenario idea is going to help you write the test correctly.

You are trying to conditionally test using try..catch (nice idea, but does not work). The trouble is conditional testing is flaky because of the timing aspect, you get the test working in a fast environment then it starts to break in a slower one (e.g CI).

Better to control the conditions (like delay above) then test page behaviour under that condition.

To test that the spinner isn't appearing, return a stub in the intercept It should be fast enough to prevent the spinner showing.

cy.intercept(url-for-api-call, {stubbed-response-object})

// whatever action triggers the spinner, e.g click a button

cy.getByTestId('loader-spinner').should('not.exist') // never appears

Take a look at When Can The Test Blink?

Wait for element to not have class - and then other element to disappear in Cypress

I Think you miss some steps, because like in this webinar, cypress can see that the element is missing from the page at the moment step 1 is implemented and the loading has not started, so it gives false positive assertion. My solution to such cases is to add more steps to the test, instead of using fixed cy.wait() -my steps are the following:

cy.get('.add_to_cart_button').click(); // Step 1
cy.get('.overlay').should( 'be.visible' ); // Needed to see that the process is starting
cy.get('.overlay').should( 'not.be.visible' ); // Needed to see that the process has ended
cy.get('.add_to_cart_button').should( 'have.class', 'loading' ); // Needed to see that the process is starting
cy.get('.add_to_cart_button').should( 'not.have.class', 'loading' ); // Needed to see that the process has ended
cy.visit( Cypress.env( 'baseUrl' ) + '/cart' ); // Step 9

Also I recommend using the following lines in the cypress.json file:

"defaultCommandTimeout": 60000,
"requestTimeout": 60000,
"responseTimeout": 60000,

How to wait for element to be visible

You can wait for the element to be visible like so:

// Give this element 10 seconds to appear
cy.get('[data-test=submitIsVisible]', { timeout: 10000 }).should('be.visible');

According to Cypress's Documentation:

DOM based commands will automatically retry and wait for their corresponding elements to exist before failing.

Cypress offers you many robust ways to query the DOM, all wrapped with retry-and-timeout logic.

Other ways to wait for an element’s presence in the DOM is through timeouts. Cypress commands have a default timeout of 4 seconds, however, most Cypress commands have customizable timeout options. Timeouts can be configured globally or on a per-command basis. Check the customizable timeout options list here.

In some cases, your DOM element will not be actionable. Cypress gives you a powerful {force:true} option you can pass to most action commands.

Cypress: Alternative for command 'wait'

My problem is not to wait till the page is successfully loaded, but till the content exist and is available/clickable etc.

With this command a small improvement is noted but is not the solution of my problem.

Cypress.config('defaultCommandTimeout', 50000);


Related Topics



Leave a reply



Submit