A Simple Cypress Command That Catches Bugs Like Magic ✨

Published: at 08:40 PM

Hey everyone! I wanted to share a small but impactful piece of work that is adding significant value to our automation tests with minimal effort. We’ve created a simple Cypress command that has contributed to nearly one-fourth of the total issues caught by our automation tests 🎉

The idea is straightforward: it checks that none of our pages are throwing API errors. If you’re new to Cypress, this is an easy and effective way to boost your testing without feeling overwhelmed.

How to set it up?

Cypress.Commands.add("verifyApiStatus", (page, timeout, expectedStatusCodes) => {
  // Intercept all API calls made to the specified endpoint
  cy.intercept("/api/**").as(page);

  // Navigate to the specified page (e.g., "/dashboard")
  cy.visit(page);

  // Wait for the specified duration to allow API calls to complete
  // (e.g., 10000 or 15000 milliseconds)
  cy.wait(timeout);

  // Check each intercepted API response
  cy.get(`@${page}.all`).each(interception => {
    // Verify that the response exists and has a status code
    if (interception.response && interception.response.statusCode) {
      // Assert that the status code matches one of the expected values
      expect(interception.response.statusCode).to.be.oneOf(expectedStatusCodes);
    }
  });
});
it("Verifies that the API for the dashboard and users page loads without errors", function () {
  // Include the steps to log in

  // Verify the API status for the dashboard and users pages,
  // expecting status codes 200, 201 or 404
  cy.verifyApiStatus("/dashboard", 10000, [200, 201, 404]);
  cy.verifyApiStatus("/users", 10000, [200, 201, 404]);
});

Why Is This Useful? 🤔

This small command has made a big difference for us. If an API call returns a status code like 500, the test will fail, alerting you to potential issues immediately. If you’re just starting with Cypress, using this command can save you time and help ensure your app is stable. Simple, powerful, and effective! 💥

Editor’s note: three ways to harden it

Rojal’s command is a great starting point, and it’s worth knowing where it will bite you as the suite grows.

1. The fixed cy.wait(timeout) is the weak spot. A hardcoded 10-second wait is both too slow on a fast run and too short on a slow one — it’s the single most common source of flaky tests. Waiting on the alias instead makes the test wait exactly as long as it needs to:

cy.wait(`@${page}`, { timeout: 15000 });

That waits for the first matching call. When a page fires several, wait on the specific ones you care about rather than a wall-clock guess.

2. .each() over zero interceptions passes silently. If the route never matched — a typo in the pattern, a changed API prefix — the command asserts nothing and the test goes green. Assert that something was actually captured:

cy.get(`@${page}.all`).should("have.length.greaterThan", 0);

A test that can’t fail isn’t protecting anything, and this is the failure mode that quietly hollows out a suite over time.

3. Consider inverting the assertion. Listing every acceptable code ([200, 201, 404]) means each new endpoint needs its list maintained. Asserting that nothing returned a server error is often closer to what you actually mean, and needs no per-page configuration:

expect(interception.response.statusCode).to.be.lessThan(500);

Whichever way you go, the value of this command is real: a whole class of “the page looks fine but the data silently failed to load” bugs gets caught for about fifteen lines of code. If a run does go red and the message isn’t obvious, the Cypress error reference covers the ones that come up most.

👉🏻 By:Rojal Bati