diff --git a/lib/commands/check-coverage.js b/lib/commands/check-coverage.js
index 6d14c428b..2816a5876 100644
--- a/lib/commands/check-coverage.js
+++ b/lib/commands/check-coverage.js
@@ -1,6 +1,5 @@
-const testExclude = require('test-exclude')
const NYC = require('../../index.js')
-const cliWrapper = require('./cli-wrapper.js')
+const { cliWrapper, setupOptions } = require('./helpers.js')
exports.command = 'check-coverage'
@@ -9,61 +8,9 @@ exports.describe = 'check whether coverage is within thresholds provided'
exports.builder = function (yargs) {
yargs
.demandCommand(0, 0)
- .option('exclude', {
- alias: 'x',
- default: testExclude.defaultExclude,
- describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded',
- global: false
- })
- .option('exclude-node-modules', {
- default: true,
- type: 'boolean',
- describe: 'whether or not to exclude all node_module folders (i.e. **/node_modules/**) by default',
- global: false
- })
- .option('exclude-after-remap', {
- default: true,
- type: 'boolean',
- description: 'should exclude logic be performed after the source-map remaps filenames?',
- global: false
- })
- .option('include', {
- alias: 'n',
- default: [],
- describe: 'a list of specific files that should be covered, glob patterns are supported',
- global: false
- })
- .option('branches', {
- default: 0,
- description: 'what % of branches must be covered?'
- })
- .option('functions', {
- default: 0,
- description: 'what % of functions must be covered?'
- })
- .option('lines', {
- default: 90,
- description: 'what % of lines must be covered?'
- })
- .option('statements', {
- default: 0,
- description: 'what % of statements must be covered?'
- })
- .option('per-file', {
- default: false,
- description: 'check thresholds per file'
- })
- .option('temp-dir', {
- alias: 't',
- describe: 'directory to read raw coverage information from',
- default: './.nyc_output',
- global: false
- })
- .option('temp-directory', {
- hidden: true,
- global: false
- })
.example('$0 check-coverage --lines 95', "check whether the JSON in nyc's output folder meets the thresholds provided")
+
+ setupOptions(yargs, 'check-coverage')
}
exports.handler = cliWrapper(async argv => {
diff --git a/lib/commands/cli-wrapper.js b/lib/commands/cli-wrapper.js
deleted file mode 100644
index 5e5984653..000000000
--- a/lib/commands/cli-wrapper.js
+++ /dev/null
@@ -1,10 +0,0 @@
-'use strict'
-
-module.exports = execute => {
- return argv => {
- execute(argv).catch(error => {
- console.error(error.message)
- process.exit(1)
- })
- }
-}
diff --git a/lib/commands/helpers.js b/lib/commands/helpers.js
new file mode 100644
index 000000000..8b967bd81
--- /dev/null
+++ b/lib/commands/helpers.js
@@ -0,0 +1,61 @@
+'use strict'
+
+const decamelize = require('decamelize')
+const schema = require('@istanbuljs/schema')
+
+/* These options still need to be connected to the instrumenter
+ * Disabling them for now also avoids the issue with OSX cutting
+ * off the error help screen at 8192 characters.
+ */
+const blockOptions = [
+ 'coverageVariable',
+ 'coverageGlobalScope',
+ 'coverageGlobalScopeFunc'
+]
+
+module.exports = {
+ setupOptions (yargs, command, cwd) {
+ Object.entries(schema.nyc.properties).forEach(([name, setup]) => {
+ if (blockOptions.includes(name)) {
+ return
+ }
+
+ const option = {
+ description: setup.description,
+ default: setup.default,
+ type: setup.type
+ }
+
+ if (name === 'cwd') {
+ if (command !== null) {
+ return
+ }
+
+ option.default = cwd
+ option.global = true
+ }
+
+ if (option.type === 'array') {
+ option.type = 'string'
+ }
+
+ if ('nycAlias' in setup) {
+ option.alias = setup.nycAlias
+ }
+
+ const optionName = decamelize(name, '-')
+ yargs.option(optionName, option)
+ if (!setup.nycCommands.includes(command)) {
+ yargs.hide(optionName)
+ }
+ })
+ },
+ cliWrapper (execute) {
+ return argv => {
+ execute(argv).catch(error => {
+ console.error(error.message)
+ process.exit(1)
+ })
+ }
+ }
+}
diff --git a/lib/commands/instrument.js b/lib/commands/instrument.js
index cdd89df12..256e40db4 100644
--- a/lib/commands/instrument.js
+++ b/lib/commands/instrument.js
@@ -2,101 +2,18 @@ const NYC = require('../../index.js')
const path = require('path')
const { promisify } = require('util')
const rimraf = promisify(require('rimraf'))
-const testExclude = require('test-exclude')
-const cliWrapper = require('./cli-wrapper.js')
+const { cliWrapper, setupOptions } = require('./helpers.js')
exports.command = 'instrument [output]'
exports.describe = 'instruments a file or a directory tree and writes the instrumented code to the desired output location'
exports.builder = function (yargs) {
- return yargs
+ yargs
.demandCommand(0, 0)
- .positional('input', {
- describe: 'file or directory to instrument',
- type: 'text'
- })
- .positional('output', {
- describe: 'directory to output instrumented files',
- type: 'text'
- })
- .option('require', {
- alias: 'i',
- default: [],
- describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., @babel/register, @babel/polyfill.'
- })
- .option('extension', {
- alias: 'e',
- default: ['.cjs', '.mjs', '.ts', '.tsx', '.jsx'],
- describe: 'a list of extensions that nyc should handle in addition to .js'
- })
- .option('source-map', {
- default: true,
- type: 'boolean',
- describe: 'should nyc detect and handle source maps?'
- })
- .option('produce-source-map', {
- default: false,
- type: 'boolean',
- describe: "should nyc's instrumenter produce source maps?"
- })
- .option('compact', {
- default: true,
- type: 'boolean',
- describe: 'should the output be compacted?'
- })
- .option('preserve-comments', {
- default: true,
- type: 'boolean',
- describe: 'should comments be preserved in the output?'
- })
- .option('instrument', {
- default: true,
- type: 'boolean',
- describe: 'should nyc handle instrumentation?'
- })
- .option('in-place', {
- default: false,
- type: 'boolean',
- describe: 'should nyc run the instrumentation in place?'
- })
- .option('exit-on-error', {
- default: false,
- type: 'boolean',
- describe: 'should nyc exit when an instrumentation failure occurs?'
- })
- .option('include', {
- alias: 'n',
- default: [],
- describe: 'a list of specific files and directories that should be instrumented, glob patterns are supported'
- })
- .option('exclude', {
- alias: 'x',
- default: testExclude.defaultExclude,
- describe: 'a list of specific files and directories that should not be instrumented, glob patterns are supported'
- })
- .option('exclude-node-modules', {
- default: true,
- type: 'boolean',
- describe: 'whether or not to exclude all node_module folders (i.e. **/node_modules/**) by default',
- global: false
- })
- .option('es-modules', {
- default: true,
- type: 'boolean',
- description: 'tell the instrumenter to treat files as ES Modules'
- })
- .option('delete', {
- describe: 'should the output folder be deleted before instrumenting files?',
- default: false,
- type: 'boolean'
- })
- .option('complete-copy', {
- describe: 'should nyc copy all files from input to output as well as instrumented files?',
- default: false,
- type: 'boolean'
- })
.example('$0 instrument ./lib ./output', 'instrument all .js files in ./lib with coverage and output in ./output')
+
+ setupOptions(yargs, 'instrument')
}
exports.handler = cliWrapper(async argv => {
diff --git a/lib/commands/merge.js b/lib/commands/merge.js
index b5b4ba654..0aefd11ec 100644
--- a/lib/commands/merge.js
+++ b/lib/commands/merge.js
@@ -2,7 +2,7 @@
const path = require('path')
const makeDir = require('make-dir')
const fs = require('../fs-promises')
-const cliWrapper = require('./cli-wrapper.js')
+const { cliWrapper, setupOptions } = require('./helpers.js')
const NYC = require('../../index.js')
@@ -11,8 +11,9 @@ exports.command = 'merge [output-file]'
exports.describe = 'merge istanbul format coverage output in a given folder'
exports.builder = function (yargs) {
- return yargs
+ yargs
.demandCommand(0, 0)
+ .example('$0 merge ./out coverage.json', 'merge together reports in ./out and output as coverage.json')
.positional('input-directory', {
describe: 'directory containing multiple istanbul coverage files',
type: 'text',
@@ -23,15 +24,9 @@ exports.builder = function (yargs) {
type: 'text',
default: 'coverage.json'
})
- .option('temp-dir', {
- alias: 't',
- describe: 'directory to read raw coverage information from',
- default: './.nyc_output'
- })
- .option('temp-directory', {
- hidden: true
- })
- .example('$0 merge ./out coverage.json', 'merge together reports in ./out and output as coverage.json')
+
+ setupOptions(yargs, 'merge')
+ yargs.default('exclude-after-remap', false)
}
exports.handler = cliWrapper(async argv => {
diff --git a/lib/commands/report.js b/lib/commands/report.js
index 0c61e8aee..4c2b29752 100644
--- a/lib/commands/report.js
+++ b/lib/commands/report.js
@@ -1,105 +1,16 @@
-const testExclude = require('test-exclude')
const NYC = require('../../index.js')
-const cliWrapper = require('./cli-wrapper.js')
+const { cliWrapper, setupOptions } = require('./helpers.js')
exports.command = 'report'
exports.describe = 'run coverage report for .nyc_output'
exports.builder = function (yargs) {
- return yargs
+ yargs
.demandCommand(0, 0)
- .option('reporter', {
- alias: 'r',
- describe: 'coverage reporter(s) to use',
- default: 'text'
- })
- .option('report-dir', {
- describe: 'directory to output coverage reports in',
- default: 'coverage'
- })
- .option('temp-dir', {
- alias: 't',
- describe: 'directory to read raw coverage information from',
- default: './.nyc_output'
- })
- .option('temp-directory', {
- hidden: true
- })
- .option('exclude', {
- alias: 'x',
- default: testExclude.defaultExclude,
- describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded',
- global: false
- })
- .option('exclude-node-modules', {
- default: true,
- type: 'boolean',
- describe: 'whether or not to exclude all node_module folders (i.e. **/node_modules/**) by default',
- global: false
- })
- .option('exclude-after-remap', {
- default: true,
- type: 'boolean',
- description: 'should exclude logic be performed after the source-map remaps filenames?',
- global: false
- })
- .option('include', {
- alias: 'n',
- default: [],
- describe: 'a list of specific files that should be covered, glob patterns are supported',
- global: false
- })
- .option('extension', {
- alias: 'e',
- default: ['.cjs', '.mjs', '.ts', '.tsx', '.jsx'],
- describe: 'a list of extensions that nyc should handle in addition to .js',
- global: false
- })
- .option('show-process-tree', {
- describe: 'display the tree of spawned processes',
- default: false,
- type: 'boolean'
- })
- .option('skip-empty', {
- describe: 'don\'t show empty files (no lines of code) in report',
- default: false,
- type: 'boolean',
- global: false
- })
- .option('check-coverage', {
- type: 'boolean',
- default: false,
- describe: 'check whether coverage is within thresholds provided',
- global: false
- })
- .option('branches', {
- default: 0,
- description: 'what % of branches must be covered?',
- global: false
- })
- .option('functions', {
- default: 0,
- description: 'what % of functions must be covered?',
- global: false
- })
- .option('lines', {
- default: 90,
- description: 'what % of lines must be covered?',
- global: false
- })
- .option('statements', {
- default: 0,
- description: 'what % of statements must be covered?',
- global: false
- })
- .option('per-file', {
- default: false,
- type: 'boolean',
- description: 'check thresholds per file',
- global: false
- })
.example('$0 report --reporter=lcov', 'output an HTML lcov report to ./coverage')
+
+ setupOptions(yargs, 'report')
}
exports.handler = cliWrapper(async argv => {
diff --git a/lib/config-util.js b/lib/config-util.js
index 28d61e048..883a12caa 100644
--- a/lib/config-util.js
+++ b/lib/config-util.js
@@ -2,9 +2,9 @@
const path = require('path')
const findUp = require('find-up')
-const testExclude = require('test-exclude')
const Yargs = require('yargs/yargs')
+const { setupOptions } = require('./commands/helpers')
const processArgs = require('./process-args')
const { loadNycConfig } = require('@istanbuljs/load-nyc-config')
@@ -23,222 +23,11 @@ async function processConfig (cwd) {
const yargs = Yargs([])
.usage('$0 [command] [options]')
.usage('$0 [options] [bin-to-instrument]')
- .option('reporter', {
- alias: 'r',
- describe: 'coverage reporter(s) to use',
- default: 'text',
- global: false
- })
- .option('report-dir', {
- describe: 'directory to output coverage reports in',
- default: 'coverage',
- global: false
- })
- .option('silent', {
- alias: 's',
- default: false,
- type: 'boolean',
- describe: "don't output a report after tests finish running",
- global: false
- })
- .option('all', {
- alias: 'a',
- default: false,
- type: 'boolean',
- describe: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)',
- global: false
- })
- .option('exclude', {
- alias: 'x',
- default: testExclude.defaultExclude,
- describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded',
- global: false
- })
- .option('exclude-after-remap', {
- default: true,
- type: 'boolean',
- description: 'should exclude logic be performed after the source-map remaps filenames?',
- global: false
- })
- .option('exclude-node-modules', {
- default: true,
- type: 'boolean',
- describe: 'whether or not to exclude all node_module folders (i.e. **/node_modules/**) by default',
- global: false
- })
- .option('include', {
- alias: 'n',
- default: [],
- describe: 'a list of specific files that should be covered, glob patterns are supported',
- global: false
- })
- .option('cwd', {
- describe: 'working directory used when resolving paths',
- default: cwd
- })
- .option('require', {
- alias: 'i',
- default: [],
- describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., @babel/register, @babel/polyfill',
- global: false
- })
- .option('eager', {
- default: false,
- type: 'boolean',
- describe: 'instantiate the instrumenter at startup (see https://git.io/vMKZ9)',
- global: false
- })
- .option('cache', {
- alias: 'c',
- default: true,
- type: 'boolean',
- describe: 'cache instrumentation results for improved performance',
- global: false
- })
- .option('cache-dir', {
- describe: 'explicitly set location for instrumentation cache',
- global: false
- })
- .option('babel-cache', {
- default: false,
- type: 'boolean',
- describe: 'cache babel transpilation results for improved performance',
- global: false
- })
- .option('es-modules', {
- default: true,
- type: 'boolean',
- describe: 'tell the instrumenter to treat files as ES Modules',
- global: false
- })
- .option('extension', {
- alias: 'e',
- default: ['.cjs', '.mjs', '.ts', '.tsx', '.jsx'],
- describe: 'a list of extensions that nyc should handle in addition to .js',
- global: false
- })
- .option('check-coverage', {
- type: 'boolean',
- default: false,
- describe: 'check whether coverage is within thresholds provided',
- global: false
- })
- .option('branches', {
- default: 0,
- description: 'what % of branches must be covered?',
- global: false
- })
- .option('functions', {
- default: 0,
- description: 'what % of functions must be covered?',
- global: false
- })
- .option('lines', {
- default: 90,
- description: 'what % of lines must be covered?',
- global: false
- })
- .option('statements', {
- default: 0,
- description: 'what % of statements must be covered?',
- global: false
- })
- .option('source-map', {
- default: true,
- type: 'boolean',
- description: 'should nyc detect and handle source maps?',
- global: false
- })
- .option('per-file', {
- default: false,
- type: 'boolean',
- description: 'check thresholds per file',
- global: false
- })
- .option('produce-source-map', {
- default: false,
- type: 'boolean',
- description: "should nyc's instrumenter produce source maps?",
- global: false
- })
- .option('compact', {
- default: true,
- type: 'boolean',
- description: 'should the output be compacted?'
- })
- .option('preserve-comments', {
- default: true,
- type: 'boolean',
- description: 'should comments be preserved in the output?'
- })
- .option('instrument', {
- default: true,
- type: 'boolean',
- description: 'should nyc handle instrumentation?',
- global: false
- })
- .option('hook-require', {
- default: true,
- type: 'boolean',
- description: 'should nyc wrap require?',
- global: false
- })
- .option('hook-run-in-context', {
- default: false,
- type: 'boolean',
- description: 'should nyc wrap vm.runInContext?',
- global: false
- })
- .option('hook-run-in-this-context', {
- default: false,
- type: 'boolean',
- description: 'should nyc wrap vm.runInThisContext?',
- global: false
- })
- .option('show-process-tree', {
- describe: 'display the tree of spawned processes',
- default: false,
- type: 'boolean',
- global: false
- })
- .option('use-spawn-wrap', {
- describe: 'use spawn-wrap instead of setting process.env.NODE_OPTIONS',
- default: false,
- type: 'boolean',
- global: false
- })
- .option('clean', {
- describe: 'should the .nyc_output folder be cleaned before executing tests',
- default: true,
- type: 'boolean',
- global: false
- })
- .option('nycrc-path', {
- description: 'specify a different .nycrc path',
- global: false
- })
- .option('temp-dir', {
- alias: 't',
- describe: 'directory to output raw coverage information to',
- default: './.nyc_output',
- global: false
- })
- .option('temp-directory', {
- hidden: true,
- global: false
- })
- .option('skip-empty', {
- describe: 'don\'t show empty files (no lines of code) in report',
- default: false,
- type: 'boolean',
- global: false
- })
- .option('skip-full', {
- describe: 'don\'t show files with 100% statement, branch, and function coverage',
- default: false,
- type: 'boolean',
- global: false
- })
+ .showHidden(false)
+
+ setupOptions(yargs, null, cwd)
+
+ yargs
.example('$0 npm test', 'instrument your tests with coverage')
.example('$0 --require @babel/register npm test', 'instrument your tests with coverage and transpile with Babel')
.example('$0 report --reporter=text-lcov', 'output lcov report after running your tests')
diff --git a/package-lock.json b/package-lock.json
index 38b3f93de..228083443 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -121,9 +121,9 @@
}
},
"@istanbuljs/schema": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.0.tgz",
- "integrity": "sha512-juX6y33AgnEkto3n3AhViX70IP19N3x6Np1eIikPcH5ATqj8ntLWD3MsOF5ohg0h+mAv6IFUfABBHjmve9dncg=="
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.1.tgz",
+ "integrity": "sha512-Dt63B/JcXUxwnngdR8BYqSuQBX0HVXgLZtGMsKAAIQLe0whQdypOjsuqcSf8HR5M00/L8NuRC/+dZb6rEc+b5g=="
},
"JSONStream": {
"version": "1.3.5",
diff --git a/package.json b/package.json
index ff2f0a10f..ad9ae4d09 100644
--- a/package.json
+++ b/package.json
@@ -69,9 +69,11 @@
"license": "ISC",
"dependencies": {
"@istanbuljs/load-nyc-config": "^1.0.0-alpha.0",
+ "@istanbuljs/schema": "^0.1.1",
"caching-transform": "^4.0.0",
"convert-source-map": "^1.6.0",
"cp-file": "^7.0.0",
+ "decamelize": "^1.2.0",
"find-cache-dir": "^3.0.0",
"find-up": "^4.1.0",
"foreground-child": "^2.0.0",
diff --git a/test/config.js b/test/config.js
index 62b440c87..881ac8459 100644
--- a/test/config.js
+++ b/test/config.js
@@ -35,7 +35,7 @@ test("ignores 'include' option if it's falsy or []", async t => {
test("ignores 'exclude' option if it's falsy", async t => {
const nyc = new NYC(await parseArgv(path.resolve(__dirname, './fixtures/conf-empty')))
- t.strictEqual(nyc.exclude.exclude.length, 15)
+ t.strictEqual(nyc.exclude.exclude.length, 18)
})
test("allows for empty 'exclude'", async t => {
diff --git a/test/nyc-integration.js b/test/nyc-integration.js
index 278d35afa..dc630afc5 100644
--- a/test/nyc-integration.js
+++ b/test/nyc-integration.js
@@ -570,6 +570,7 @@ t.test('combines multiple coverage reports', async t => {
})
const mergedCoverage = require('./fixtures/cli/coverage')
+ console.log(Object.keys(mergedCoverage))
// the combined reports should have 100% function
// branch and statement coverage.
t.strictDeepEqual(
diff --git a/test/source-map-support.js b/test/source-map-support.js
index 3f2ac11b5..3e4beee18 100644
--- a/test/source-map-support.js
+++ b/test/source-map-support.js
@@ -14,7 +14,9 @@ require('source-map-support').install({ hookRequire: true })
t.beforeEach(resetState)
t.test('handles stack traces', async t => {
- const nyc = new NYC(await parseArgv(undefined, ['--produce-source-map']))
+ const nyc = new NYC(await parseArgv(undefined, [
+ '--produce-source-map=true'
+ ]))
await nyc.reset()
nyc.wrap()
@@ -24,7 +26,9 @@ t.test('handles stack traces', async t => {
})
t.test('does not handle stack traces when disabled', async t => {
- const nyc = new NYC(await parseArgv())
+ const nyc = new NYC(await parseArgv(undefined, [
+ '--produce-source-map=false'
+ ]))
await nyc.reset()
nyc.wrap()