Visual testing and unit testing both permit small-scale observation of how quality changes over time across individual Gatsby components and pages. However, there are often situations where, as a Gatsby developer, it will be desirable to perform end-to-end (e2e) testing that involves not only single pages and components but navigating through an entire Gatsby site with multiple pages and components involved in one test.
This is particularly important for accessibility testing when it comes to accessible client-side routing, as an e2e test can reveal when navigating between pages isn’t working properly due to a missing Reach route change or other issue. Though there are multiple systems commonly used for e2e testing, Cypress is a common choice.
Because e2e testing typically requires a second parallel server to be running alongside Gatsby’s local development server, you’ll want to use the start-server-and-test
library to manage both in parallel. Add the following to your development dependencies (devDependencies
):
$
npm
install
--save-dev
cypress
start-server-and-test
\
@testing-library/cypress
Cypress comes with the ability to configure certain global settings. Do that now by creating a new cypress.json file in your project root:
//
cypress.json
{
"baseUrl":
}
This baseUrl
configuration will ensure that every URL that Cypress visits or issues a request to will be prefixed with the correct domain for our Gatsby development server. Next, you need to add Cypress scripts to our package.json to ensure you can run Cypress tests from the terminal:
//
package.json
{
"scripts":
{
"develop":
"gatsby develop",
"test:jest":
"jest",
"cy:open":
"cypress open",
"test:e2e":
}
}
If you’re using Cypress in the context of a CI provider like CircleCI or Travis, you will need to use the cypress run
command instead of cypress open
:
"cy:run"
:
"cypress run"
,
To kick off a Cypress test, execute the following after installing other dependencies required for Cypress:
$
npm
run
test
:e2e
NOTE
To distinguish between Jest unit tests and end-to-end Cypress tests, you may want to consider changing the npm run test
command to npm run test:jest
. This will avoid any possible confusion with an npm run test:e2e
command for Cypress.
You’ll see a new directory named cypress created within the root of your project.
WARNING
If you’re running your Gatsby development server with HTTPS enabled (i.e., gatsby develop --https
), you will need to indicate to start-server-and-test
that it needs to disable SSL certificate checks, because these will cause Cypress to hang. In your package.json, your test:e2e
command should be changed to the following to include an environment variable that disables certificate checks:
"test:e2e":
"START_SERVER_AND_TEST_INSECURE=1
start-server-and-test develop
One of the most common use cases for end-to-end testing with Cypress is accessibility testing, which requires a library such as Axe. Though building in automated accessibility testing is a best practice for Gatsby sites, it’s also a best practice to perform at least some manual accessibility testing lest something fall through the cracks.
You can install those additional Axe dependencies now:
$
npm
install
--save-dev
cypress-axe
axe-core
Because you already ran Cypress once, you can open the already created cypress/support/index.js file and import the additional dependencies you now need, including @testing-library/cypress
:
// cypress/support/index.js
import
"./commands"
import
"cypress-axe"
import
"@testing-library/cypress/add-commands"
Though Cypress will look for tests within the cypress/integration directory by default, accessibility tests that visit multiple pages are considered end-to-end tests and should be placed in a new cypress/e2e directory as a best practice. In this case, you’ll need to configure an integrationFolder
in your Cypress configuration as follows:
//
cypress.json
{
"baseUrl"
:
"http://localhost:8000/"
,
"integrationFolder"
:
"cypress/e2e"
}
To finish our exploration of Cypress end-to-end testing, let’s create a rudimentary test that checks for the absence of accessibility violations on the initial load of the home page of our example Gatsby site, which in this section is our Gatsby blog starter. Create a new file in the cypress/e2e directory named accessibility.test.js with the following contents:
// cypress/e2e/accessibility.test.js
/// <reference types="Cypress" />
describe("Accessibility tests", () => {
beforeEach(() => {
cy.visit("/").get("main").injectAxe()
})
it("Has no detectable accessibility violations on load", () => {
cy.checkA11y()
})
it("Navigates to blog post and checks for accessibility violations", () => {
cy.findByText(/new beginnings/i)
.click()
.checkA11y()
})
})
This comment facilitates autocompletion if you’re using certain IDEs (such as those with IntelliSense).
As the cy.visit()
method suggests, Cypress visits the home page of your Gatsby site and waits until the page load is complete. The subsequent chained methods find the <main>
HTML element (using cy.get()
, as Gatsby may “finish” loading too quickly), where the Axe accessibility testing API is injected and made available.
The cy.checkA11y()
method performs a check for any accessibility errors on the home page.
The cy.findByText()
method finds the first blog post displayed in the Gatsby blog starter and navigates to it, performing another check for accessibility errors on that page.
You can extend this end-to-end accessibility test by working through some additional assertions using the should
method to check whether a given link has text legible to screen readers and has an href
attribute, as is expected of all links:
// cypress/e2e/accessibility.test.js
describe
(
"Accessibility tests"
,
()
=>
{
// Previous assertions.
it
(
"Focuses on the header link and asserts its attributes"
,
()
=>
{
cy
.
findAllByText
(
"Gatsby Starter Blog"
).
focus
()
cy
.
focused
()
.
should
(
"have.text"
,
"Gatsby Starter Blog"
)
.
should
(
"have.attr"
,
"href"
,
"/"
)
})
})
NOTE
A full examination of Cypress and Axe is beyond the scope of this brief introduction to end-to-end testing, but Cypress offers a getting started guide, core concepts page, and API reference. In addition, Gatsby provides a Cypress example and a guide to customizing Axe options. For more information about Axe, see the Axe documentation.
Leave a Reply