React Testing Setup
September 6, 2020
Testing your code is like having a lifesaver, everyone should have one. Here, I'm going to set up an environment of safety, one that will you the confidence you need to ship your React code in the best shape possible.
Let's assume you already have your React project setup and all you want is add testing to it. I'm going to be using my own code to guide you on the process.
Here is the code I'm going to use through this guide:
// src/components/Counter/Counter.tsximport * as React from 'react'function Counter(): JSX.Element {const [count, setCount] = React.useState(0)return (<div><button aria-label="decrement" onClick={() => setCount(count - 1)} type="button">-</button><div>{count}</div><button aria-label="increment" onClick={() => setCount(count + 1)} type="button">+</button></div>)}export default Counter
Simple right? But let's forget about it for a second and focus on the important things.
🧰 Install the toolkit
My prefered choice is, jest as a test runner and @testing-library/react to test our React components.
Why? Because jest
works straight away along the most known javascript frameworks and libraries (zero config) and it has a simple and great API, that is very well known in the javascript world. And @testing-library/react
has this really great concept of not testing implementation details but just test your component as close as how a real user will interact with it.
I will also be using
typescript
for the example as it brings another layer of safety to our code.
So the final toolkit is:
- jest
- @testing-library/react
- typescript
But, I will need to install a few addons to make our testing environment work. So here is the final command:
npm install jest @testing-library/react typescript @types/jest @types/node ts-jest @testing-library/jest-dom --save-dev
⚙️ Configure the environment
Earlier, I said jest
was zero config. Well, if it wasn't because we were using typescript
, we wouldn't have to do a lot here, but I promise it is going to be simple.
The good thing is, we can configure jest
directly from the package.json
file!
Add these few lines to it:
{"jest": {"roots": ["<rootDir>/src"],"transform": {"^.+\\.tsx?$": "ts-jest"},"setupFilesAfterEnv": ["@testing-library/jest-dom/extend-expect"]}}
roots
is making surejest
knows where to look for our code (By default it's the root directory).transform
is tellingjest
how to make our code understandable (As we are using typescript and jest doesn't know about it).setupFilesAfterEnv
is running some code after the environment is prepared (In our case it will extend the defaultexpect
command from jest).
Then all you gotta do is make sure typescript
knows you are using React and JSX syntax.
How? Create a tsconfig.json
file and add the following:
{"compilerOptions": {"target": "es5","module": "commonjs","lib": ["es2015", "dom"],"sourceMap": true,"allowJs": true,"jsx": "react","strict": true,"strictFunctionTypes": true,"noImplicitReturns": true,"noImplicitThis": true,"noImplicitAny": true,"strictNullChecks": true,"alwaysStrict": true,"noUnusedLocals": true,"noUnusedParameters": true,"skipLibCheck": true,"esModuleInterop": true}}
This is an example of one of my projects. All these options might not match your perfect setup. Check the tsconfig docs for more information.
💨 Running the tests
Wait a sec! I don't have any tests!
By default, jest
will look for files matching the following naming conventions:
__tests__/Component.tsx
Component.test.tsx
Component.spect.tsx
So make sure you create one, I wrote this one:
// src/components/Counter/__tests__/Counter.test.tsximport * as React from 'react'import { render, screen } from '@testing-library/react'import Counter from '../Counter'test('Counter renders correctly', () => {render(<Counter />)expect(screen.getByText('0')).toBeInTheDocument()})
Now this seems to be ready, but we are missing one last step, creating a script to run jest
from our command line. To do this let's come back to our package.json
and add the following lines.
{"scripts": {"test": "jest","test:watch": "jest --watch"}}
Depending on how you want to run jest, you got choice:
- While writing some more code,
test:watch
will make sure your changes are picked up. - Or if for instance you want to run them after you've done all your changes,
test
will do so.
Let's run them and see if they pass:
npm run test
This should be the output you should be getting!
PASS src/components/Counter/__tests__/Counter.test.tsx✓ Counter renders correctly (26 ms)Test Suites: 1 passed, 1 totalTests: 1 passed, 1 totalSnapshots: 0 totalTime: 1.179 s, estimated 3 sRan all test suites.
🔗 All together
If you want to sense it all together, here is the project that I set up while writing this guide.