Asserting Asynchronous Events
Learn built-in waiting mechanisms for action commands, retries for certain commands, and the ability to override timeouts.
In Cypress, we don’t have to manually wait for asynchronous events because Cypress handles them automatically. The default functionality of Cypress makes it trivial to work with asynchronous scenarios if we know how to avoid a few common pitfalls. Let’s practice some of the most common scenarios with a few examples.
Example application
Let’s look at the following application that showcases some common asynchronous events we encounter in React applications.
describe("Async examples", () => { it("Automatically waits until object is in dom", () => { cy.visit("/"); cy.get("button").click(); cy.contains("Clicked"); }); it("Overriding timeout", () => { cy.visit("/"); cy.get("button").click(); cy.contains("Clicked", { timeout: 1000 }).should("not.exist"); }); it("Automatically waits until buttons are actionable", () => { cy.visit("/"); cy.get("button").click(); cy.get("button").click(); cy.contains("Button clicks: 2"); }); it("Can force clicking on a disabled button", () => { cy.visit("/"); cy.get("button").click(); cy.get("button").click({ force: true }); cy.contains("Button clicks: 1"); }); it("Waits incorrectly", () => { cy.visit("/"); cy.get("button").click(); cy.contains("Button clicks") .invoke("text") .then((text) => text.split(": ")[1]) .should("eq", "1"); }); it("Waits correctly", () => { cy.visit("/"); cy.get("button").click(); cy.contains("Button clicks") .invoke("text") .should((text) => { const count = text.split(": ")[1]; expect(count).eq("1"); }); }); }); export {};
Lines 3–7: We define an object where the keys are the possible values of the button’s state, and the values are titles for them.
Line 10: We define a state for tracking the number of times the button is clicked.
Lines 11–13: We define a state for the button. We use the
useState
hook with a type parameter to enforce that the state can only have one of three specific string values:IDLE
,SUBMITTING
, orSUBMITTED
. This helps ensure that the state can only have valid values and prevents typos or other errors.Lines 15–23: We use the
useEffect
hook to handle the button’s state changes. If the button is in theSUBMITTING
state, a 2-second timer is set to update the button’s state toSUBMITTED
and increment the button click count.Line ...