How to Wait until page is fully loaded
Asked Answered
C

4

13

I'm using Cypress to test my spa. Sometimes the page displays quickly and sometimes it is very slow. I need to be able to check for a button or text that will display once the page is loaded, but do not want to wait for eternity.

I've been using excessively long wait periods but would like the test to run faster.

let targeturl = 'http:\\something.com'
let longwait = 2500

describe('Update Case', () => {
  it('Create Case', () => {   
    cy.visit(targeturl)
    cy.wait(longwait)
    cy.get('button').contains('Create').click()

I want to be able to set a wait that waits until the button 'Create' is displayed.

Coo answered 10/7, 2019 at 14:33 Comment(0)
R
19

By default, Cypress will wait for your page to load all resources before continuing the test. Your cy.wait() shouldn't be necessary. The default timeout for cy.visit() is 60 seconds.

Also, cy.get() will retry finding your element until the element exists. The default timeout is 4 seconds, but you can increase it.

Something like this is generally all you need:

describe('Update Case', () => {
  it('Create Case', () => {   
    cy.visit(targeturl)
    cy.get('button').contains('Create').click()

If you find that this isn't working, perhaps because your page takes more than 4 seconds to render after it loads all resources, then you can do something like this:

describe('Update Case', () => {
  it('Create Case', () => {   
    cy.visit(targeturl)
    // wait up to 30 seconds for some element to exist before continuing the test
    cy.get('.some-element-in-your-app-that-only-exists-once-page-has-loaded', { timeout: 30000 })
    cy.get('button').contains('Create').click()

In general, you shouldn't ever need to use cy.wait() to delay your tests by a certain number of milliseconds. Doing so is almost always a bad practice.

Regimen answered 10/7, 2019 at 14:42 Comment(3)
Adding the timeout as an option to the get is what I'm looking for. It is taking longer to load, but only on the first load. ThanksCoo
I understand the solution and what you want to achieve with it. I came up with a very similar solution. I sometimes get page loading errors, because the authentication fails or something. With this solution, my test waits a long time in each of these cases, even though meanwhile the error page got loaded. That's why I'm still waiting for a better solution.Forbidden
I actually like this for initial visits. We use something custom to check for loading after clicks, navigation etc. but the initial render doesn't have the DOM to work with. Trying to grab something in it before saying visit is down sounds obvious.Melodimelodia
K
1

What about writing some assertion like .should() :

let targeturl = 'http:\\something.com'
let longwait = 2500

describe('Update Case', () => {
  it('Create Case', () => {   
    cy.visit(targeturl)
    cy.url().should('include',targeturl)
    cy.get('button').contains('Create').click()

That worked for me in some cases I needed to have page load complete before selecting any content from page.

Krause answered 19/1, 2022 at 15:49 Comment(0)
M
0

For any newcomers to this question/problem:

The Cypress docs explicitly discourage arbitrary wait() usage, while thankfully now supplying solutions using intercept() and an aliased route.

Here's how it'd work per the docs. Say you want to wait for the /users page/endpoint to load and then you want to check that a DOM element like a table is present, here's how you'd do it.

cy.intercept('GET', '/users').as('getUsers')
cy.get('[data-testid="fetch-users"]').click()
cy.wait('@getUsers') // <--- wait explicitly for this route to finish
cy.get('table tr').should('have.length', 2)

And if after that you still have issues, like XHR request still completing after page load and therefore halting your element from appearing, then you can pass the timeout prop to cy.get() like this

cy.get('table tr', { timeout: 20000 }).should('have.length', 2)

Cypress wont wait for that whole length of time if it's already loaded and doesnt need it, thanks to your previous intercept/aliased route usage (unlike wait which stalls your tests no matter what.) But that'll give you extra padding if you need it.

Motoneuron answered 15/9, 2023 at 1:49 Comment(0)
F
-3

I think you might want to use timeout option of visit:

cy.visit(targeturl, { timeout: 30000 })

I remember I was having similar issue in the past, this Github issue provided me some useful information back then.

Forcemeat answered 10/7, 2019 at 14:42 Comment(2)
cy.visit has a default timeout of 60 seconds, see the docsRegimen
using timeout won't handle many casesRacialism

© 2022 - 2024 — McMap. All rights reserved.