DEV Community

Cover image for How to set up Cypress code coverage with TypeScript and ts-loader
Christine Schorn (she/her)
Christine Schorn (she/her)

Posted on

How to set up Cypress code coverage with TypeScript and ts-loader


This post first appeared on the IE Digital Blog

In this short tutorial, I want to show you how you can set up Cypress code coverage using the @cypress/code-coverage plugin in a TypeScript project. 

Note: If you are using babel-loader in your project, this tutorial might not be necessary for you. Instead, I recommend you to follow this tutorial. However, if your project is using the ts-loader, stick with me. 

To begin with, let's assume that you already have a project set up with webpack and TypeScript and that you are using Cypress as your front end testing tool. So you are now at a point where you want to generate a nicely formatted code coverage report.

As it turns out, at the point of writing this, it's a bit trickier to integrate Cypress code-coverage if you are using the ts-loader, so just following the @cypress/code-coverage plugin setup won't work. Luckily though, with some more steps, we can get it working for our project as well. So let's start.

Installing babel dependencies

First, we have to install some dependencies that we'll need to get things rolling. Since Cypress code-coverage doesn't just work with the ts-loader (as mentioned), we have to add the babel-loader and its necessary dependencies to our project.

yarn add -D @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript babel-loader

Setting up webpack

Since webpack is managing our loaders and we're only using the ts-loader at the moment, we'll have to update our webpack.config.js file and add the babel-loader to our rules as well.

module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.scss', '.js'],
  },
Enter fullscreen mode Exit fullscreen mode

You might be wondering why we're using two transpilers now. In my case, the project was already set up using the ts-loader, so I choose to just add the babel-loader instead of changing the whole project to only use the babel-loader.

Setting up babel

Setting up babel is pretty simple. Babel will help us transpile our TypeScript to the right Javascript standard. So let's create our .babelrc file if you don't have one already and add the following snippet:

{
  "presets": [
    "@babel/react",
    "@babel/typescript",
    [
      "@babel/env",
      {
        "modules": false,
        "targets": {
          "chrome": "58",
          "ie": "11"
        }
      }
    ]
  ]
}
Enter fullscreen mode Exit fullscreen mode

All we do here, for now, is to tell Babel to use it's React and TypeScript presets and to transpile to a minimum version of IE 11 and Chrome 58.

Installing Cypress dependencies

add -D @istanbuljs/nyc-config-typescript source-map-support ts-node

Proceed to your package.json file and add the following lines

"nyc": {
    "extends": "@istanbuljs/nyc-config-typescript",
    "all": true,
    "report-dir": "cypress-coverage"
  }
Enter fullscreen mode Exit fullscreen mode

If you want to save your reports in another folder, you can just change cypress-coverage to the name of your target folder.

I know this is a lot but hang in there. As our next step, let's install the Cypress code coverage plugin.

yarn add -D @cypress/code-coverage nyc istanbul-lib-coverage

Update your .babelrc file, so it looks like this:

{
  "plugins": [
    "istanbul"
  ],
  "presets": [
    "@babel/react",
    "@babel/typescript",
    [
      "@babel/env",
      {
        "modules": false,
        "targets": {
          "chrome": "58",
          "ie": "11"
        }
      }
    ]
  ]
}
Enter fullscreen mode Exit fullscreen mode

Because the @cypress/code-coverage plugin DOES NOT instrument your code, we have to instrument it ourselves. We are using the Istanbul.js tool for that and since we are now using Babel to transpile our code, we can just add the babel-plugin-istanbul to our .babelrc file and we're good to go.

Now we're almost there. Add the following line to your cypress/support/index.js file:

import '@cypress/code-coverage/support'

And the following snippet to your cypress/plugins/index.js:

const cypressTypeScriptPreprocessor = require('./cy-ts-preprocessor')

module.exports = (on, config) => {
  require('@cypress/code-coverage/task')(on, config)
  on('file:preprocessor', cypressTypeScriptPreprocessor);
  return config
}
Enter fullscreen mode Exit fullscreen mode

As our final step, let's create a new file cy-ts-preprocessor.js in your cypress/plugins/ folder and paste the following snippet:

const wp = require('@cypress/webpack-preprocessor')

const webpackOptions = {
  resolve: {
    extensions: ['.ts', '.js']
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: [/node_modules/],
        use: [
          {
            loader: 'ts-loader'
          }
        ]
      }
    ]
  }
}

const options = {
  webpackOptions
}

module.exports = wp(options)
Enter fullscreen mode Exit fullscreen mode

Now you should be able to run your tests and get a nicely formatted code-coverage report.

yarn run cypress run
open cypress-coverage/lcov-report/index.html

I really hope this helps you all to get your Cypress code-coverage going.

Special thanks to all the folks out there who have put out amazing tutorials as well. I would not have been able to write this tutorial without them. If you want to have a further look, check them out below


Top comments (7)

Collapse
 
inspiraller profile image
steve • Edited

Hi thanks for sharing this. I cloned your repo and was struggling to see the results of the coverage, after following all your instructions:

Cannot find coverage file c:\cypress-typescript-coverage-example\.nyc_output\out.json
Skipping coverage report
Enter fullscreen mode Exit fullscreen mode

I realised now that when running the actual application in dev mode, that is when the plugins are detected in babel. This is my update. Might be worth

Add dependency - cross-env - or something to enable the variable

yarn add cross-env --save-dev
Enter fullscreen mode Exit fullscreen mode

package.json

  "scripts": {
    "start": "cross-env CODE_COVERAGE=true webpack-dev-server",
    "test": "nyc --reporter=text-summary cypress run --headless"
  }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
srikanthkyatham profile image
Srikanth Kyatham

Hi

This was exactly the guide needed for my use case as well. Appreciate your effort here.
I have faced the following packages were missing from the instructions if you could update your guide with those would be helpful

1."@cypress/webpack-preprocessor"
2."istanbuljs/nyc-config-typescript"

Collapse
 
ravih profile image
Ravi Hasija

Christine,

This is genius. This was the last step in my 100 mile journey! I needed to change a couple things because I use Quasar/Vue, but this got me there. THANK YOU!

Collapse
 
cauany profile image
Cauany Souza • Edited

Hi Ravi, could you tell me how you solved this problem? I'm having a problem with the configuration, I'm using Quasar Framework and Vue.js the problem is that the files are not read typescript files for code coverage.

Collapse
 
enitschorn profile image
Christine Schorn (she/her)

Woooow! So happy that it helped you - that's exactly what I wrote this tutorial for ❤️

Collapse
 
chirag1212 profile image
Chirag Parihar

Christine, this was extremely useful. I was stumbling since days to figure out cypress code coverage setup for my project and this blog helped me achieve the same. One quick question though, after adding babel-loader alongside (the already existing) ts-loader, my build time have shot up expectedly. Did you also experience the same? If yes, what can be done to solve this

Collapse
 
vendenix profile image
Romain Andres

Is this tutoriel possible without webpack ?