DEV Community

Cover image for Code Coverage With Cypress & Angular
Robert Dale Morris
Robert Dale Morris

Posted on • Edited on

Code Coverage With Cypress & Angular

This example can be found on github ang-cy-cov-example

As a front end developer it's very easy to get caught up in the fine tuning of that perfect web application. If you have multiple people working together, it can be annoying when someone else's changes tend to skew the looks or functionality of your component. There haven't really been any great testing frameworks that test applications visually the way a user does. Not until now at least...
Cypress.io is an amazing framework designed for complete top down testing of your application. Written by front end developers, for front end developers. For those of us working in companies though, we may still need to provide a report that shows the coverage of our tests still reach a percentage of the code base. Since Cypress is designed to work with any front end framework, or none for that matter, they leave this to us to implement. Don't be to worried though.. I'm here to walk you through the easy set up.

Note: This walk-through is meant for Angular version 8 and above.

First we will start off by generating a fresh new Angular application

  ng new ang-cy-cov-example

It does not matter if you add routing or which type of style you use for the purpose of this walk-through

Install cypress-schematic to switch from protractor to cypress e2e framework

  npm i -D  @briebug/cypress-schematic

Add the schematic as a dependency to your project.

  ng add @briebug/cypress-schematic

This will prompt you to remove protractor, answer y

NOTE: if you are following this example from an application that already has cypress installed, you may need to run the above command with --force so that it pushes through the error that is created by the cypress.json already existing
This command will also override your cypress.json file, just revert those changes and add the following line
"supportFile": "cypress/support/index.ts"

Open up cypress/integration/spec.ts and change

it("loads examples", () => {
  cy.visit("http://localhost:4200");
  cy.contains("Replace me with something relevant");
});

to

it("loads examples", () => {
  cy.visit("http://localhost:4200");
  cy.contains("we are doing big things!");
});

Open up src/app/app.component.html and change the following:

<span>Learn Angular</span>

to

<span>we are doing big things!</span>

now we can check to see if our schematic set up correctly by running

ng e2e

After your angular server begins, cypress will open showing your test.
Alt Text
click on spec.ts and watch your first successful test!
Alt Text

Now this is all very fun and exciting, but now on to the professional stuff. That good old coverage report.

Next we will add a few files.
First you will need to add coverage.webpack.js to your cypress/ folder

touch cypress/coverage.webpack.js

inside the file, paste this code.

module.exports = {
    module: {
      rules: [
        {
          test: /\.(js|ts)$/,
          loader: 'istanbul-instrumenter-loader',
          options: { esModules: true },
          enforce: 'post',
          include: require('path').join(__dirname, '..', 'src'),
          exclude: [
            /\.(e2e|spec)\.ts$/,
            /node_modules/,
            /(ngfactory|ngstyle)\.js/
          ]
        }
      ]
    }
  };

next we will add cy-ts-preprocessor.js to your cypress/plugins/ folder

touch cypress/plugins/cy-ts-preprocessor.js

inside the file, paste this code.

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)

Then we will add a new builder

npm i -D ngx-build-plus

proceed to your angular.json file and alter your serve configuration to look like this, to use the ngx-build with extra config.

