As you might know, I have been diving into setting up a boilerplate for a TypeScript project with React. And what good is a project without a unit testing framework? So I will go through the process of setting up Jest with TypeScript and Babel in this post.
If you are curious about my project setup, you can read about how I setup TypeScript with Babel and my ESLint for TypeScript setup.
For people unfamiliar with Jest, it is a JavaScript testing framework which comes in with a lot of built-in capabilities such as mocking, assertion, snapshot testing etc. It works out of the box for JavaScript projects but since we are using TypeScript, we need to do some configurations, though it is not a lot.
Installing Jest
To install Jest, all you need to do is run npm install jest
yarn add jest
You should also add the corresponding types (@types/jest) for it since those will come in handy. You will also need to react-test-renderer
Modifying your Babel configuration for Jest
In the Babel configuration, we set the modules property to false in our .babelrc file (for our Babel preset env). We did this because we were relying on Webpack to find out which imports are being used, transpile them and create the output bundle. We do not transpile the import statements using Babel because we want Webpack to be able to do tree shaking and eliminate dead code.
But Jest does not understand the module syntax and it does not know what to do. So, for Jest to understand what is going on, we will convert the modules to
module.exports = api => {
// Testing if babel is being run in test mode
const isTest = api.env('test');
/**
* Cache the returned value forever and don't call this function again. This is the default behavior but since we
* are reading the env value above, we need to explicitly set it after we are done doing that, else we get a
* caching was left unconfigured error.
*/
api.cache(true);
return {
presets: [
// For transformation of JSX and other react related bable plugins
'@babel/preset-react',
// Enabling Babel to understand TypeSFcript
'@babel/preset-typescript',
[
// Allows smart transpilation according to target environments
'@babel/preset-env',
{
// Specifying which browser versions you want to transpile down to
targets: {
browsers: ['last 2 versions'],
},
/**
* Specifying what module type should the output be in.
* For test cases, we transpile all the way down to commonjs since jest does not understand TypeScript.
* For all other cases, we don't transform since we want Webpack to do that in order for it to do
* dead code elimination (tree shaking) and intelligently select what all to add to the bundle.
*/
modules: isTest ? 'commonjs' : false,
},
],
],
};
};
JavaScriptWhat is happening above is that we are reading the environment variable to check if the current mode
This sets up Babel for us, and all we are left with is writing the test cases and executing them.
Writing a test case
Jest by default looks for test files with any of the popular naming conventions, that is files with:
- .js suffix in __tests__ folders
- .test.js suffix
- .spec.js suffix
I prefer having the files next to the code that they are written with so that the imports at the top are shorter (since they are in the same folder). Colocation is also useful for larger projects.
A basic Jest test case looks like this:
import React from 'react';
import TestRenderer from 'react-test-renderer';
import App from './App';
it('renders without crashing', () => {
TestRenderer.create(<App />);
});
JavaScriptWe are simply importing the required packages and files, setting expectations and hoping that it does not crash. You can add assertions using expect
For running the test cases, all you need to do is run the jest command from the terminal. You can add a build script as "test": "jest"
in your npm run test
or yarn test
.
Creating coverage reports using Jest
Jest has built-in support for creating coverage reports for your test cases. All you need to do is pass the –coverage param while running Jest to get the report. This will create a report in the coverage/
It is worth noting that coverage mode adds additional code collection metrics to the statements, so it does slow down the execution of the test cases.
And this is all you need to know about configuring Jest to work in your Typescript project with Babel and Webpack. I have the final output as a repository here which you might want to refer if you get stuck. It contains all the source code for configuring everything and I try to keep it updated.
If you have any questions, feel free to drop them in the comments section below.