Setup jest from scratch in a vanilla js project.
Manuel Artero Anguita šØ
Posted on May 13, 2022
From time to time I see myself setting up a web project from scratch. Something super-easy if you use create-react-app
(if you're using React)... but not that smooth in vanilla.
ā”ļø This occasion we needed at work a vanilla js project.
A co-worker was setting up webpack and asked me to enable jest.
And I was like, "sure this should take 10 mins at most".
It took longer.
1. Install jest
First step is obv.
$ yarn add -D jest
...
"html-webpack-plugin": "^5.5.0",
+ "jest": "^28.0.3",
"postcss-loader": "^6.2.1",
...
2. Base Config
Next, call the jest CLI
tool which will create the base config:
$Ā» jest --init
The following questions will help Jest to create a suitable configuration for your project
ā Would you like to use Jest when running "test" script in "package.json"? ā¦ yes
ā Would you like to use Typescript for the configuration file? ā¦ no
ā Choose the test environment that will be used for testing āŗ jsdom (browser-like)
ā Do you want Jest to add coverage reports? ā¦ no
ā Which provider should be used to instrument code for coverage? āŗ babel
ā Automatically clear mock calls, instances and results before every test? ā¦ no
ā”ļø Note: Here we've taken one relevant decision. test environment is
jsdom
since we're building a web app, we want a browser-like environment.
[3]. Optional Step
We try to reduce dot-files-pollution at root folder. Basically, we gather every tool-related config file and move them to config/
.
$Ā» mv jest.config.js config/
This implies a subtle tuning at jest.config.js
...
- roots: ['src']
+ roots: ['../src'],
...
Plus considering the new path at package.json
...
- "test": "jest"
+ "test": "jest --config=config/jest.config.js"
...
4. Configure Jest
Jest runs over node. From the docs:
Jest runs the code of your project as JavaScript, hence a transformer is needed if you use some syntax not supported by Node out of the box.
Since we're playing with browser-things, we need babel-jest
.
$Ā» yarn add -D babel-jest @babel/preset-env @babel/core
...
+ "@babel/core": "^7.17.9",
+ "@babel/preset-env": "^7.16.11",
+ "babel-jest": "^28.0.3",
...
Plus these lines at jest.config.js
+ transform: {
+ '\\.[jt]sx?$': 'babel-jest',
+ },
And (if you didn't have one already) a brand new config/babel.config.json
{
"env": {
"test": {
"presets": [
"@babel/preset-env"
],
}
}
}
5. Try the thing with a real test
One of the things I hate the most from tutorials is that they use fake-hello-world examples.
Our real world test is:
import axios from 'axios';
import api from './api';
jest.mock('axios');
afterEach(() => {
jest.clearAllMocks();
});
test('getLayoutData() [200]', async () => {
axios.get.mockResolvedValue({ status: 200, data: { layout: 'hello world' } });
const id = 42
const layoutData = await api.getLayoutData(id, { someQueryParam: true });
expect(layoutData).toEqual({ layout: 'hello world' });
expect(axios.get).toHaveBeenCalledTimes(1);
expect(axios.get).toHaveBeenCalledWith('https://fake-url.api.test/v1/layouts/42', {
headers: {
'x-api-key': '==API KEY TEST==',
},
params: {
someQueryParam: true,
},
});
});
I bet you have one of those at your real world problems
6. ENV vars
Our code relies on two env vars; these two values: 'https://fake-url.api.test'
and '==API KEY TEST=='
.
Let's add those:
- At
config/jest.config.js
+setupFiles: ['./jest-env-vars.js']
config/jest-env-vars.js
process.env.API_URL = 'https://fake-url.api.test';
process.env.API_KEY = '==API KEY TEST==';
AND... It fails š¤
7. Enable async
await
Straight to the point what it's happening is that we need yet another babel plugin: @babel/plugin-transform-runtime
Enable the plugin at babel.config.js
{
"env": {
"test": {
"presets": [
"@babel/preset-env"
],
+ "plugins": [
+ "@babel/plugin-transform-runtime"
+ ]
}
}
}
8. Final touches š
At some point we'll rendering some component, and testing those you want the handy methods toBeInTheDocument()
, toBeVisible()
from Testing Library
$Ā» yarn add -D @testing-library/jest-dom
- At
config/jest.config.js
+ setupFilesAfterEnv: ['./setup-tests.js'],
config/setup-tests.js
import '@testing-library/jest-dom';
Summary
With just 7 dev-dependencies,
@babel/core
@babel/preset-env
@babel/plugin-transform-runtime
@testing-library/jest-dom
babel-jest
jest
jest-environment-jsdom
And just 4 config files,
- babel.config.json
- jest-env-vars.js
- jest.config.js
- setup-tests.js
we got $Ā» yarn test
working š
--
Cover image People illustrations by Storyset
Thanks for reading š.
Posted on May 13, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 25, 2023