jaikl
jaikl

Reputation: 1091

How to wait for element to disappear in cypress?

I have a loading indicator that I need to wait for to disappear before doing my assertions.

I've seen some use the following, but it does not seem to work for me and also I don´t want it to be an assertion.

cy.get('element', {timeout: 10_000}).should('not.exist');

Anyone having any tips?

Upvotes: 66

Views: 96482

Answers (9)

Shelly Nezri
Shelly Nezri

Reputation: 23

According to documentation you should not make assertions inside waitUntil: enter image description here

https://github.com/NoriSte/cypress-wait-until/issues/75#issuecomment-572685623

Upvotes: 0

Amit Verma
Amit Verma

Reputation: 197

Either of these should work:

.should('not.be.visible')

or

.should('not.exist')

Else go for installing and using:

cypress-wait-until

Upvotes: -2

voy
voy

Reputation: 717

IMHO the cleanest way is not to use waits nor timeouts with get, this is kinda an antipattern.

I would recommend to use Cypress waitUntil command and use something like:

 cy.waitUntil(function() {
  return cy.get('element').should('not.exist');
 })

or depending on the app code you can use not.be.visible.

Upvotes: 32

Alien
Alien

Reputation: 1162

cypress-wait-until did not work for me. I just used the basic:

cy.get('.ant-drawer-body').should('not.exist');

It waits automatically.

Upvotes: 35

leonheess
leonheess

Reputation: 21361

Use cypress-wait-until like this:

cypress/support/commands.js:

import 'cypress-wait-until'

test.spec.js:

cy.waitUntil(() => cy.get('element').then($el => $el.length === 0))

Upvotes: 0

MetaWhirledPeas
MetaWhirledPeas

Reputation: 486

Diogo Rocha's approach is important to use for a lot of cases, but to be really certain the image is gone you need to follow Philzen's advice. Assert that it's not visible, and the test playback will wait for it to disappear.

This is especially important when you plan to take a screenshot or a visual snapshot, because the XHR request returning does not necessarily mean the image is gone.

Upvotes: 2

Josh Pittman
Josh Pittman

Reputation: 7324

.findByTestId('loading-spinner-data-testid').should('not.be.visible')

This works in a similar context for me.

As of "@testing-library/cypress": "^5.3.1",

Just make sure you give your spinner component a data-testid attribute.

<LoadingSpinner data-testid='loading-spinner-data-testid'>

Upvotes: 2

Philzen
Philzen

Reputation: 4647

Loading spinner implementations often just hide the element rather than removing it from the DOM. Hence, should("not.exist") won't work for them.

cy.get("element").should("not.be.visible") is the right approach in such cases (as Diogo's answer already hinted).

Upvotes: 16

Diogo Rocha
Diogo Rocha

Reputation: 10575

If you specifically need to wait, you could use the wait() function of cypress before making an assertion, and provide the amount of time to wait before timeout.

But note, this is an anti-pattern as you can find in the docs:

You almost never need to wait for an arbitrary period of time. There are always better ways to express this in Cypress.

That said, if your loading indicator is bound to some network request, you can wait for them to finish before making an assertion. This could be achieved with something like this example:

// Wait for the route aliased as 'getAccount' to respond
// without changing or stubbing its response
cy.server()
cy.route('/accounts/*').as('getAccount')
cy.visit('/accounts/123')
cy.wait('@getAccount').then((xhr) => {
  // we can now access the low level xhr
  // that contains the request body,
  // response body, status, etc
})

More info about waiting for requests could be found here.

Also, make sure that you really want to use .should('not.exist') and not .should('not.be.visible').

Upvotes: 24

Related Questions