Find broken navigation links using Cypress

Victor Bruce-Crabbe
2 min readJan 22, 2024
Photo by Dawid Zawiła on Unsplash

Seeing a 404 not found page when visiting a website as a user isn’t just frustrating and unpleasant but also an indication not to return to such a website. Aside from the bad user experience, broken links also negatively affect your SEO(Search Engine Optimization) ranking due to a high bounce rate.

Many factors account for broken links on a website, but the most common reasons are a deleted page, a page moved to another URL, an expired domain, or a wrong URL address entered.

Detecting Broken Links

In detecting broken links, our interest mainly lies in the HTTP 404 response status code, which indicates that a link leading to a specific page is missing on the server.

We can use Cypress to automate visiting each link on our website to check for broken links.

Test thought Process

  1. Visit the website you want to test for broken links.
  2. Get all the available links(URLs) for the Navigation component.
  3. Send HTTP requests to the URLs.
  4. Verify it’s throwing any error by logging the response.

Cypress Test To Find the Broken Link

// navigation.cy.ts
describe("Broken Navigation Links", () => {

beforeEach(() => {
cy.visit("http://localhost:3000/");
});

it("should find all broken links in the navigation component", () => {
cy.get("[data-test='navbar']")
.find("a:not([href*='mailto:'])")
.each(($link) => {
if($link.prop("href")) {
cy.request({
url: $link.prop("href"),
failOnStatusCode: false
})
}
cy.log($link.prop("href"));
});
});
});

Understanding the Code above:

Step 1:

beforeEach(() => {
cy.visit("http://localhost:3000/");
});

👉 Before each test case(it block), visit the URL http://localhost:3000/

Step 2:

cy.get("[data-test='navbar']")

👉 Get the navigation bar element using the data-test attribute on the nav element. <nav data-test="navbar"></nav>

Step 3:

cy.get("[data-test='navbar']").find("a:not([href*='mailto:'])")

👉 Chain the find() query method to find descendant elements with a selector. We find all anchor elements excluding “mailto” anchor elements within our nav element.

Step 4:

cy.get("[data-test='navbar']")
.find("a:not([href*='mailto:'])")
.each(($link) => {}) // step 4

👉 Iterate through each a element excluding the ones with href="mailto" using the .each() command.

Step 5:

// continuing from the .each() command
.each(($link) => {

})

👉 Validate if each <a> has the href attribute. If validation passes, make an HTTP request usingcy.request() . By default cy.requesttakes in a string as an argument cy.request('https://google.com') for example.

But in our case, we changed the default behavior of cy.request by passing in an options object. Aurloption(for making HTTP requests) and a failOnStatusCode option to fail on response codes other than 2xx and 3xx.

By default failOnStatusCode option is true . Since we are logging each request using cy.log(), we will set failOnStatusCode: false to avoid the test from stopping abruptly when we encounter response codes other than 2xx and 3xx.

References:

I was able to gather information on this topic with the help of the resources below:

--

--

Victor Bruce-Crabbe

[Available for Hire]. I share my learning experience through writing based on what I will want to read when learning a new concept to help others.