{
"serve": {
          "builder": "ngx-build-plus:dev-server",
          "options": {
            "browserTarget": "cypress-angular-coverage-example:build",
            "extraWebpackConfig": "./cypress/coverage.webpack.js"
          }
}

Add to Instrument JS files with istanbul-lib-instrument for subsequent code coverage reporting

npm i -D istanbul-instrumenter-loader

Make Istanbul understand your Typescript source file

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

proceed to your package.json and include the following configuration

{
 "nyc": {
    "extends": "@istanbuljs/nyc-config-typescript",
    "all": true
  }
}

If you are still following great! I realize its a little tedious but we are almost there.
Next, install the cypress code coverage plugin

npm install -D @cypress/code-coverage nyc istanbul-lib-coverage

Then we need to add a few lines to some cypress files.
first open cypress/support/index.js and add the following.

import './commands';

// Import cypress code-coverage collector plugin
import '@cypress/code-coverage/support';

next open cypress/plugins/index.js and replace

module.exports = (on, config) => {
  // `on` is used to hook into various events Cypress emits
  // `config` is the resolved Cypress config
}

with

/**
 * @type {Cypress.PluginConfig}
 */
const cypressTypeScriptPreprocessor = require('./cy-ts-preprocessor')

module.exports = on => {
  on('file:preprocessor', cypressTypeScriptPreprocessor);

  // enable code coverage collection
  on('task', require('@cypress/code-coverage/task'));
}

now, we should have arrived, we can now run the following

ng run ang-cy-cov-example:cypress-run

this should open cypress and run your tests then close. you will then be able to see the newly generated .nyc-output and coverge folders in your project tree.
Alt Text

This will also generate an html page for you that looks like this.
Alt Text

Thanks and I really hope this helps you all.
Also, check out my npm package for those who are trying to generate reports using mocha/mochawesome report generator here cy-report-setup-helper

Please feel free to connect on linked in for any questions or just to link up!
Robert Morris on Linked in
follow me on twitter
Robert Morris on Twitter
Github
Gettindatfoshow
Blogspot
CsSoldier

Top comments (10)

Collapse
 
craigdae profile image
Craig

Hey, I'm having two issues that I was hoping you could help me work through.

  1. When I run ng e2e using @briebug/cypress-schematic, it sets the baseUrl to http://localhost:4200. Cypress tells me this is being set in the cli. I need the baseUrl to be: http://localhost.localdomain:8080 for reasons relating the nginx being configured a specific way for the local backend. I can't figure out how to override this value. cypress.json doesn't do it, setting an environment variable in linux doesn't do it. How can I set the baseUrl to what I need?

  2. I get the error: ⚠️ Code coverage tasks were not registered by the plugins file. See support issue for possible workarounds. [@cypress/code-coverage] I can't make sense of this error, since I followed the steps in this guide, and I have require('@cypress/code-coverage/task')(on, config); in my index.js file.

Please help!

Collapse
 
john__olson profile image
John Olson

Thanks Robert. We were just looking at adding coverage to our Angular Cypress tests. Perfect timing. Have you found a way to redirect the coverage output to another folder? Right now, we're using a script to move all our e2e coverage to a single folder. Nyc has a report-dir but didn't seem to work. Thanks.

Collapse
 
szai0103 profile image
szai0103 • Edited

Thank You for the great tutorial, please, can you give a solution for this error

Error: The handler for the event task must be an object which is thrown by plugin file cypress/plugins/index.js`. I use the "cypress": "^5.2.0"

Collapse
 
jwp profile image
John Peters

Thanks Robert... I say Jamine is dead because of Cypress. It just makes way more sense.

Collapse
 
cssoldiervoif profile image
Robert Dale Morris

Absolutely, this is testing the way everyone ACTUALLY tests their UI applications... Visually.

Collapse
 
jwp profile image
John Peters

So true, manual tester have approached web tests from the web browser for 20 years now. How Jasmine ever thought to 'better that" is just beyond me. Especially when the app had to mock everything, preventing any application html requests/responses.

Collapse
 
chrismurphy profile image
Chris Murphy • Edited

I have followed every step exactly as far as I can tell, however when Cypress is open the coverage step is saying I don't have code instrumented. I have the ngx build plus config in the serve of my application and I'm pointing to the custom webpack coverage file. The only difference being my application is in a projects folder so have changed "src" to "projects/my-application/src". I have redone everything several times. The nyc and coverage folder are being created. Any ideas on what else I can try please?

Collapse
 
valio2 profile image
valio2

Since cypress version 4.4, plugins/indexjs file should look like this:

const cypressTypeScriptPreprocessor = require("./cy-ts-preprocessor");
const registerCodeCoverageTasks = require('@cypress/code-coverage/task');

module.exports = (on, config) => {
on('file:preprocessor', cypressTypeScriptPreprocessor);

// enable code coverage collection
return registerCodeCoverageTasks(on, config);
}

Collapse
 
jameseg profile image
jameseg

I'm having trouble getting .html files excluded from coverage and I think it may have to do with the coverage.webpack.js file. Anyone have a way to add these to the exclusion list?

Collapse
 
karthik22061993 profile image
karthik22061993

Hi everyone, has anyone tried to generate cypress code coverage using angular 6.1? If yes, can someone tell me what modification I have to make in reference to this blog to get code coverage?