We run the Playwright test suite on each PR to test that the front end works correctly and there are no visual regressions.
The end-to-end tests make sure that functionality works as expected and are
located in test/playwright/e2e
. They test, for instance, that we can open the
filters by clicking on the Filters button in the header, or select the filters
and execute the relevant search by clicking on the filter checkboxes.
There are also visual regression tests that make sure that the pages display
correct components, and components are rendered correctly. The components can be
tested in isolation to make sure that the states are correctly rendered. For
more on which states should be tested, see
TESTING_GUIDELINES.md
. These tests should use
Storybook to render the component in isolation, and be placed in
test/storybook/visual-regression
.
The component tests that test that the component state is correctly rendered
based on the page interaction should be placed in
test/visual-regression/components
. For example, the header elements are tested
this way because their appearance depends on the page scroll position.
Our Playwright test suite runs inside a docker container in order to prevent cross-platform browser differences from creating flaky test behavior. We run both end-to-end and visual-regression tests in the same container to save from having to run the Nuxt production build twice.
Having docker and docker-compose is a pre-requisite to running the playwright tests locally. Please follow the relevant instructions for your operating system for how to install docker and docker-compose. If you're on Windows 10 Home Edition, please note that you'll need to install and run docker inside WSL2. We strongly recommend (and only plan to support) Windows users run everything inside of WSL.
If it's not possible for you to run docker locally, don't fret! Our CI will run it on every pull request and another contributor who is able to run the tests locally can help you develop new or update existing tests for your changes.
The Playwright docker container runs everything needed for the end-to-end and visual-regression tests, including the Nuxt server and a Talkback proxy for the API. It will also generate and match against the existing visual-regression snapshots in the codebase.
To run the end-to-end tests, after having installed docker, run the following:
pnpm test:playwright
You may pass arguments to playwright directly, for example -u
to update
snapshots or a filter.
pnpm test:playwright visual-regression -u
The above will run only test files with visual-regression
in the path and will
update any snapshot tests due to the -u
flag.
When writing visual regression tests, it is good practice to write tests for
each relevant breakpoint. There is a series of helpers in
./utils/breakpoints.ts
for this. The most common
usage for this module is to run a test or set of tests for every breakpoint our
app knows about or a subset of them. Occasionally you will need to separate
tests by breakpoint or by range for which there are also helpers.
Each of the following methods expects a describe block callback function accepting some useful helpers.
breakpoints.describeEvery
: Generates a describe block for every breakpoint our app is concerned with.breakpoints.describeEachDesktop
: Generates a describe block for every breakpoint that roughly correlates with desktop and tablet width devices.breakpoints.describeEachMobile
: Generates a describe block for every breakpoint that roughly correlates with smartphone sized mobile devices.breakpoints.describeEachBreakpoint
: Accepts a list of breakpoints to generate describe blocks for, with similar syntax tojest
'stest.each
helper. Used likebreakpoints.describeEachBreakpoint(['xs', '2xl'])(<block>)
.describeEvery
and the twodescribeEach*
methods are aliases for pre-configureddescribeEachBreakpoint
. It is unlikely that you will need to use this helper directly.
Additionally there are describe blocks for individual breakpoints, each
following the pattern `describe${Capitalize<Breakpoint>}`
, for example
breakpoints.describeXs
.
The describe blocks are passed the following helpers:
breakpoint
: The name of the breakpoint for the current describe block.getConfigValues
: Returns useful configuration values if running a snapshot test manually.expectSnapshot
: A function accepting an identifier and a screenshot-able object. This will generate the screenshot and match it against a snapshot matching the name passed. Remember toawait
this function or else theexpect
will not be fired within the context of the test (you'll get a nasty error in this case).
Optionally, you may pass a configuration object as the first argument to the
breakpoints.describe*
functions. If you do this, then the describe block is
the second argument.
The configuration object currently supports the following options:
uaMocking
: Thisboolean
option defaults totrue
. When enabled, it will use a mock mobile browser user agent string for narrow viewports. Setting it tofalse
for viewport widths abovemd
(inclusive) is a no-op.
Please see the
homepage.spec.ts
visual-regression tests
as an example of how to use these helpers.
Visual regression tests can match entire pages or on individual elements in
specific states. They're useful, for example, to test the various focus, hover,
and active states of interactive elements. Use
page.locator
to
select specific elements to pass to expectSnapshot
.
The Playwright test container also runs an API proxy using Talkback to prevent network requests from hitting the live API during end-to-end and visual-regression tests. This significantly speeds up the tests and makes the data being tested against consistent across test runs and eliminates variations that the API may include after data refreshes happen.
The configuration for the Talkback proxy is in the proxy.js
module and is run using pnpm talkback
. It is rare and unlikely that you will
need to run it directly as running it is handled by the Playwright webServer
configuration.
If you've added new tests or updated existing ones, you may get errors about API responses not being found. To remedy this, you'll need to update the tapes:
pnpm test:playwright:update-tapes
If for some reason you find yourself needing to completely recreate the tapes,
you may do so using the test:playwright:recreate-tapes
script. Please use this
sparingly as it creates massive diffs in PRs (tens of thousands of lines across
over literally hundreds of JSON files). Note that you may be rate-limited by the
upstream production API if you do this. There is no official workaround for this
at the moment.
Additional debugging may be accomplished in two ways. You may inspect the trace
output of failed tests by finding the trace.zip
for the relevant test in the
test-results
folder. Traces are only saved for failed tests. You can use the
Playwright Trace Viewer to inspect
these (or open the zip yourself and poke around the files on your own).
For Playwright tests failing in CI, a GitHub comment will appear with a link to
download an artifact of the test-results
folder.
Visual regression tests that fail to match the existing snapshots will also have
expected
, actual
and diff
files generated that are helpful for
understanding why intermittent failures are happening. These are generated
automatically by Playwright and will be placed in the test-results
folder
under the fully qualified name of the test that failed (with every parent
describe block included).
Additionally, you can run run the tests in debug mode. This will run the tests with a headed browser as opposed to a headless (invisible) one and allow you to watch the test happen in real time. It's not possible for a headed browser to run inside the docker container, however, so be aware that when debugging the environment will be slightly different. For example, if you're on any OS other than Linux, the browser you're running will have small differences in how it renders the page compared to the docker container.
To run the debug tests:
pnpm test:playwright:debug
Note that this still runs the talkback proxy and the Nuxt server for you. If
you'd like to avoid this, simply run the Nuxt server before you run the
test:playwright:debug
script and Playwright will automatically prefer your
previously running Nuxt server.
search-types.spec.js:102:3 › Can open All content page client-side
search-types.spec.js:102:3 › Can open Images page client-side
Don't be alarmed if you notice this.
When writing end-to-end tests, it can be helpful to use Playwright codegen to generate the tests by performing actions in the browser:
pnpm run test:playwright:gen
This will open the app in a new browser window, and record any actions you take in a format that can be used in end-to-end tests.
Note that this does not run the server for you; you must run the Nuxt server
using pnpm start
or pnpm dev
separately before running the codegen script.
To generate tests for a non-default breakpoint, set the viewport size using the
--viewport-size
flag. For example, to test the xs
breakpoint, run:
pnpm run test:playwright:gen --viewport-size=340,600"