I recently installed Cypress 10
on a personal project and I was implementing a dummy test to ensure everything works. I decided to go a bit "the extra" mile on the example and I am wondering why the following assertions fail. The scenario is the following: the user types into a search box, and a list of cultural events
is displayed. The user clicks an anchor on the first one; This causes the page to go from /
to /events/:event_id
(most of these things are still hard-coded hence the usage of .first
when finding items (instead of looking for a specific listitem
)... Now, the problem arises with the expectations that come after that.
If I add a cy.wait
expression, the assertions work; If I do not use cy.wait
nor cypress-testing-library#within
, the assertions work... If I do not use cy.wait
and use within
, the assertions fail regardless of having or not having timeouts spread all over the code. Note that, I am confident by verification, that the assertions are supposed to be within a main
HTML element. I have the browser element-inspect open right next to me, as well as the Next code that renders the <AppLayout>
and sticks the content within the main
element.
I would like to know the alternatives to cy.wait
since this is not a very reliable way of waiting for elements to render. Also, if someone can explain the reasoning behind these failings, it would be great.
describe("dummy spec", () => {
it("passes", () => {
const testEvent = "networking for introverts";
const testEventRegExp = new RegExp(testEvent, "i");
cy.visit("/");
cy.findByRole("banner").within(() => {
cy.findByRole("searchbox", { name: /search events/i }).type(`${testEvent}{enter}`);
});
cy.findByRole("main").within(() => {
cy.findAllByRole("listitem")
.first()
.within(() => {
cy.findByRole("link", { name: testEventRegExp }).click();
});
});
cy.location("pathname").should("eq", "/events/e2");
// Waiting the tinniest bit and the expectations below pass as expected
// cy.wait(25);
cy.findByRole("main").within(() => {
cy.findByRole("heading", { name: testEventRegExp })
// Assertion fails regardless of specified timeout amount
.should("be.visible", { timeout: 1000 })
.contains(testEvent, {
matchCase: false
});
cy.findByTestId("event-summary").should("be.visible");
cy.findByTestId("event-description").should("be.visible");
});
});
});
First thing I would say is 25 ms is nothing compared to the overall test duration (about 1/12 the time of a blink).
Don't be concerned about the principle of cy.wait()
if it's what makes the test work, but burn-test to make sure you have the right duration.
Since you have a Next app which has React as base framework, and if you use functional components (hooks) you may be able to use cy.wait(0)
.
Javascript is single-threaded, meaning any code running in the test will hog the thread until blocked by, say a network call or a setTimeout()
.
Using wait(0)
blocks the test momentarily and allows the React hooks to complete.
This also fits with your observation that adding timeout does not work.
// Assertion fails regardless of specified timeout amount
.should("be.visible", { timeout: 1000 })
However timeout: 1000
is going the wrong way - normal timeout is 4000
so you want to try 10000
.