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
typescriptfor 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"]}}
rootsis making surejestknows where to look for our code (By default it's the root directory).transformis tellingjesthow to make our code understandable (As we are using typescript and jest doesn't know about it).setupFilesAfterEnvis running some code after the environment is prepared (In our case it will extend the defaultexpectcommand 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.tsxComponent.test.tsxComponent.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:watchwill make sure your changes are picked up. - Or if for instance you want to run them after you've done all your changes,
testwill 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.
