Cypress Waitings and Execution Order

Learn how Cypress executes and waits for commands.

Cypress waitings and execution order

In the previous lesson, we wrote the following initial test:

it("The happy path should work", () => {
  cy.visit("/register");
  cy.get(".form-control").then($els => {
    cy.get($els[0]).type("Tester");
    cy.get($els[1]).type("user@realworld.io");
    cy.get($els[2]).type("mysupersecretpassword");
    cy.get("button").click();
    cy.contains("No articles are here").should("be.visible");
  });
});

Without noting it, we’ve leveraged some of Cypress’s interesting features.

Automatic waiting

Did you notice that the test seems to have a synchronous flow? Think about what happens between a command and the next one:

cy.visit("/register");
// what does "visit" mean? When is Cypress going to execute the next commands? Is JavaScript ready?
cy.get(".form-control").then($els => {
  cy.get($els[0]).type("Tester");
  // typing is an asynchronous task, when will the next task start?
  cy.get($els[1]).type("user@realworld.io");
  cy.get($els[2]).type("mysupersecretpassword");
  cy.get("button").click();
  // the web app makes an AJAX call, a lot of time passes before the "No articles are here" text becomes visible
  cy.contains("No articles are here").should("be.visible");
});

In UI tests, everything is asynchronous: The JavaScript execution is asynchronous, the DOM update is asynchronous, and the actions of the user are asynchronous. A synchronous approach is a failure by definition.

Whereas, most of the existing browser automation tools (like Selenium or Puppeteer) force you to manually manage many asynchronous situations, while Cypress was created with asynchronous UI testing in mind.

Automatic waitings are important because:

  • They allow you to heed no mind to most asynchronous updates.

  • They make the test as fast as possible, avoiding fixed, slow, and brittletest pauses.

Answering the questions added as comments to the above snippet:

  • cy.visit waits for the window to dispatch the load event

  • The next command is not executed until the typing ends.

  • Cypress retries cy.contains, cy.get, and other commands by default. The commands have customizable timeout and when Cypress is not able to find the requested elements, they are retried until the elements are either added to the page or report an error.

Test Runner interactivity

Test Runner shows you what’s happening in:

  1. The front-end application

  2. Every executed Cypress command

  3. The result of all assertions

As we’ve seen in the previous lesson, Test Runner is also interactive!

TTest Runner allows you to “time travel” through various phases of code and check the state of the front-end before and after the execution of every command. Take a look at the Test Runner documentation to discover more about it.

Test code execution order

Because Cypress command is asynchronous by default, Cypress automatically executes the test code twice:

  • First, Cypress executes the test code to read and queue all the commands it needs to execute.

  • Second, Cypress loads the page and executes, all the commands previously queued, one by one.

Try changing the test code to the following code.

Note: You can see the Cypress UI better by opening the link next to Your app can be found at:

Get hands-on with 1200+ tech skills courses.