Cypress: cy.visit re-visited, and how should I properly wait for page load?

Created on 3 Mar 2019  路  4Comments  路  Source: cypress-io/cypress

Current behavior:

Commands after cy.visit are executed before page is fully loaded (before page loaded event is fired)

Desired behavior:

cy.visit should wait on page load event or timeout set before proceeding to any commands after it has been invoked.

Steps to reproduce: (app code and test code)

https://github.com/janusqa/cypress-test-tiny
Run test and view console (spec.js).

Versions

chrome: Version 72.0.3626.121 (Official Build) (64-bit)
linux: Ubuntu 18.04.2 LTS
Cypress package version: 3.1.5
Cypress binary version: 3.1.5

Other comments

Maybe "should" should wait instead but that fails to find the element as well because page was not fully loaded and/or "should" did not wait and/or default timeout for "should" was too short?

from the docs

When you load your application using cy.visit(), Cypress will wait for the load event
to fire. It is really this easy. The cy.visit() command loads a remote page and does 
not resolve until all of the external resources complete their loading phase.

This seems to describe what is in "### Desired Behavior" but what I get is "### Current Behavior"

question

All 4 comments

Are you judging the order of operations by the console log calls from this test?

describe('page', () => {
  it('does not work', () => {
    cy.visit('https://google.com', {
      onLoad: () => console.log('*** PAGE IS LOADED ***')
    });
    console.log('Should be printed AFTER *** PAGE LOADED ***');
  });
});

What do you see? What do you expect to see? Here is what the test prints I believe

Should be printed AFTER *** PAGE LOADED ***
*** PAGE IS LOADED ***

Please read how commands are queued in Cypress in https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Commands-Are-Asynchronous

when you do

cy.visit()
console.log('BEFORE visit')

cy.visit just adds a command to visit the page to the Cypress' internal chain of commands, but nothing is running yet. console.log on the other hand runs IMMEDIATELY, thus printing BEFORE visit _before_ visit.

In your code replace console.log('Should be printed AFTER *** PAGE LOADED ***'); with cy.log('Should be printed AFTER *** PAGE LOADED ***');. and you will see what you expect to see: first the visit (which finishes for real, not just in our imagination or future plans), and then cy.log prints a message.

If you application has a lot of actions going on AFTER page loads and you would like to wait for them to complete, just add an assertion to wait for something: DOM element to be visible, text to be found, some flag to be set, etc. See

@bahmutov

Aha! I was thinking all commands enqueued! Thanks.
I will try increasing the timeout on the "should" i use for the slow loading element and then try some technique you mentioned above.

I updated the cy.get().should() timeout to get to 20000ms arbitrarily and that seems to have "solved" the issue. The elements in questions are glyphicons calendar pickers.

However its still flaky. sometimes the timeout will work sometimes not.

you may use cy.server().route() (the last xhr of cy.visit) before cy.visit and use cy.wait(@alias) after

Also, there's this useful plugin: https://github.com/NoriSte/cypress-wait-until. Might be helpful!

Was this page helpful?
0 / 5 - 0 ratings