Javascript React
Where Am I: URL Assertions with Cypress
The URL that appears in the browser's URL bar is one of the first and primary ways that users interact with our web apps. The URL tells the app and the user of their location within the route hierarchy of the app. It sometimes even contains state. The URL consequently serves as an excellent first assertion when writing integration tests.
When writing Cypress integration tests, there are several ways for us to assert about the current URL.
The cy.url()
and
cy.location()
functions are the primary ways for us to gain access to information about
the current state of the URL. From there, we can perform a variety of
assertions.
We can assert about the entire URL:
// URL: http://localhost:8000/pokemon
cy.url().should('eq', 'http://localhost:8000/pokemon');
// ✅ passes
This is certain the most precise assertion. The tradeoff is that it requires
us to know something about the environment configuration (namely,
baseUrl
). This can get verbose and make our tests brittle.
Alternatively, we can make a partial assertion about the URL:
// URL: http://localhost:8000/pokemon
cy.url().should('contain', '/pokemon');
// ✅ passes
This frees us from having to specify the full path with the base URL. This, too, has a potential drawback. This way of asserting about the URL can be overly permissive and may result in a false-positive.
Imagine we are writing a test for our pokemon show page. As part of that
test we want to be sure that the back button works. We are on the show
page for a specific pokemon (/pokemon/2
) and our back button is not
correctly wired up yet. Here is our assertion:
// Click: 'Back' -- no change in URL
// URL: http://localhost:8000/pokemon/2
cy.url().should('contain', '/pokemon');
// ✅ passes (false positive)
What we'd like is a stricter assertion without the need to specify the base
URL. This is where cy.location()
can help.
// Click: 'Back' -- no change in URL
// URL: http://localhost:8000/pokemon/2
cy.location('pathname').should('eq', '/pokemon');
// ❌ fails
This time our assertion correctly fails because /pokemon
does not match
the current pathname of /pokemon/2
. Once we update our application code
with a working back button we should see this test pass. Going forward we
will have the confidence that if the back button breaks again, so will the
test.
We looked at a couple ways to assert about the current state of your app's
URL. Though cy.url()
can certainly be used to this end, I recommend
utilizing cy.location()
. There is a lot more to cy.location()
than we
covered in this post. Check out the
examples in
the Cypress docs for all the other ways this function can be used to assert
about the URL.
Want to see more of the code? Check out the supplementary repository.
Cover photo credit: Jean-Frederic Fortier