Repository: istanbuljs/nyc
Pull request #1195 (2019-10-07 04:17:20)

chore: 100% coverage

coveralls: 
[![Coverage Status](https://coveralls.io/builds/26145742/badge)](https://coveralls.io/builds/26145742)

Coverage increased (+0.2%) to 100.0% when pulling **1210fe064cced9b8a5e47a78feb85e2ccfdecc16 on coreyfarrell:cov-100** into **fd40d49331665d936b86f30e9a873ba80071b770 on istanbuljs:master**.


Patch:
diff --git a/bin/nyc.js b/bin/nyc.js
index 3760dbc..5f295ab 100755
--- a/bin/nyc.js
+++ b/bin/nyc.js
@@ -43,6 +43,7 @@ async function main () {
     NYC_CWD: process.cwd()
   }
 
+  /* istanbul ignore else */
   if (argv['babel-cache'] === false) {
     // babel's cache interferes with some configurations, so is
     // disabled by default. opt in by setting babel-cache=true.
@@ -103,6 +104,6 @@ async function main () {
 
 /* istanbul ignore next: the error branch should be unreachable */
 main().catch(error => {
-  console.log('nyc error:', error)
+  console.error(error.message)
   process.exit(1)
 })
diff --git a/index.js b/index.js
index c51bf75..92e22d5 100755
--- a/index.js
+++ b/index.js
@@ -48,8 +48,7 @@ function coverageFinder () {
 
 class NYC {
   constructor (config) {
-    config = config || {}
-    this.config = config
+    this.config = { ...config }
 
     this.subprocessBin = config.subprocessBin || path.resolve(__dirname, './bin/nyc.js')
     this._tempDirectory = config.tempDirectory || config.tempDir || './.nyc_output'
@@ -151,7 +150,7 @@ class NYC {
       compact: this.config.compact,
       preserveComments: this.config.preserveComments,
       esModules: this.config.esModules,
-      plugins: this.config.parserPlugins
+      parserPlugins: this.config.parserPlugins
     })
   }
 
@@ -365,7 +364,6 @@ class NYC {
 
   writeCoverageFile () {
     var coverage = coverageFinder()
-    if (!coverage) return
 
     // Remove any files that should be excluded but snuck into the coverage
     Object.keys(coverage).forEach(function (absFile) {
diff --git a/lib/commands/instrument.js b/lib/commands/instrument.js
index 256e40d..f88cccf 100644
--- a/lib/commands/instrument.js
+++ b/lib/commands/instrument.js
@@ -1,6 +1,7 @@
 const NYC = require('../../index.js')
 const path = require('path')
 const { promisify } = require('util')
+const resolveFrom = require('resolve-from')
 const rimraf = promisify(require('rimraf'))
 const { cliWrapper, setupOptions } = require('./helpers.js')
 
@@ -49,5 +50,12 @@ exports.handler = cliWrapper(async argv => {
   }
 
   const nyc = new NYC(argv)
+  if (!argv.useSpawnWrap) {
+    nyc.require.forEach(requireModule => {
+      const mod = resolveFrom.silent(nyc.cwd, requireModule) || requireModule
+      require(mod)
+    })
+  }
+
   await nyc.instrumentAllFiles(argv.input, argv.output)
 })
diff --git a/lib/fs-promises.js b/lib/fs-promises.js
index c99316a..b67ebb1 100644
--- a/lib/fs-promises.js
+++ b/lib/fs-promises.js
@@ -44,6 +44,7 @@ const fns = [
   'writeFile'
 ]
 fns.forEach(fn => {
+  /* istanbul ignore else: all functions exist on OSX */
   if (fs[fn]) {
     module.exports[fn] = promisify(fs[fn])
   }
diff --git a/lib/instrumenters/istanbul.js b/lib/instrumenters/istanbul.js
index 2946218..1793f0c 100644
--- a/lib/instrumenters/istanbul.js
+++ b/lib/instrumenters/istanbul.js
@@ -5,9 +5,6 @@ function InstrumenterIstanbul (options) {
   const convertSourceMap = require('convert-source-map')
   const mergeSourceMap = require('merge-source-map')
 
-  const { plugins } = options
-  const configPlugins = plugins ? { plugins } : {}
-
   const instrumenter = createInstrumenter({
     autoWrap: true,
     coverageVariable: '__coverage__',
@@ -17,7 +14,7 @@ function InstrumenterIstanbul (options) {
     produceSourceMap: options.produceSourceMap,
     ignoreClassMethods: options.ignoreClassMethods,
     esModules: options.esModules,
-    ...configPlugins
+    parserPlugins: options.parserPlugins
   })
 
   return {
diff --git a/lib/wrap.js b/lib/wrap.js
index cb32133..3f18f8a 100644
--- a/lib/wrap.js
+++ b/lib/wrap.js
@@ -1,9 +1,10 @@
 const NYC = require('../index.js')
 
-let config = {}
-if (process.env.NYC_CONFIG) {
-  config = JSON.parse(process.env.NYC_CONFIG)
-}
+const config = JSON.parse(
+  process.env.NYC_CONFIG ||
+  /* istanbul ignore next */ '{}'
+)
+
 config.isChildProcess = true
 
 config._processInfo = {
@@ -18,11 +19,7 @@ if (process.env.NYC_PROCESSINFO_EXTERNAL_ID) {
 }
 
 if (process.env.NYC_CONFIG_OVERRIDE) {
-  const override = JSON.parse(process.env.NYC_CONFIG_OVERRIDE)
-  config = {
-    ...config,
-    ...override
-  }
+  Object.assign(config, JSON.parse(process.env.NYC_CONFIG_OVERRIDE))
   process.env.NYC_CONFIG = JSON.stringify(config)
 }
 
diff --git a/nyc.config.js b/nyc.config.js
new file mode 100644
index 0000000..eedda3d
--- /dev/null
+++ b/nyc.config.js
@@ -0,0 +1,22 @@
+'use strict'
+
+const isWindows = require('is-windows')()
+
+module.exports = {
+  exclude: [
+    'coverage',
+    'self-coverage',
+    'test/fixtures/coverage.js',
+    'test/build/*',
+    'test/src/*',
+    'test/nyc.js',
+    'test/process-args.js',
+    'test/fixtures/_generateCoverage.js'
+  ],
+  /* Unknown why we don't get 100% coverage on Windows. */
+  'check-coverage': !isWindows,
+  branches: 100,
+  functions: 100,
+  lines: 100,
+  statements: 100
+}
diff --git a/package.json b/package.json
index ad9ae4d..8a68cbb 100644
--- a/package.json
+++ b/package.json
@@ -22,19 +22,6 @@
     "bin/*.js",
     "lib/**/*.js"
   ],
-  "nyc": {
-    "exclude": [
-      "node_modules",
-      "coverage",
-      "self-coverage",
-      "test/fixtures/coverage.js",
-      "test/build/*",
-      "test/src/*",
-      "test/nyc.js",
-      "test/process-args.js",
-      "test/fixtures/_generateCoverage.js"
-    ]
-  },
   "standard": {
     "ignore": [
       "**/fixtures/**",


Test patch:
diff --git a/tap-snapshots/test-nyc-integration.js-TAP.test.js b/tap-snapshots/test-nyc-integration.js-TAP.test.js
index b026b05..7e4f26d 100644
--- a/tap-snapshots/test-nyc-integration.js-TAP.test.js
+++ b/tap-snapshots/test-nyc-integration.js-TAP.test.js
@@ -930,6 +930,16 @@ exports[`test/nyc-integration.js TAP reports error if input is not a directory >
 
 `
 
+exports[`test/nyc-integration.js TAP run-in-context provide coverage for vm.runInContext > stdout 1`] = `
+---------------|---------|----------|---------|---------|-------------------
+File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
+---------------|---------|----------|---------|---------|-------------------
+All files      |     100 |      100 |     100 |     100 |                   
+ in-context.js |     100 |      100 |     100 |     100 |                   
+---------------|---------|----------|---------|---------|-------------------
+
+`
+
 exports[`test/nyc-integration.js TAP setting instrument to "false" configures noop instrumenter > must match snapshot 1`] = `
 [
   [
diff --git a/test/fixtures/hooks/run-in-context.js b/test/fixtures/hooks/run-in-context.js
new file mode 100644
index 0000000..653a45d
--- /dev/null
+++ b/test/fixtures/hooks/run-in-context.js
@@ -0,0 +1,9 @@
+'use strict'
+const path = require('path')
+const vm = require('vm')
+
+vm.runInContext(
+  '(() => 10)();',
+  vm.createContext({}),
+  path.resolve(__dirname, 'in-context.js')
+)
diff --git a/test/fixtures/nyc.config.js b/test/fixtures/nyc.config.js
new file mode 100644
index 0000000..f925162
--- /dev/null
+++ b/test/fixtures/nyc.config.js
@@ -0,0 +1,4 @@
+'use strict'
+
+// This just blocks fixtures from seeing the root nyc.config.js
+module.exports = {}
diff --git a/test/fixtures/parser-plugins/no-plugins.json b/test/fixtures/parser-plugins/no-plugins.json
new file mode 100644
index 0000000..e95c94f
--- /dev/null
+++ b/test/fixtures/parser-plugins/no-plugins.json
@@ -0,0 +1,3 @@
+{
+  "parser-plugins": []
+}
diff --git a/test/fixtures/parser-plugins/package.json b/test/fixtures/parser-plugins/package.json
new file mode 100644
index 0000000..d655f2e
--- /dev/null
+++ b/test/fixtures/parser-plugins/package.json
@@ -0,0 +1,7 @@
+{
+  "nyc": {
+    "parser-plugins": [
+      "v8intrinsic"
+    ]
+  }
+}
diff --git a/test/fixtures/parser-plugins/v8.js b/test/fixtures/parser-plugins/v8.js
new file mode 100644
index 0000000..74c572a
--- /dev/null
+++ b/test/fixtures/parser-plugins/v8.js
@@ -0,0 +1,2 @@
+function fn() {}
+%GetOptimizationStatus(fn)
diff --git a/test/nyc-integration.js b/test/nyc-integration.js
index dc630af..5fd43a1 100644
--- a/test/nyc-integration.js
+++ b/test/nyc-integration.js
@@ -167,6 +167,16 @@ t.test('hooks provide coverage for requireJS and AMD modules', t => testSuccess(
   cwd: path.resolve(__dirname, './fixtures/hooks')
 }))
 
+t.test('run-in-context provide coverage for vm.runInContext', t => testSuccess(t, {
+  args: [
+    '--hook-run-in-context',
+    '--hook-require=false',
+    process.execPath,
+    './run-in-context.js'
+  ],
+  cwd: path.resolve(__dirname, './fixtures/hooks')
+}))
+
 t.test('does not interpret args intended for instrumented bin', async t => {
   const { status, stderr, stdout } = await runNYC({
     tempDir: t.tempDir,
@@ -215,6 +225,18 @@ t.test('nyc instrument single file to console', async t => {
   t.match(originalText.stdout, `path:${JSON.stringify(path.resolve(fixturesCLI, 'half-covered.js'))}`)
 })
 
+t.test('nyc instrument disabled instrument', async t => {
+  const { status, stderr, stdout } = await runNYC({
+    tempDir: t.tempDir,
+    args: ['instrument', '--instrument=false', 'half-covered.js']
+  })
+
+  t.is(status, 0)
+  t.is(stderr, '')
+  t.match(stdout, 'var a = 0')
+  t.notMatch(stdout, 'cov_')
+})
+
 t.test('nyc instrument a directory of files', async t => {
   const { status, stderr, originalText } = await runNYC({
     tempDir: t.tempDir,
@@ -570,7 +592,6 @@ 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(
@@ -600,3 +621,48 @@ t.test('--all instruments unknown extensions as js', t => testSuccess(t, {
   cwd: path.resolve(fixturesCLI, '../conf-multiple-extensions'),
   args: ['--all', process.execPath, './run.js']
 }))
+
+t.test('instrument with invalid --require fails when using node-preload', async t => {
+  const { status, stderr, stdout } = await runNYC({
+    tempDir: t.tempDir,
+    args: [
+      '--require=@istanbuljs/this-module-does-not-exist',
+      'instrument',
+      './skip-full.js'
+    ]
+  })
+
+  t.is(status, 1)
+  t.match(stderr, /Cannot find module '@istanbuljs\/this-module-does-not-exist'/)
+  t.is(stdout, '')
+})
+
+t.test('invalid --require fails when using node-preload', async t => {
+  const { status, stderr, stdout } = await runNYC({
+    tempDir: t.tempDir,
+    args: [
+      '--require=@istanbuljs/this-module-does-not-exist',
+      './skip-full.js'
+    ]
+  })
+
+  t.is(status, 1)
+  t.match(stderr, /Cannot find module '@istanbuljs\/this-module-does-not-exist'/)
+  t.is(stdout, '')
+})
+
+t.test('invalid --require fails when using spawn-wrap', async t => {
+  const { status, stderr, stdout } = await runNYC({
+    tempDir: t.tempDir,
+    args: [
+      '--use-spawn-wrap=true',
+      '--require=@istanbuljs/this-module-does-not-exist',
+      'instrument',
+      './skip-full.js'
+    ]
+  })
+
+  t.is(status, 1)
+  t.match(stderr, /Cannot find module '@istanbuljs\/this-module-does-not-exist'/)
+  t.is(stdout, '')
+})
diff --git a/test/parser-plugins.js b/test/parser-plugins.js
new file mode 100644
index 0000000..c375e61
--- /dev/null
+++ b/test/parser-plugins.js
@@ -0,0 +1,29 @@
+'use strict'
+
+const path = require('path')
+
+const t = require('tap')
+
+const { runNYC } = require('./helpers')
+
+const cwd = path.resolve(__dirname, './fixtures/parser-plugins')
+
+t.test('parser plugin set', async t => {
+  const { status, stdout, stderr } = await runNYC({
+    args: ['instrument', 'v8.js'],
+    cwd
+  })
+  t.strictEqual(status, 0)
+  t.strictEqual(stderr, '')
+  t.match(stdout, /function cov_/)
+})
+
+t.test('parser plugin unset', async t => {
+  const { status, stdout, stderr } = await runNYC({
+    args: ['instrument', '--nycrc-path=no-plugins.json', 'v8.js'],
+    cwd
+  })
+  t.strictEqual(status, 0)
+  t.strictEqual(stderr, '')
+  t.notMatch(stdout, /function cov_/)
+})
diff --git a/test/process-args.js b/test/process-args.js
index 4b0cf43..ca3a37d 100644
--- a/test/process-args.js
+++ b/test/process-args.js
@@ -5,7 +5,7 @@ const yargs = require('yargs/yargs')
 
 const processArgs = require('../self-coverage/lib/process-args')
 
-const nycBin = require.resolve('../bin/nyc.js')
+const nycBin = require.resolve('../self-coverage/bin/nyc.js')
 
 test('hideInstrumenterArgs removes dashed options that proceed bin', async t => {
   process.argv = [