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.
click on spec.ts and watch your first successful test!
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.
This will also generate an html page for you that looks like this.
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)
Hey, I'm having two issues that I was hoping you could help me work through.
When I run
ng e2e
using@briebug/cypress-schematic
, it sets the baseUrl tohttp://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?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 haverequire('@cypress/code-coverage/task')(on, config);
in my index.js file.Please help!
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.
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"Thanks Robert... I say Jamine is dead because of Cypress. It just makes way more sense.
Absolutely, this is testing the way everyone ACTUALLY tests their UI applications... Visually.
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.
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?
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);
}
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?
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?