Skip to content

Commit 32be1dc

Browse files
LekoArtscalcsam
authored andcommitted
Add Docs about Cypress, react-testing-library and testing of CSS-in-JS (#6708)
* Add Docs about Cypress, react-testing-library and testing of CSS-in-JS * Small fixes * Update link * Minor edits * Change titles * Edits * Address Shannon's comments
1 parent 16bf528 commit 32be1dc

File tree

3 files changed

+251
-0
lines changed

3 files changed

+251
-0
lines changed

docs/docs/end-to-end-testing.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
title: "End-to-end testing"
3+
---
4+
5+
[Cypress](https://www.cypress.io/) is one of the options when it comes to end-to-end (E2E) testing. Cypress is a all-in-one testing framework focused on E2E testing meaning that you don't have to install 10 different things to get your test suite set up. You can write your first passing test in minutes without any configuration with the help of Cypress' API which is easy to read and understand. It runs tests as fast as your browser can render content which also makes test-driven development possible. You'll also profit from the time travel feature or the extensive debugging capabilities with Chrome DevTools. Of course you can also use it with Gatsby and this guide will explain how.
6+
7+
In order to run Gatsby's development server and Cypress at the same time you'll use the little helper [start-server-and-test](https://github.com/bahmutov/start-server-and-test). If you're already using [react-testing-library](docs/testing-react-components) for [unit testing](docs/unit-testing) you might want to install [cypress-testing-library](https://github.com/kentcdodds/cypress-testing-library), too. This way you can use the exact same methods you used with `react-testing-library` in your Cypress tests. Install the following packages to your `devDependencies`:
8+
9+
```sh
10+
npm install --save-dev cypress start-server-and-test
11+
```
12+
13+
We also want the urls used by `cy.visit()` or `cy.request()` to be prefixed hence you have to create the file `cypress.json` at the root of your project with the following content:
14+
15+
```json
16+
{
17+
"baseUrl": "http://localhost:8000/"
18+
}
19+
```
20+
21+
Last but not least you add additional scripts to your `package.json` to run Cypress:
22+
23+
```json
24+
{
25+
"scripts": {
26+
"develop": "gatsby develop",
27+
"cy:open": "cypress open",
28+
"test:e2e": "start-server-and-test develop http://localhost:8000 cy:open"
29+
}
30+
}
31+
```
32+
33+
Run `test:e2e` in your command line and see Cypress running for the first time. A folder named `cypress` will be created at the root of your project and a new application window will pop up. [Cypress' getting started guide](https://docs.cypress.io/guides/getting-started/writing-your-first-test.html#) is a good start to learn how to write tests!
34+
35+
### Continuous Integration
36+
37+
If you want to run Cypress in Continuous Integration (CI) you have to use `cypress run` instead of `cypress open`:
38+
39+
```json
40+
{
41+
"scripts": {
42+
"develop": "gatsby develop",
43+
"cy:open": "cypress open",
44+
"cy:run": "cypress run",
45+
"test:e2e:ci": "start-server-and-test develop http://localhost:8000 cy:run"
46+
}
47+
}
48+
```
49+
50+
Please read the [Cypress' official documentation](https://docs.cypress.io/guides/guides/continuous-integration.html) on CI if you want to know how to setup Travis or Gitlab with Cypress.

docs/docs/testing-css-in-js.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
---
2+
title: "Testing CSS-in-JS"
3+
---
4+
5+
Popular CSS-in-JS libraries like [styled-components](https://github.com/styled-components/styled-components) or [emotion](https://github.com/emotion-js/emotion) can also be tested with the help of [jest-styled-components](https://github.com/styled-components/jest-styled-components) or [jest-emotion](https://github.com/emotion-js/emotion/tree/master/packages/jest-emotion) respectively. These packages improve Jest's built-in snapshot testing experience and are a great way to help avoid unintended changes to your website's UI. Please refer to your package's documentation to see if it also offers testing capabilities.
6+
7+
*Snapshot serializers* like `jest-styled-components` or `jest-emotion` modify the standard output to a more meaningful and readable snapshot, e.g. by removing unnecessary information or displaying data in another format. Which ultimately leads to more compareable and effective snapshot tests.
8+
9+
By default snapshots of your styled components show the generated class names (which you didn't set) and no styling information. When changing the styles you'll only see the diff of some cryptic class names (hashes). That's why you should use the above mentioned *snapshot serializers*. They remove the hashes and format the CSS in style elements.
10+
11+
For this example we'll use emotion. The testing utilities of emotion and glamor are largely based on [jest-styled-components](https://github.com/styled-components/jest-styled-components) so they have a similar usage. Please have a look at the testing section of your library to follow along.
12+
13+
## Installation
14+
15+
```sh
16+
npm install --save-dev jest-emotion babel-plugin-emotion
17+
```
18+
19+
As [Gatsby's emotion plugin](https://www.gatsbyjs.org/packages/gatsby-plugin-emotion/) is using `babel-plugin-emotion` under the hood you'll also need to install it so that Jest can use it.
20+
21+
If you followed along with the [Unit testing guide](docs/unit-testing) you'll have the file `jest-preprocess.js` at the root of your project. Open that file and add the plugin:
22+
23+
```diff
24+
const babelOptions = {
25+
presets: ["@babel/react", "@babel/env"],
26+
plugins: [
27+
+ "emotion",
28+
"@babel/plugin-proposal-optional-chaining",
29+
"@babel/plugin-proposal-class-properties",
30+
],
31+
}
32+
33+
module.exports = require("babel-jest").createTransformer(babelOptions)
34+
```
35+
36+
In order to tell Jest to use the serializer you'll need to create the file `setup-test-env.js` which will be run automatically before every test. Create the file `setup-test-env.js` at the root of your project. Insert this code into it:
37+
38+
```js
39+
import { createSerializer } from 'jest-emotion';
40+
import * as emotion from 'emotion';
41+
42+
expect.addSnapshotSerializer(createSerializer(emotion));
43+
```
44+
45+
Lastly you need to tell Jest where to find this file. Open your `package.json` and add this entry to your `"jest"` section:
46+
47+
```json
48+
"jest": {
49+
"setupTestFrameworkScriptFile": "<rootDir>/setup-test-env.js"
50+
}
51+
```
52+
53+
## Usage
54+
55+
In this example you'll use `react-test-renderer` but you can also use [react-testing-library](docs/testing-react-components) or any other appropriate library. Because you created the `setup-test-env.js` file you can write your unit tests like you used to do. But now you'll also get the styling information!
56+
57+
```js
58+
// src/components/Button.test.js
59+
60+
import React from 'react'
61+
import styled from 'react-emotion'
62+
import renderer from 'react-test-renderer'
63+
64+
const Button = styled.div`
65+
color: hotpink;
66+
`
67+
68+
test('Button renders correctly', () => {
69+
expect(
70+
renderer.create(<Button>This is hotpink.</Button>).toJSON()
71+
).toMatchSnapshot()
72+
})
73+
```
74+
75+
The resulting snapshot will look like this:
76+
77+
```js
78+
// Jest Snapshot v1, https://goo.gl/fbAQLP
79+
80+
exports[`Button renders correctly 1`] = `
81+
.emotion-0 {
82+
color: hotpink;
83+
}
84+
85+
<div
86+
className="emotion-0 emotion-1"
87+
>
88+
This is hotpink.
89+
</div>
90+
`;
91+
```
92+
93+
If your styled component depends on `theme` via `ThemeProvider` you'll have two options:
94+
95+
- Wrap all your components with the `ThemeProvider`
96+
- Use API helpers (have a look at the library's documentation, e.g. [styled-components](https://github.com/styled-components/jest-styled-components#theming) or [emotion](https://github.com/emotion-js/emotion/tree/master/packages/emotion-theming#createbroadcast-function))
97+
98+
And this is where snapshots tests really shine. If you change, e.g. the primary color in your theme file you'll see which components get affected by this change. This way you can catch unintended changes to the style of your components.
99+
100+
This example uses the first option:
101+
102+
```js
103+
// src/components/Wrapper.test.js
104+
105+
import React from 'react'
106+
import { ThemeProvider } from 'emotion-theming'
107+
import renderer from 'react-test-renderer'
108+
109+
const theme = {
110+
maxWidth: '1450px',
111+
}
112+
113+
const Wrapper = styled.section`
114+
max-width: ${props => props.theme.maxWidth};
115+
`
116+
117+
test('Wrapper renders correctly', () => {
118+
expect(
119+
renderer.create(
120+
<ThemeProvider theme={theme}>
121+
<Wrapper>Content.</Wrapper>
122+
</ThemeProvider>
123+
).toJSON()
124+
).toMatchSnapshot()
125+
})
126+
```
127+
128+
The resulting snapshot will look like this:
129+
130+
```js
131+
// Jest Snapshot v1, https://goo.gl/fbAQLP
132+
133+
exports[`Wrapper renders correctly 1`] = `
134+
.emotion-0 {
135+
max-width: 1450px;
136+
}
137+
138+
<section
139+
className="emotion-0 emotion-1"
140+
>
141+
Content
142+
</div>
143+
`;
144+
```
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: "Testing React components"
3+
---
4+
5+
_The recommended testing framework is [Jest](https://jestjs.io/). This guide assumes that you followed the [Unit testing](docs/unit-testing) guide to setup Jest._
6+
7+
Kent C. Dodds' [react-testing-library](https://github.com/kentcdodds/react-testing-library) has risen in popularity since its release and is a great replacement for [enzyme](https://github.com/airbnb/enzyme). You can write unit and integration tests and it encourages you to query the DOM in the same way the user would. Hence the guiding principle:
8+
9+
> The more your tests resemble the way your software is used, the more confidence they can give you.
10+
11+
It provides light utility functions on top of `react-dom` and `react-dom/test-utils` and gives you the confidence that refactors of your component in regards to the implementation (but not functionality) don't break your tests.
12+
13+
## Installation
14+
15+
Install the library as one of your project's `devDependencies`. Optionally you may install `jest-dom` to use its [custom jest matchers](https://github.com/gnapse/jest-dom#custom-matchers).
16+
17+
```sh
18+
npm install --save-dev react-testing-library jest-dom
19+
```
20+
21+
Create the file `setup-test-env.js` at the root of your project. Insert this code into it:
22+
23+
```js
24+
import 'jest-dom/extend-expect';
25+
26+
// this is basically: afterEach(cleanup)
27+
import 'react-testing-library/cleanup-after-each';
28+
```
29+
30+
This file gets run automatically by Jest before every test and therefore you don't need to add the imports to every single test file.
31+
32+
Lastly you need to tell Jest where to find this file. Open your `package.json` and add this entry to your `"jest"` section:
33+
34+
```json
35+
"jest": {
36+
"setupTestFrameworkScriptFile": "<rootDir>/setup-test-env.js"
37+
}
38+
```
39+
40+
## Usage
41+
42+
Let's create a little example test using the newly added library. If you haven't done already read the [unit testing guide](docs/unit-testing) — essentially you'll use `react-testing-library` instead of `react-test-renderer` now. There are a lot of options when it comes to selectors, this example chooses `getByTestId` here. It also utilizes `toHaveTextContent` from `jest-dom`:
43+
44+
```js
45+
import React from 'react'
46+
import { render } from 'react-testing-library'
47+
48+
// You have to write data-testid
49+
const Title = () => <h1 data-testid="hero-title">Gatsby is awesome!</h1>
50+
51+
test('Displays the correct title', () => {
52+
const { getByTestId } = render(<Title />)
53+
// Assertion
54+
expect(getByTestId('hero-title')).toHaveTextContent('Gatsby is awesome!')
55+
// --> Test will pass
56+
})
57+
```

0 commit comments

Comments
 (0)