From 562ddd2e12ffe21e1ce6ce19f74595988c308234 Mon Sep 17 00:00:00 2001 From: "Martin H. Normark" Date: Fri, 30 Dec 2022 16:00:13 +0100 Subject: [PATCH] Describe how to use Cypress --- website/README.md | 15 ++++++++++ website/cypress/README.md | 62 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 website/cypress/README.md diff --git a/website/README.md b/website/README.md index ffbc4b64..f70dcfce 100644 --- a/website/README.md +++ b/website/README.md @@ -102,6 +102,21 @@ All static images, fonts, svgs, etc are stored in `public/`. We're not really using CSS styles. `styles/` can be ignored. +## Testing the UI + +Cypress is used for end-to-end (e2e) and component testing and is configured in `./cypress.config.ts`. The `./cypress` folder is used for supporting configuration files etc. + +- Store e2e tests in the `./cypress/e2e` folder. +- Store component tests adjacent to the component being tested. If you want to wriite a test for `./src/components/Layout.tsx` then store the test file at `./src/components/Layout.cy.tsx`. + +A few npm scripts are available for convenience: + +- `npm run cypress`: Useful for development, it opens Cypress and allows you to explore, run and debug tests. It assumes you have the NextJS site running at `localhost:3000`. +- `npm run cypress:run`: Runs all tests. Useful for a quick sanity check before sending a PR or to run in CI pipelines. +- `npm run cypress:image-baseline`: If you have tests failing because of visual changes that was expected, this command will update the baseline images stored in `./cypress-visual-screenshots/baseline` with those from the adjacent comparison folder. More can be found in the [docs of `uktrade/cypress-image-diff`](https://github.com/uktrade/cypress-image-diff/blob/main/docs/CLI.md#update-all-baseline-images-for-failing-tests). + +Read more in the [./cypress README](cypress/). + ## Best Practices When writing code for the website, we have a few best practices: diff --git a/website/cypress/README.md b/website/cypress/README.md new file mode 100644 index 00000000..12a32378 --- /dev/null +++ b/website/cypress/README.md @@ -0,0 +1,62 @@ +# Component and e2e testing with Cypress + +[Cypress](https://www.cypress.io/) is used for both component- and end-to-end testing. Below there's a few examples for the context of this site. To learn more, the [Cypress documentation](https://docs.cypress.io/guides/getting-started/opening-the-app) has it all. + +Don't get scared by the commercial offerings they offer. Their core is open source, the cloud offering is not necesarry at all and can be replaced by CI tooling and [community efforts](https://sorry-cypress.dev/). + +# Component testing + +To write a new component test, you either create a new `.tsx` adjacent to the component you want to test or you can use the guide presented yo you when running `npm run cypress` which allows you to easily create the skeleton test for an existing component. + +If you have a `Button.tsx` component, create a file next to it called `Button.cy.tsx` which could look like this: + +```typescript +import React from "react"; +import { Button } from "./Button"; + +describe("); + cy.get("button").compareSnapshot("button-element"); + }); +}); +``` + +## What's happening here? + +First we use `cy.mount` to mount our component under test. Notive how we specify `className` and inner text - this is where we arrange our component with fake data that we could assert on later. + +In the example above, we also use `cy.get` to select the rendered `button` element. Cypress has multiple ways to [select elements](https://docs.cypress.io/guides/references/best-practices), `get` is just one of them (and often not recommended). + +At last, we use `captureSnapshot` which is a plugin that snaps a photo of the `button` element and compares it to a baseline located in the `./cypress-visual-screenshots/baseline/` folder. If there's too many unidentical pixels between the two, it will fail the test. + +# End-to-end (e2e) testing + +e2e tests are stored in the `./cypress/e2e` folder and should be named `{page}.cy.ts` and located in a relative folder structure that mirrors the page under test. + +When running `npm run cypress` and selecting e2e testing, we assume you have the NextJS site running at `localhost:3000`. + +An example test from this time of writing, could look as follows: + +```typescript +describe("signin flow", () => { + it("redirects to a confirmation page on submit of valid email address", () => { + cy.visit("/auth/signin"); + cy.get(".chakra-input").type(`test@example.com{enter}`); + cy.url().should("contain", "/auth/verify"); + }); +}); + +export {}; +``` + +## What's happening here? + +First we use [`cy.visit`](https://docs.cypress.io/api/commands/visit) to point the browser at the desired page. It appends relative paths to the configured `baseUrl` (found in `./cypress.config.ts`). + +Cypress will [automatically await](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#Timeouts) almost anything you do, but fail if the default timeout is reached. + +Then we get the email input field and type our email address. Notice the `{enter}` keyword, this will cause Cypress to hit the return key which we expect to submit the form. + +We then assert that the URL should contain `/auth/verify`. Again the timeout will make sure we are not waiting forever, and the test will fail if we do not manage to get there in a reasonable time.