Istanbul is a code coverage utility for JavaScript apps. It is integrated with most unit-testing frameworks like Jest. It is also possible to produce an instrumentation build with a babel plugin named babel-plugin-istanbul. This works for any React app scaffolded with Webpack configuration. However, it does not work for create-react-app (CRA). CRA does not expose webpack.config or .babelrc file, files where we can add the istanbul plugin. After consulting with Facebook team, I decided to create a custom react-scripts package named react-scripts-istanbul.
Creating a custom react-scripts package
The react-scripts-istanbul package does the following:
- Include babel-plugin-istanbul if the environment is not production.
- Produce a regular production build when –coverage flag is not specified.
- Produce an instrumentation build when –coverage flag is specified.
- Start the webpack-dev-server with instrumented source code.
While creating the react-scripts package, I encountered a few obstacles. It was caused by working on top of master branch with some unreleased changes in react-dev-utils package. For those who want to create a custom react-scripts package, make sure you checkout the latest released tag and build it up from there.
Another thing that was a problem for me was how to test it. I could not figure how to run the tests for react-scripts package. So, I set out to publish the package in NPM before testing it. If you know how to test react-scripts, please let me know in a blog post or in comments.
I made a few changes in two files: config/webpack.config.js and build.js
- webpack.config.js: Added the plugin for development environment.
- webpack.config.js: For development environment, specified the output path.
- In build.js, switched the environment back to development if –coverage flag is specified.
- Since build.js is written only for production environment, made some changes so that it works for development environment also.
With the above changes, I published the NPM package.
How to use react-scripts-istanbul
CRA allows using custom react-scripts like so.
create-react-app
--scripts-version react-scripts-istanbul
coveragedemo
After installation, the dependencies should like so.
cd coveragedemo
yarn start
This should start localhost at port 3000. Open the browser console and type __coverage__ and press Enter. You should see the coverage object like so.
Next, do a regular production build and use utility like serve to run a server.
yarn build
cd build
serve
Go to localhost:5000 and look for coverage object like before. Since this is a production build, you should not see any coverage object.
To produce an instrumentation build, use the –coverage flag.
yarn build --coverage
cd build
serve
Go to localhost:5000 and look for coverage object. You should now see the coverage object.
Using packages like istanbul-coverage-display, we can view the coverage object as we interact with the app.
Using istanbul-coverage-display
Install the package.
yarn add istanbul-coverage-display
In App.js, import the CoverageSummary component.
import { CoverageSummary } from 'istanbul-coverage-display';
import 'istanbul-coverage-display/dist/bundle.css';
Add the CoverageSummary component to the App component just before the closing div tag.
<CoverageSummary />
</div>
When you run the app, you should see the “Show coverage” button. On clicking on the button, you should view the coverage summary in a nice widget.
There is also a CoverageDetail component which can be placed below the logo.
<CoverageDetail />
The coverage is low because of the service worker in CRA.
Hi,
nice tutorial. I am using your scrips, the problem is that the build script doesn’t transpile the code and everything fails when I execute my app with nginx.
There is anything I can do to transpile the instrumented code?
Thanks,
Marc