diff --git a/.circleci/config.yml b/.circleci/config.yml
index 36f96851..a00aca9c 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -354,6 +354,43 @@ workflows:
../../node_modules/.bin/only-covered main.js
working_directory: examples/support-files
+ - cypress/run:
+ attach-workspace: true
+ name: example-all-files
+ requires:
+ - cypress/install
+ # there are no jobs to follow this one
+ # so no need to save the workspace files (saves time)
+ no-workspace: true
+ start: npm start --prefix examples/all-files
+ wait-on: 'http://localhost:1234'
+ command: npx cypress run --project examples/all-files
+ # store screenshots and videos
+ store_artifacts: true
+ post-steps:
+ - run: cat examples/all-files/.nyc_output/out.json
+ - run: cat examples/all-files/coverage/coverage-final.json
+ # store the created coverage report folder
+ # you can click on it in the CircleCI UI
+ # to see live static HTML site
+ - store_artifacts:
+ path: examples/all-files/coverage
+ # make sure the examples captures 100% of code
+ - run:
+ command: npx nyc report --check-coverage true --lines 100
+ working_directory: examples/all-files
+ - run:
+ name: Check code coverage 📈
+ # we will check the final coverage report
+ # to make sure it only has files we are interested in
+ # because there are files covered at 0 in the report
+ command: |
+ ../../node_modules/.bin/check-coverage main.js
+ ../../node_modules/.bin/check-coverage second.js
+ ../../node_modules/.bin/check-coverage not-covered.js
+ ../../node_modules/.bin/only-covered --from coverage/coverage-final.json main.js second.js not-covered.js
+ working_directory: examples/all-files
+
- cypress/run:
attach-workspace: true
name: example-exclude-files
@@ -467,3 +504,4 @@ workflows:
- example-exclude-files
- example-docker-paths
- example-use-webpack
+ - example-all-files
diff --git a/README.md b/README.md
index 78e8a331..a4bf6016 100644
--- a/README.md
+++ b/README.md
@@ -298,6 +298,8 @@ For example, if you want to only include files in the `app` folder, but exclude
}
```
+**Note:** if you have `all: true` NYC option set, this plugin will check the produced `.nyc_output/out.json` before generating the final report. If the `out.json` file does not have information for some files that should be there according to `include` list, then an empty placeholder will be included, see [PR 208](https://github.com/cypress-io/code-coverage/pull/208).
+
## Disable plugin
You can skip the client-side code coverage hooks by setting the environment variable `coverage` to `false`.
diff --git a/common-utils.js b/common-utils.js
new file mode 100644
index 00000000..d2c786a8
--- /dev/null
+++ b/common-utils.js
@@ -0,0 +1,37 @@
+// @ts-check
+function combineNycOptions({
+ pkgNycOptions,
+ nycrc,
+ nycrcJson,
+ defaultNycOptions
+}) {
+ // last option wins
+ const nycOptions = Object.assign(
+ {},
+ defaultNycOptions,
+ nycrc,
+ nycrcJson,
+ pkgNycOptions
+ )
+
+ if (typeof nycOptions.reporter === 'string') {
+ nycOptions.reporter = [nycOptions.reporter]
+ }
+ if (typeof nycOptions.extension === 'string') {
+ nycOptions.extension = [nycOptions.extension]
+ }
+
+ return nycOptions
+}
+
+const defaultNycOptions = {
+ 'report-dir': './coverage',
+ reporter: ['lcov', 'clover', 'json'],
+ extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx'],
+ excludeAfterRemap: true
+}
+
+module.exports = {
+ combineNycOptions,
+ defaultNycOptions
+}
diff --git a/cypress/integration/combine-spec.js b/cypress/integration/combine-spec.js
index 9c05d1a6..1d6718b6 100644
--- a/cypress/integration/combine-spec.js
+++ b/cypress/integration/combine-spec.js
@@ -1,4 +1,4 @@
-const { combineNycOptions, defaultNycOptions } = require('../../task-utils')
+const { combineNycOptions, defaultNycOptions } = require('../../common-utils')
describe('Combine NYC options', () => {
it('overrides defaults', () => {
const pkgNycOptions = {
diff --git a/examples/all-files/.babelrc b/examples/all-files/.babelrc
new file mode 100644
index 00000000..7a016cf8
--- /dev/null
+++ b/examples/all-files/.babelrc
@@ -0,0 +1,3 @@
+{
+ "plugins": ["istanbul"]
+}
diff --git a/examples/all-files/README.md b/examples/all-files/README.md
new file mode 100644
index 00000000..e5faf288
--- /dev/null
+++ b/examples/all-files/README.md
@@ -0,0 +1 @@
+# example: all files
diff --git a/examples/all-files/cypress.json b/examples/all-files/cypress.json
new file mode 100644
index 00000000..5abc6bc7
--- /dev/null
+++ b/examples/all-files/cypress.json
@@ -0,0 +1,4 @@
+{
+ "fixturesFolder": false,
+ "baseUrl": "http://localhost:1234"
+}
diff --git a/examples/all-files/cypress/integration/spec.js b/examples/all-files/cypress/integration/spec.js
new file mode 100644
index 00000000..d7ca62b2
--- /dev/null
+++ b/examples/all-files/cypress/integration/spec.js
@@ -0,0 +1,12 @@
+///
+it('works', () => {
+ cy.visit('/')
+ cy.contains('Page body')
+
+ cy.window()
+ .invoke('reverse', 'super')
+ .should('equal', 'repus')
+
+ // application's code should be instrumented
+ cy.window().should('have.property', '__coverage__')
+})
diff --git a/examples/all-files/cypress/plugins/index.js b/examples/all-files/cypress/plugins/index.js
new file mode 100644
index 00000000..b17c48db
--- /dev/null
+++ b/examples/all-files/cypress/plugins/index.js
@@ -0,0 +1,5 @@
+module.exports = (on, config) => {
+ require('../../../../task')(on, config)
+ on('file:preprocessor', require('../../../../use-babelrc'))
+ return config
+}
diff --git a/examples/all-files/cypress/support/commands.js b/examples/all-files/cypress/support/commands.js
new file mode 100644
index 00000000..219920ee
--- /dev/null
+++ b/examples/all-files/cypress/support/commands.js
@@ -0,0 +1,2 @@
+import '../../../../support'
+console.log('this is commands file')
diff --git a/examples/all-files/cypress/support/index.js b/examples/all-files/cypress/support/index.js
new file mode 100644
index 00000000..b5c578c9
--- /dev/null
+++ b/examples/all-files/cypress/support/index.js
@@ -0,0 +1 @@
+require('./commands')
diff --git a/examples/all-files/index.html b/examples/all-files/index.html
new file mode 100644
index 00000000..993f0c18
--- /dev/null
+++ b/examples/all-files/index.html
@@ -0,0 +1,17 @@
+
+ Page body
+
+
+
+
diff --git a/examples/all-files/main.js b/examples/all-files/main.js
new file mode 100644
index 00000000..5dd69be2
--- /dev/null
+++ b/examples/all-files/main.js
@@ -0,0 +1,3 @@
+window.add = (a, b) => a + b
+
+window.sub = (a, b) => a - b
diff --git a/examples/all-files/not-covered.js b/examples/all-files/not-covered.js
new file mode 100644
index 00000000..39897541
--- /dev/null
+++ b/examples/all-files/not-covered.js
@@ -0,0 +1,7 @@
+// this file is NOT included from "index.html"
+// thus it is not instrumented and not included
+// in the final code coverage numbers
+function throwsError() {
+ throw new Error('NO')
+}
+throwsError()
diff --git a/examples/all-files/package.json b/examples/all-files/package.json
new file mode 100644
index 00000000..59c6d0a8
--- /dev/null
+++ b/examples/all-files/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "example-all-files",
+ "description": "Report all files",
+ "scripts": {
+ "start": "../../node_modules/.bin/parcel serve index.html",
+ "cy:open": "../../node_modules/.bin/cypress open",
+ "cy:run": "../../node_modules/.bin/cypress run",
+ "dev": "../../node_modules/.bin/start-test 1234 cy:open",
+ "e2e": "../../node_modules/.bin/start-test 1234 cy:run",
+ "report": "../../node_modules/.bin/nyc report"
+ },
+ "nyc": {
+ "all": true,
+ "include": "*.js"
+ },
+ "devDependencies": {
+ "@babel/core": "7.9.0"
+ }
+}
diff --git a/examples/all-files/second.js b/examples/all-files/second.js
new file mode 100644
index 00000000..494a0c5f
--- /dev/null
+++ b/examples/all-files/second.js
@@ -0,0 +1,7 @@
+// this file should be excluded from the final coverage numbers
+// using "nyc.exclude" list in package.json
+window.reverse = s =>
+ s
+ .split('')
+ .reverse()
+ .join('')
diff --git a/package-lock.json b/package-lock.json
index 75cd32dc..86d316b2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2976,7 +2976,6 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
"integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
- "dev": true,
"requires": {
"@nodelib/fs.stat": "2.0.3",
"run-parallel": "^1.1.9"
@@ -2985,8 +2984,7 @@
"@nodelib/fs.stat": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
- "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
- "dev": true
+ "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA=="
}
}
},
@@ -3000,7 +2998,6 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz",
"integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
- "dev": true,
"requires": {
"@nodelib/fs.scandir": "2.1.3",
"fastq": "^1.6.0"
@@ -4164,8 +4161,7 @@
"array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="
},
"array-unique": {
"version": "0.3.2",
@@ -6742,7 +6738,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
"requires": {
"path-type": "^4.0.0"
},
@@ -6750,8 +6745,7 @@
"path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
}
}
},
@@ -7558,7 +7552,6 @@
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.7.0.tgz",
"integrity": "sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ==",
- "dev": true,
"requires": {
"reusify": "^1.0.4"
}
@@ -8497,7 +8490,6 @@
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz",
"integrity": "sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==",
- "dev": true,
"requires": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
@@ -8510,14 +8502,12 @@
"@nodelib/fs.stat": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
- "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
- "dev": true
+ "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA=="
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
"requires": {
"fill-range": "^7.0.1"
}
@@ -8526,7 +8516,6 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz",
"integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==",
- "dev": true,
"requires": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
@@ -8540,7 +8529,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
@@ -8549,7 +8537,6 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
- "dev": true,
"requires": {
"is-glob": "^4.0.1"
}
@@ -8557,20 +8544,17 @@
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"merge2": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz",
- "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==",
- "dev": true
+ "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw=="
},
"micromatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
- "dev": true,
"requires": {
"braces": "^3.0.1",
"picomatch": "^2.0.5"
@@ -8580,7 +8564,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"requires": {
"is-number": "^7.0.0"
}
@@ -8983,8 +8966,7 @@
"ignore": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz",
- "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==",
- "dev": true
+ "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A=="
},
"import-fresh": {
"version": "2.0.0",
@@ -15570,8 +15552,7 @@
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
- "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
- "dev": true
+ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
},
"pify": {
"version": "2.3.0",
@@ -16967,8 +16948,7 @@
"reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
},
"rgb-regex": {
"version": "1.0.1",
@@ -17003,8 +16983,7 @@
"run-parallel": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
- "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
- "dev": true
+ "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q=="
},
"run-queue": {
"version": "1.0.3",
@@ -17582,8 +17561,7 @@
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
},
"slice-ansi": {
"version": "0.0.4",
diff --git a/package.json b/package.json
index 7ffea21b..58ca69c3 100644
--- a/package.json
+++ b/package.json
@@ -50,8 +50,9 @@
"@cypress/browserify-preprocessor": "2.2.1",
"debug": "4.1.1",
"execa": "4.0.0",
- "nyc": "15.0.1",
- "istanbul-lib-coverage": "3.0.0"
+ "globby": "11.0.0",
+ "istanbul-lib-coverage": "3.0.0",
+ "nyc": "15.0.1"
},
"devDependencies": {
"@babel/core": "7.9.0",
diff --git a/task-utils.js b/task-utils.js
index 7abd6274..05b729df 100644
--- a/task-utils.js
+++ b/task-utils.js
@@ -7,38 +7,8 @@ const { readFileSync, writeFileSync, existsSync } = require('fs')
const { isAbsolute, resolve, join } = require('path')
const debug = require('debug')('code-coverage')
const chalk = require('chalk')
-
-function combineNycOptions({
- pkgNycOptions,
- nycrc,
- nycrcJson,
- defaultNycOptions
-}) {
- // last option wins
- const nycOptions = Object.assign(
- {},
- defaultNycOptions,
- nycrc,
- nycrcJson,
- pkgNycOptions
- )
-
- if (typeof nycOptions.reporter === 'string') {
- nycOptions.reporter = [nycOptions.reporter]
- }
- if (typeof nycOptions.extension === 'string') {
- nycOptions.extension = [nycOptions.extension]
- }
-
- return nycOptions
-}
-
-const defaultNycOptions = {
- 'report-dir': './coverage',
- reporter: ['lcov', 'clover', 'json'],
- extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx'],
- excludeAfterRemap: true
-}
+const globby = require('globby')
+const { combineNycOptions, defaultNycOptions } = require('./common-utils')
function readNycOptions(workingDirectory) {
const pkgFilename = join(workingDirectory, 'package.json')
@@ -264,12 +234,116 @@ function tryFindingLocalFiles(nycFilename) {
}
}
+/**
+ * Tries to find source files to be included in the final coverage report
+ * using NYC options: extension list, include and exclude.
+ */
+function findSourceFiles(nycOptions) {
+ debug('include all files options: %o', {
+ all: nycOptions.all,
+ include: nycOptions.include,
+ exclude: nycOptions.exclude,
+ extension: nycOptions.extension
+ })
+
+ if (!Array.isArray(nycOptions.extension)) {
+ console.error(
+ 'Expected NYC "extension" option to be a list of file extensions'
+ )
+ console.error(nycOptions)
+ return []
+ }
+
+ let patterns = []
+ if (Array.isArray(nycOptions.include)) {
+ patterns = patterns.concat(nycOptions.include)
+ } else if (typeof nycOptions.include === 'string') {
+ patterns.push(nycOptions.include)
+ } else {
+ debug('using default list of extensions')
+ nycOptions.extension.forEach(extension => {
+ patterns.push('**/*' + extension)
+ })
+ }
+
+ if (Array.isArray(nycOptions.exclude)) {
+ const negated = nycOptions.exclude.map(s => '!' + s)
+ patterns = patterns.concat(negated)
+ } else if (typeof nycOptions.exclude === 'string') {
+ patterns.push('!' + nycOptions.exclude)
+ }
+ // always exclude node_modules
+ // https://github.com/istanbuljs/nyc#including-files-within-node_modules
+ patterns.push('!**/node_modules/**')
+
+ debug('searching files to include using patterns %o', patterns)
+
+ const allFiles = globby.sync(patterns, { absolute: true })
+ return allFiles
+}
+/**
+ * If the website or unit tests did not load ALL files we need to
+ * include, then we should include the missing files ourselves
+ * before generating the report.
+ *
+ * @see https://github.com/cypress-io/code-coverage/issues/207
+ */
+function includeAllFiles(nycFilename, nycOptions) {
+ if (!nycOptions.all) {
+ debug('NYC "all" option is not set, skipping including all files')
+ return
+ }
+
+ const allFiles = findSourceFiles(nycOptions)
+ if (debug.enabled) {
+ debug('found %d file(s)', allFiles.length)
+ console.error(allFiles.join('\n'))
+ }
+ if (!allFiles.length) {
+ debug('no files found, hoping for the best')
+ return
+ }
+
+ const nycCoverage = JSON.parse(readFileSync(nycFilename, 'utf8'))
+ const coverageKeys = Object.keys(nycCoverage)
+ const coveredPaths = coverageKeys.map(key => nycCoverage[key].path)
+ debug('coverage has the following paths %o', coveredPaths)
+
+ let changed
+ allFiles.forEach(fullPath => {
+ if (coveredPaths.includes(fullPath)) {
+ // all good, this file exists in coverage object
+ return
+ }
+ debug('adding empty coverage for file %s', fullPath)
+ changed = true
+ // insert placeholder object for now
+ nycCoverage[fullPath] = {
+ path: fullPath,
+ statementMap: {},
+ fnMap: {},
+ branchMap: {},
+ s: {},
+ f: {},
+ b: {}
+ }
+ })
+
+ if (changed) {
+ debug('saving updated file %s', nycFilename)
+ writeFileSync(
+ nycFilename,
+ JSON.stringify(nycCoverage, null, 2) + '\n',
+ 'utf8'
+ )
+ }
+}
+
module.exports = {
showNycInfo,
resolveRelativePaths,
checkAllPathsNotFound,
tryFindingLocalFiles,
readNycOptions,
- combineNycOptions,
- defaultNycOptions
+ includeAllFiles
}
diff --git a/task.js b/task.js
index 08c72a71..866cec0c 100644
--- a/task.js
+++ b/task.js
@@ -8,7 +8,8 @@ const {
resolveRelativePaths,
checkAllPathsNotFound,
tryFindingLocalFiles,
- readNycOptions
+ readNycOptions,
+ includeAllFiles
} = require('./task-utils')
const { fixSourcePaths } = require('./support-utils')
const NYC = require('nyc')
@@ -62,10 +63,13 @@ function maybePrintFinalCoverageFiles(folder) {
}
})
+ const hasStatements = totalStatements > 0
const allCovered = coveredStatements === totalStatements
+ const coverageStatus = hasStatements ? (allCovered ? '✅' : '⚠️') : '❓'
+
debug(
'%s %s statements covered %d/%d',
- allCovered ? '✅' : '⚠️',
+ coverageStatus,
key,
coveredStatements,
totalStatements
@@ -165,6 +169,11 @@ const tasks = {
// seems nyc API really is using camel cased version
nycReportOptions.reportDir = nycReportOptions['report-dir']
+ if (nycReportOptions.all) {
+ debug('nyc needs to report on all included files')
+ includeAllFiles(nycFilename, nycReportOptions)
+ }
+
debug('calling NYC reporter with options %o', nycReportOptions)
debug('current working directory is %s', process.cwd())
const nyc = new NYC(nycReportOptions)