Lessons learned enabling code typescript coverage in cypress with rollup and babel
cypress, javascript, typescript ·I spent last two evening fighting with my rollup
and babel
infrastructure to make code coverage work in cypress
for typescript
and I want to share some of my journey in case you encounter the same problems.
Let me start first by saying that if you have the simpler tasks of enabling code coverage in javascript, you should first just check this guide, I still recommend that you read this article because there is a twist in how to configure babel
but go first read the other post, I’ll wait here !
Likewise if you need to do it using webpack there is this other guide.
With that out of the way let’s focus on our problem, we have typescript
(and potentially javascript
) code that needs to be instrumented so that coverage can work in cypress
.
Cypress
supports coverage but don’t support instrumenting your code so something else has to do it.
The something else is currently nyc
/istanbul
and there is a plugin for babel to do that: babel-plugin-istanbul
, if you need typescript
be sure to also install @istanbuljs/nyc-config-typescript
.
Next we need to instruct nyc
to use the typescript
configuration that we just installed. I did that by adding this to my package.json
:
"nyc": {
"extends": "@istanbuljs/nyc-config-typescript",
"all": true
},
Next step is babel.
Babel
Your configuration (.babelrc.json
/ babelrc.js
) should look something like that:
{
presets: [
'@babel/preset-env',
'@babel/preset-typescript',
];
}
I don’t recommend to add plugins: ['istanbul'],
in the file as other posts suggest because otherwise you will have the instrumenting even in your release version, instead you should have a .dev
rollup configuration that you use for CI / testing of your release builds.
At this point it’s good to check that things are working correctly, install @babel/cli
and run:
npx babel src --extensions ".ts,.js,.tsx,.jsx" --plugins "istantbul"
If everything works as expected you should see path:
in the generated js
file:
grep path: demo/cubism-es.standalone.js |grep ts
path: "/github-cubism-es/src/context/apiCSS.ts",
path: "/github-cubism-es/src/context/apiKeyboard.ts",
If this is working we can move to configuring rollup to properly invoke babel
Rollup
The rollup configuration that you will use for coverage should contain an entry similar to this:
babel({
extensions: ['.js', '.jsx', '.ts', '.tsx'],
plugins: ['istanbul'],
// add here your additional settings like babelHelpers
}),
The first setting is to ensure that Javascript and Typescript files are properly handled by babel, I forgot to add it and that and it took me a while to figure out why the generated file from rollup
wasn’t properly instrumented.
The second setting is to obviously call istanbul
, re-iterating what I just said above this should go only in your .dev
or .testing
rollup configuration, not the one that you use to generate the artifacts for the releases.
Cypress
Add in cypress.config.js
the following code in the setupNodeEvent()
function:
require('@cypress/code-coverage/task')(on, config)
// include any other plugin code...
//
// It's IMPORTANT to return the config object
// with any changed environment variables
return config
The resulting configuration should look like:
const { defineConfig } = require('cypress');
module.exports = defineConfig({
chromeWebSecurity: false,
e2e: {
setupNodeEvents(on, config) {
require('@cypress/code-coverage/task')(on, config);
// include any other plugin code...
//
// It's IMPORTANT to return the config object
// with any changed environment variables
return config;
},
},
});
And there you have it your next cypress
should generate coverage for your code in javascript and typescript.