How to setup unit tests with Create React App, Mocha and Visual Studio Code Mocha side-bar
Create React App is a great tool, it helped me to get the grips with the creation of my first app, understanding how the different elements of a React app (source code, node_modules, scripts) work and interact together.
Lately I have joined a team of external developers for which I design some features of existing React applications. They don’t use Create React App to and rely on Mocha as their test engine. Create React App comes with Jest, besides the scripts and the configuration to start unit testing your application right away.
Since I was curious to try Mocha but did not want to eject (un-link the app to its CRA environment) I researched a method to change only the test engine; maintaining the test libraries I normally use for components and assertions, in my case Enzyme, Chai and Chai-Enzyme.
I will now share with you the steps it took me to get Mocha to work in my application. In this example we will create a new React app with Create React Application but the process is the same for an existing app (just skip part 1) We will also integrate our tests into Visual Studio Code, installing and configuring the Mocha sidebar extension, enabling test running and debugging from the IDE. The example is based on Node 10.3.0 and React 16.6.3.
There is repository on GitHub, where you can download or clone the finished example.
- We create our react app with Create React App
npx create-react-app test-mocha
2. Install Mocha as a dev dependency, the test engine
yarn add mocha --dev
or npm install mocha --save-dev
3. Install Chai-Enzyme
This library packs Chai assertions and specific functions to test React components, it depends on Enzyme, Chai, the Enzyme React Adapter (which is dependent on React version) and Cheerio. The latter is a dependency of Enzyme and most probably already installed with it.
yarn add chai chai-enzyme enzyme enzyme-adapter-react-16 cheerio --dev
or npm install chai chai-enzyme enzyme enzyme-adapter-react-16 cheerio --save-dev
4. Install Babel (Core and Babel Register), Commonjs babel plugin and React app babel preset
We install Babel so that we will be able to compile our jsx code at test runtime, using the test script in the package.json file, bypassing react-scripts. Babel will be invoked by Babel Register by the — required
hook we will use later at script launching.
yarn add @babel/core @babel/register --dev
or npm install @babel/core @babel/register — save-dev
For having Babel compile our jsx code into JavaScript and use ES6/ES2015 features we will have to install the Babel CommonJS plugin and the babel-preset-react-app-babel-7.
yarn add babel-preset-react-app-babel-7 @babel/plugin-transform-modules-commonjs --dev
or npm install babel-preset-react-app-babel-7 @babel/plugin-transform-modules-commonjs --save-dev
5. Configure Babel
This can be done in two ways. We could create a Babel configuration file and call it.babelrc
,we will put this in the root of our application. The file will look like this:
{
"presets": ["react-app"],
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}
Another option would be to create a babel.config.js
file, this file has to be unique in your application and it will override any configuration you may have in any .babelrc
files. Why would you want to have a babel.config.js
file as opposed to a .babelrc
? One of reasons is that .babelrc
by default won’t transpile any file in the mode_modules folder in case you wanted, while babel.config.js
will. If we wanted the same configuration above our babel.config.js
file would look like this:
module.exports = function (api) {
const presets = ["react-app"];
const plugins = [
"@babel/plugin-transform-modules-commonjs",
"inline-react-svg"
]; /*change this value when you have a lot of tests*/
api.cache(false); return {
presets,
plugins
}};
6. Change our default test file to use Chai-Enzyme:
We will change the default Create React App test so that it can use our newly installed chai-enzyme enabling more intuitive functionalities to test our React components when our application will be more complex (see Chai, Enzyme and chai-enzyme docs). First we will create a new directory at root level of our application root, we will call it “test”. Then, we will move the file App.test.js
a in our test
directory, our structure will look like this:
|--test-mocha
|--src
|--test
App.test.js
App.css
App.js
index.css
logo.js
logo.svg
babel.config.js
...
Then change our App.test.js
as follows:
For the outcome of this tutorial we won’t go into the details of Enzyme’s Adapter, configure, shallow and render. To have a better understanding of these rendering methods refer to the respective docs (in the links).
7. Try to test now, it’s going…going…but…. wait…no…FAILED, what are those long error messages?
It took me a while to understand that Babel does not natively transpile two elements that are contained in the Create React App initial screen. These are the svg logo.svg
(the circling React logo) and the css stylesheets of the page, App.css
and index.css
These elements won’t necessarily be in your application but relating the test to the main Create React App page will help you understand how to implement tests in your first component.
To get Babel transpile svg we will have to install the Babel plugin inline svg yarn add babel-plugin-inline-react-svg --dev
or npm install babel-plugin-inline-react-svg --save-dev
To get Babel ignore the css imports we will have install the ignore styles module npm install ignore-styles --save-dev
or yarn add ignore-styles --dev
. If we want Babel to use this module we will have to require it in our test script that will launch Mocha, explained later.
If we decided to use a .babelrc
file, it will look like this:
If we are using a babel.config.js
it will look like this:
8. Change the test script in our package.json file
In our package.json file we will change the original Jest configuration with the following string:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "NODE_ENV=test mocha — require @babel/register — require ignore-styles src/test/*.test.js",
"eject": "react-scripts eject"
}
The test will set up the NODE_ENV
variable to test
, mocha
will call the Mocha test engine, the first — require
flag will load @babel/register
, transpiling our jsx into js , the second — require
will ignore the css stylesheets. Finally the last item is the path where our scripts are, it basically says to test all files that end with .test.js
in our src/test
directory. The directory pattern you want to match the tests may be different. If your OS is Windows the test script will be:
"test": "NODE_ENV=test&& mocha --require @babel/register --require ignore styles src/test/*.test.js
9. Run your test from the terminal
In Linux open your terminal and type from the root directory of your app type npm test
or yarn run test
And wow you should see the default Create React App test to render App.js
passing, just as you would have done it with jest.
I think that one benefits of Mocha is a really nice extension on VS Code that integrates it, if this is also your IDE you could proceed to the next part.
10. Install and setup the Visual Studio code Mocha sidebar
Mocha sidebar is a good tool to keep track of tests in your application in a visual way. It is also possible to debug our tests, and I feel like recommending it if you getting started with testing.
In VS code install the Mocha side bar extension from the interface and reload the application. If you are on Linux is better to restart VS code from terminal with $ code
, as I noticed that VS code sometimes does not recognise where your NodeJS path is, making the extension useless.
Once installed we will have to configure a few things to let the sidebar run with our tests. Hit Ctrl + ,
to open the settings dialog window and type “Mocha” on the search box on top, this will show all Mocha settings for VS code.
The options we are going to change are our Mocha: Env, Mocha -> Files -> Glob and Mocha:Requires. We can change them all in one go using VS code settings.json
. Click on “Edit in settings.json” under Mocha:Env, this will open the settings configuration file. Changes can be made at user, workspace or folder level, is up to you how you want to make these changes persistent. As I use workspaces and I have other workspaces for which I have different configurations I only changes the “Workspace settings”.
Change settings.json
as follows:
{
"settings": {
"window.zoomLevel": 0,
"javascript.updateImportsOnFileMove.enabled": "always",
"terminal.integrated.rendererType": "dom",
"mocha.files.glob": "src/test/*.test.js",
"mocha.requires": [
"@babel/register",
"ignore-styles"
],
"mocha.env": {
"NODE_ENV": "test"
}
}
}
11. Run your first test from Mocha VS code sidebar
Everything is ready to run our test from VS code Mocha sidebar, click on the “becker” icon, added by the extension and you will open the extension main interface where you can see the tests you set in your test folder.
When we will be in test mode the interface will be divided in three three main parts:
- The code editor: this is where your test code will appear, where you can create new test suites/specs and debug your existing ones, hovering and clicking on the run item/debug item buttons.
- The sidebar: it will contain a summary of the tests we have in our test folder, it will be possible to run/debug our suites/specs from there too and have a visual feedback on the test result with the icon next to every item. It will be possible to activate test watch on our code and check test coverage (shown on the footer).
- The terminal: Mocha sidebar will add a new item to our Output terminal in which we can see any Mocha output and get a more comprehensive information regarding the test we are running and its results, in the same way the terminal outputs information on our test.
Congratulations! We have just created a test environment with Mocha and Create React App. This tutorial is far from being exhaustive on creating a structured test strategy but it is a good start into exploring different testing options. I am myself still learning principles and concepts of unit testing and I feel the environment we have just created is helping me a lot, I hope it will be the same for you.
Happy testing everyone :-).