diff --git a/README.md b/README.md index 9f288b32..b11541b8 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,39 @@ If your application is loaded Istanbul-instrumented source code, then the covera ![Coverage report](images/coverage.jpg) +## Instrument unit tests + +If you test your application code directly from `specs` you might want to instrument them and combine unit test code coverage with any end-to-end code coverage (from iframe). You can easily instrument spec files using [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul) for example. Put the following in `cypress/plugins/index.js` file to use `.babelrc` file + +```js +const browserify = require('@cypress/browserify-preprocessor') + +module.exports = (on, config) => { + on('task', require('cypress-istanbul/task')) + + // tell Cypress to use .babelrc when bundling spec code + const options = browserify.defaultOptions + options.browserifyOptions.transform[1][1].babelrc = true + on('file:preprocessor', browserify(options)) +} +``` + +Install the plugin + +``` +npm i -D babel-plugin-istanbul +``` + +and set in your `.babelrc` file + +```rc +{ + "plugins": ["istanbul"] +} +``` + +Now the code coverage from spec files will be combined with end-to-end coverage. + ## Examples - [Demo battery app](https://github.com/bahmutov/demo-battery-api/tree/bundle) branch "bundle" diff --git a/support.js b/support.js index 6e5aba53..2acaa6d3 100644 --- a/support.js +++ b/support.js @@ -11,13 +11,35 @@ afterEach(() => { // because the entire "window" object is about // to be recycled by Cypress before next test cy.window().then(win => { - if (win.__coverage__) { - cy.task('combineCoverage', win.__coverage__) + // if application code has been instrumented, the app iframe "window" has an object + const applicationSourceCoverage = win.__coverage__ + + if (applicationSourceCoverage) { + cy.task('combineCoverage', applicationSourceCoverage) } }) }) after(() => { + const specFolder = Cypress.config('integrationFolder') + const supportFolder = Cypress.config('supportFolder') + + // if spec bundle has been instrumented (using Cypress preprocessor) + // then we will have unit test coverage + // NOTE: spec iframe is NOT reset between the tests, so we can grab + // the coverage information only once after all tests have finished + const unitTestCoverage = window.__coverage__ + if (unitTestCoverage) { + // remove coverage for the spec files themselves, + // only keep "external" application source file coverage + const coverage = Cypress._.omitBy( + window.__coverage__, + (fileCoverage, filename) => + filename.startsWith(specFolder) || filename.startsWith(supportFolder) + ) + cy.task('combineCoverage', coverage) + } + // when all tests finish, lets generate the coverage report cy.task('coverageReport') })