Waiting for an Ajax Request

Let's learn about the Ajax request in testing.

AJAX request

Do you remember the list of problems that would break the signup flow? We fixed the DOM-related ones by retrieving the elements based on the contents instead of the order, but there were a lot of problems related to the AJAX request itself:

  • The AJAX call does not start.

  • The AJAX call has the wrong request payload.

  • The API does not work and it does not respond.

  • The API returns the wrong payload.

  • The user already exists.

The tests we’ve covered so far still do not solve these errors. When they fail, we need to spend some time debugging the web app during testing to discover that the issue is related to the incorrect AJAX request. Don’t worry, Cypress will improve the E2E testing experience!

Server contract

When we test the front-end of our web app, we need to consider it as a closed block (i.e. blackbox testing) and check its interactions with the external world. We need to test the contracts between the front-end and all other involved entities. What contracts should be recognized by the front-end app?

  1. Functional contract with the user: The subject of all E2E tests.

  2. Presentational contract with the user: The subject for all visual regression tests (which will be discussed later).

  3. Contract with the server: The subject of front-end communication with the back-end.

We need to concentrate on the last one because the front-end often stops working due to a misaligned communication with the back-end.

AJAX request waiting

Because we know that an AJAX request happens systematically, we know that an AJAX request will occur every time we run the app. Thus, we need to consider the AJAX request in our Cypress test. The signup flow is a good example. Let’s see what APIs allow us to do consider the AJAX request.

First, we need to set up AJAX call interception:

it("The happy path should work", () => {
+ cy.intercept("POST", "**/api/users");

  cy.visit(paths.register);
  // the rest of the test code
});
  • cy.intercept tells Cypress to intercept some requests. We can use a lot of options to match precisely which AJAX request we want to intercept.
  • cy.intercept("POST", "**/api/users") tells Cypress to intercept every POST request to every URL that ends with **/api/users as the signup form makes a request to the http://localhost:3100/api/users to take advantage of * and ** glob support.

Second, we need to set a Cypress alias to reference it later on.

it("The happy path should work", () => {
  cy.intercept("POST", "**/api/users")
+   .as("signup-request");

  cy.visit(paths.register);
  // the rest of the test code
});

Third, we must “wait” for the AJAX request triggered by the front-end app.

it("The happy path should work", () => {
  cy.intercept("POST", "**/api/users")
    .as("signup-request");
  cy.visit(paths.register);
  // form filling code
  cy.get("form")
    .within(() => cy.findByText(strings.signUp).click());
+ cy.wait("@signup-request");
  cy.findByText(noArticles, { timeout: 10000 }).should("be.visible");
});

What does “waiting” mean when applied to an AJAX request? The test will then wait up to 5 seconds for the front-end to begin the AJAX request and up to 30 seconds for the back-end to fulfill the request (both of the timeouts are customizable). Here, we can see the advantages of automatic Cypress waitings mixed with AJAX requests management! Essentially, AJAX will ask Cypress to wait viacy.wait("@signup-request");

Do you remember why we added the custom timeout to the cy.findByText(noArticles, { timeout: 10000 }) call? We initially added the timeout due to the problem that cy.contain (later replaced by cy.findByText) sometimes failed because the AJAX request took too long (and the default cy.contain/cy.findByText timeout is 4000 milliseconds). Now we do not need this timeout anymore because the cy.wait knows that an AJAX request could take a really long time!

- cy.findByText(noArticles, { timeout: 10000 }).should("be.visible");
+ cy.findByText(noArticles).should("be.visible");

That’s all the changes we applied to the test

Create a free account to view this lesson.

By signing up, you agree to Educative's Terms of Service and Privacy Policy