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

Viewed 597

I have a flow, where I put something in a cart on a webshop, and then this occurs:

  1. I choose the options and click 'Add to cart'.
  2. Small delay (like 200ms)
  3. An overlay appears, with a loading indicator (for about 1000ms)
  4. The overlay disappears.
  5. Small delay (like 200ms)
  6. The 'Add to cart'-button reaches a loading-state (with a spinner)
  7. The loading-state (the spinner) disappears
  8. The product gets added to the cart.
  9. Go to cart (confirming that the product was added).

How do I chain this together in Cypress?

Attempt 1

The small delays and the order of things messes it up.

cy.get('.add_to_cart_button').click(); // Step 1
cy.get('.overlay').should( 'not.be.visible' ); // Step 4
cy.get('.add_to_cart_button').should( 'not.have.class', 'loading' ); // Step 7
cy.visit( Cypress.env( 'baseUrl' ) + '/cart' ); // Step 9

But the flakyness is unreal!

Sometimes it goes to the cart, showing an empty cart (if it checks for the overlay and the loading-state of the button are reaches within the small delays.

Attempt 2

I even tried adding some quick-fixes, adding cy.wait(3000) a couple of places. But even then it gives me this error:

wait 3000

!! TypeError
The following error originated from your application code, not from Cypress.

  > Cannot read property 'indexOf' of undefined

When Cypress detects uncaught errors originating from your application it will automatically fail the current test.

This behavior is configurable, and you can choose to turn this off by listening to the uncaught:exception event.Learn more


Ideally, I should check that the overlay are both shown and then hidden, to ensure that the order of things occurs in the order described above. I'm just afraid that it's shown for such a brief amount of time, that Cypress will miss that it was there, leading to even more flakyness.

1 Answers

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,
Related