How to wait for element to disappear in cypress? [duplicate]
Asked Answered
A

9

65

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?

Aztec answered 7/12, 2018 at 15:22 Comment(3)
Why don't you want to use an assertion?. I use .should("not.be.visible") every time I need to wait for an element to disappear, it works perfectly. Also, please let us know what you mean by "it does not seem to work for me" - is there an error? timeout? Post the output.Wooded
When your loading indicator is done does the DOM change in anyway? Are things added to the DOM once the loading indicator is done?Chekiang
Is this your actual code? That code would throw a syntax error, as it's missing single quotes after element and after not.exist.Loincloth
R
33

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.

Renferd answered 12/5, 2020 at 11:12 Comment(3)
from cypress-wait-until#readme The most common case is checking that an element exists or not, instead of using cy.get('#id').should('exist') you should check that Cypress.$('#id').length is greater than 0Cambria
This doesn't return a truthy value so the waitUntil never exitsHarebrained
This answer is incorrect - this wait will never return.Weinreb
G
33

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

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

It waits automatically.

Gatehouse answered 26/1, 2022 at 18:6 Comment(2)
+1, this should be the accepted answer. Fast, simple, clean, and solves the problem. If you want another max timeout, just use the standard way of overriding the default: cy.get('.selector', { timeout: 10000 }).should('not.exist') docs.cypress.io/api/commands/should#TimeoutsPlanimetry
For an element such as a wait spinner that is dependent on other calls and loading status, this is simpler than other solutions.Hellhole
S
24

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

Schoolhouse answered 7/12, 2018 at 16:3 Comment(8)
So how do you wait for an animation to finish?Ghislainegholston
@EgorPavlikhin please refer to this section of Cypress documentation.Schoolhouse
the loading indicator is binded to network request, but sometimes multiple requests are made and as we use graphQL, all requests look the same. And i´m only interested in the last one as that is the only request the application care about.Aztec
Do you have any tips regarding pattern matching urls in cy.route(..)? I seem to find it difficult to match the url for which I want to wait.Gemoets
@Gemoets Under the hood Cypress uses minimatch to match glob patterns of url. You can test it here.Schoolhouse
how do we wait if it is a Postback (e.g. asp.net postback on dropdown change)? as the postback does not have any URLMegass
@DiogoRocha waiting for @getAccount' does not in any way guarantee that the loading spinner is gone when the XHR is finished, which is what the user asked for - still, you have provided the most appropriate solution at the end of your post.Loincloth
Watching API call is unreliable and have hidden dependencies of APIs. Any API call route changes, though may not impact functionality, would cause the test fail.Bergman
L
16

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

Loincloth answered 3/4, 2020 at 16:51 Comment(2)
Is there a way to extend how long it waits? Otherwise, I'll just set up cy.intercept and cy.wait calls accordingly to await the underlying network requests.Semblable
@Semblable you can pass in the wait time tp cy.get(). Ex: cy.get("element", { timeout: timeToWait })Hamfurd
A
2

.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'>

Aimeeaimil answered 12/5, 2020 at 4:21 Comment(0)
S
1

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.

Solidarity answered 18/11, 2020 at 22:38 Comment(0)
E
0

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))
Extortionate answered 11/8, 2021 at 15:3 Comment(0)
B
0

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

Battologize answered 23/10, 2023 at 8:34 Comment(1)
Please edit to a) remove judgment of other answers (future answers may also be misleading by the way) b) provide textual information as text instead of as pictures of text c) elaborate a little on the consequences and possible workarounds for your statment.Quieten
P
-2

Either of these should work:

.should('not.be.visible')

or

.should('not.exist')

Else go for installing and using:

cypress-wait-until

Prankster answered 5/1, 2023 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.