Repository: istanbuljs/nyc
Pull request #1026 (2019-03-13 01:01:20)

feat: Pass `extension` to test-exclude, use TestExclude.globSync.
BREAKING CHANGE: The logic involving include/exclude processing has
changed.  Results should be verified to ensure all desired sources have
coverage data.

coreyfarrell: The testing changes are less significant than it looks.  The tests were actually checking for results that were impossible in practice.  Although `shouldInstrument('file-without-extension')` could previously return `true`, the file would never have been instrumented because it has no extension for the require hook.
coveralls: 
[![Coverage Status](https://coveralls.io/builds/22144095/badge)](https://coveralls.io/builds/22144095)

Coverage increased (+0.1%) to 93.898% when pulling **651eced9bc7362ec1f81c8e3e451512a2d14a533 on coreyfarrell:updated-test-exclude** into **d8f28e91fb6a1aff498846b81db1b1ceefe9728b on istanbuljs:master**.

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

Coverage increased (+0.1%) to 93.898% when pulling **651eced9bc7362ec1f81c8e3e451512a2d14a533 on coreyfarrell:updated-test-exclude** into **d8f28e91fb6a1aff498846b81db1b1ceefe9728b on istanbuljs:master**.

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

Coverage increased (+0.1%) to 93.898% when pulling **651eced9bc7362ec1f81c8e3e451512a2d14a533 on coreyfarrell:updated-test-exclude** into **d8f28e91fb6a1aff498846b81db1b1ceefe9728b on istanbuljs:master**.

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

Coverage increased (+0.1%) to 93.898% when pulling **651eced9bc7362ec1f81c8e3e451512a2d14a533 on coreyfarrell:updated-test-exclude** into **d8f28e91fb6a1aff498846b81db1b1ceefe9728b on istanbuljs:master**.


Patch:
diff --git a/index.js b/index.js
index 296733a..36863a0 100755
--- a/index.js
+++ b/index.js
@@ -7,7 +7,6 @@ const cachingTransform = require('caching-transform')
 const util = require('util')
 const findCacheDir = require('find-cache-dir')
 const fs = require('fs')
-const glob = require('glob')
 const Hash = require('./lib/hash')
 const libCoverage = require('istanbul-lib-coverage')
 const libHook = require('istanbul-lib-hook')
@@ -42,6 +41,7 @@ function NYC (config) {
   this._reportDir = config.reportDir || 'coverage'
   this._sourceMap = typeof config.sourceMap === 'boolean' ? config.sourceMap : true
   this._showProcessTree = config.showProcessTree || false
+  this._buildProcessTree = this._showProcessTree || config.buildProcessTree
   this._eagerInstantiation = config.eager || false
   this.cwd = config.cwd || process.cwd()
   this.reporter = arrify(config.reporter || 'text')
@@ -49,10 +49,16 @@ function NYC (config) {
   this.cacheDirectory = (config.cacheDir && path.resolve(config.cacheDir)) || findCacheDir({ name: 'nyc', cwd: this.cwd })
   this.cache = Boolean(this.cacheDirectory && config.cache)
 
+  this.extensions = arrify(config.extension)
+    .concat('.js')
+    .map(ext => ext.toLowerCase())
+    .filter((item, pos, arr) => arr.indexOf(item) === pos)
+
   this.exclude = testExclude({
     cwd: this.cwd,
     include: config.include,
-    exclude: config.exclude
+    exclude: config.exclude,
+    extension: this.extensions
   })
 
   this.sourceMaps = new SourceMaps({
@@ -63,17 +69,10 @@ function NYC (config) {
   // require extensions can be provided as config in package.json.
   this.require = arrify(config.require)
 
-  this.extensions = arrify(config.extension).concat('.js').map(function (ext) {
-    return ext.toLowerCase()
-  }).filter(function (item, pos, arr) {
-    // avoid duplicate extensions
-    return arr.indexOf(item) === pos
-  })
-
-  this.transforms = this.extensions.reduce(function (transforms, ext) {
+  this.transforms = this.extensions.reduce((transforms, ext) => {
     transforms[ext] = this._createTransform(ext)
     return transforms
-  }.bind(this), {})
+  }, {})
 
   this.hookRequire = config.hookRequire
   this.hookRunInContext = config.hookRunInContext
@@ -226,14 +225,7 @@ NYC.prototype.instrumentAllFiles = function (input, output, cb) {
 }
 
 NYC.prototype.walkAllFiles = function (dir, visitor) {
-  var pattern = null
-  if (this.extensions.length === 1) {
-    pattern = '**/*' + this.extensions[0]
-  } else {
-    pattern = '**/*{' + this.extensions.join() + '}'
-  }
-
-  glob.sync(pattern, { cwd: dir, nodir: true, ignore: this.exclude.exclude }).forEach(function (filename) {
+  this.exclude.globSync(dir).forEach(filename => {
     visitor(filename)
   })
 }
@@ -325,7 +317,7 @@ NYC.prototype.createTempDirectory = function () {
   mkdirp.sync(this.tempDirectory())
   if (this.cache) mkdirp.sync(this.cacheDirectory)
 
-  if (this._showProcessTree) {
+  if (this._buildProcessTree) {
     mkdirp.sync(this.processInfoDirectory())
   }
 }
@@ -384,7 +376,7 @@ NYC.prototype.writeCoverageFile = function () {
     'utf-8'
   )
 
-  if (!this._showProcessTree) {
+  if (!this._buildProcessTree) {
     return
   }
 
diff --git a/lib/config-util.js b/lib/config-util.js
index 37f7267..71d492a 100644
--- a/lib/config-util.js
+++ b/lib/config-util.js
@@ -224,6 +224,12 @@ Config.buildYargs = function (cwd) {
       type: 'boolean',
       global: false
     })
+    .option('build-process-tree', {
+      describe: 'create files for the tree of spawned processes',
+      default: false,
+      type: 'boolean',
+      global: false
+    })
     .option('clean', {
       describe: 'should the .nyc_output folder be cleaned before executing tests',
       default: true,
diff --git a/package.json b/package.json
index a53a03b..14d6caf 100644
--- a/package.json
+++ b/package.json
@@ -74,7 +74,6 @@
     "find-cache-dir": "^2.0.0",
     "find-up": "^3.0.0",
     "foreground-child": "^1.5.6",
-    "glob": "^7.1.3",
     "istanbul-lib-coverage": "^2.0.4",
     "istanbul-lib-hook": "^2.0.4",
     "istanbul-lib-instrument": "^3.1.1",
@@ -96,6 +95,7 @@
     "any-path": "^1.3.0",
     "chai": "^4.2.0",
     "coveralls": "^3.0.3",
+    "glob": "^7.1.3",
     "is-windows": "^1.0.2",
     "lodash": "^4.17.11",
     "newline-regex": "^0.2.1",


Test patch:
diff --git a/test/fixtures/_generateReport.js b/test/fixtures/_generateReport.js
index 09b8b96..4da8972 100644
--- a/test/fixtures/_generateReport.js
+++ b/test/fixtures/_generateReport.js
@@ -10,7 +10,7 @@ var _ = require('lodash')
 var rimraf = require('rimraf')
 var sourceMapFixtures = require('source-map-fixtures')
 
-var NYC = require('../../')
+var NYC = require('../../self-coverage')
 
 // Load source map fixtures.
 var fixtures = {
diff --git a/test/fixtures/package.json b/test/fixtures/package.json
index 13746bf..0a5f68a 100644
--- a/test/fixtures/package.json
+++ b/test/fixtures/package.json
@@ -9,8 +9,8 @@
   },
   "nyc": {
     "exclude": [
-      "**/blarg",
-      "**/blerg"
+      "**/blarg.js",
+      "**/blerg.js"
     ]
   }
 }
diff --git a/test/nyc-index.js b/test/nyc-index.js
index 00f7f8f..f7b549e 100644
--- a/test/nyc-index.js
+++ b/test/nyc-index.js
@@ -2,17 +2,12 @@
 
 require('source-map-support').install({ hookRequire: true })
 
+const fs = require('fs')
 const _ = require('lodash')
 const ap = require('any-path')
-const configUtil = require('../lib/config-util')
-const fs = require('fs')
 
-let NYC
-try {
-  NYC = require('../index.covered.js')
-} catch (e) {
-  NYC = require('../')
-}
+const configUtil = require('../self-coverage/lib/config-util')
+const NYC = require('../self-coverage')
 // we test exit handlers in nyc-integration.js.
 NYC.prototype._wrapExit = () => {}
 
@@ -21,12 +16,14 @@ const rimraf = require('rimraf')
 const isWindows = require('is-windows')()
 const spawn = require('child_process').spawn
 const fixtures = path.resolve(__dirname, './fixtures')
-const bin = path.resolve(__dirname, '../bin/nyc')
+const bin = path.resolve(__dirname, '../self-coverage/bin/nyc')
 const resetState = require('./lib/reset-state')
 
 require('chai').should()
 require('tap').mochaGlobals()
 
+const transpileHook = path.resolve(process.cwd(), './test/fixtures/transpile-hook')
+
 describe('nyc', function () {
   beforeEach(resetState)
 
@@ -101,9 +98,9 @@ describe('nyc', function () {
       ]))
 
       // nyc always excludes "node_modules/**"
-      nyc.exclude.shouldInstrument('/cwd/foo', 'foo').should.equal(true)
-      nyc.exclude.shouldInstrument('/cwd/node_modules/bar', 'node_modules/bar').should.equal(false)
-      nyc.exclude.shouldInstrument('/cwd/foo/node_modules/bar', 'foo/node_modules/bar').should.equal(false)
+      nyc.exclude.shouldInstrument('/cwd/foo.js', 'foo.js').should.equal(true)
+      nyc.exclude.shouldInstrument('/cwd/node_modules/bar.js', 'node_modules/bar.js').should.equal(false)
+      nyc.exclude.shouldInstrument('/cwd/foo/node_modules/bar.js', 'foo/node_modules/bar.js').should.equal(false)
       nyc.exclude.shouldInstrument('/cwd/test.js', 'test.js').should.equal(false)
       nyc.exclude.shouldInstrument('/cwd/testfoo.js', 'testfoo.js').should.equal(true)
       nyc.exclude.shouldInstrument('/cwd/test-foo.js', 'test-foo.js').should.equal(false)
@@ -118,22 +115,22 @@ describe('nyc', function () {
       var nyc = new NYC(configUtil.buildYargs(fixtures).parse())
 
       // fixtures/package.json configures excludes: "blarg", "blerg"
-      nyc.exclude.shouldInstrument('blarg', 'blarg').should.equal(false)
+      nyc.exclude.shouldInstrument('blarg.js', 'blarg.js').should.equal(false)
       nyc.exclude.shouldInstrument('blarg/foo.js', 'blarg/foo.js').should.equal(false)
-      nyc.exclude.shouldInstrument('blerg', 'blerg').should.equal(false)
-      nyc.exclude.shouldInstrument('./blerg', './blerg').should.equal(false)
-      nyc.exclude.shouldInstrument('./blerg', '.\\blerg').should.equal(false)
+      nyc.exclude.shouldInstrument('blerg.js', 'blerg.js').should.equal(false)
+      nyc.exclude.shouldInstrument('./blerg.js', './blerg.js').should.equal(false)
+      nyc.exclude.shouldInstrument('./blerg.js', '.\\blerg.js').should.equal(false)
     })
 
     it('should exclude outside of the current working directory', function () {
       var nyc = new NYC(configUtil.buildYargs('/cwd/foo/').parse())
-      nyc.exclude.shouldInstrument('/cwd/bar', '../bar').should.equal(false)
+      nyc.exclude.shouldInstrument('/cwd/bar.js', '../bar.js').should.equal(false)
     })
 
     it('should not exclude if the current working directory is inside node_modules', function () {
       var nyc = new NYC(configUtil.buildYargs('/cwd/node_modules/foo/').parse())
-      nyc.exclude.shouldInstrument('/cwd/node_modules/foo/bar', './bar').should.equal(true)
-      nyc.exclude.shouldInstrument('/cwd/node_modules/foo/bar', '.\\bar').should.equal(true)
+      nyc.exclude.shouldInstrument('/cwd/node_modules/foo/bar.js', './bar.js').should.equal(true)
+      nyc.exclude.shouldInstrument('/cwd/node_modules/foo/bar.js', '.\\bar.js').should.equal(true)
     })
 
     it('allows files to be explicitly included, rather than excluded', function () {
@@ -392,7 +389,7 @@ describe('nyc', function () {
         'utf-8'
       )
 
-      var nyc = (new NYC(configUtil.buildYargs(fixtures).parse(['--require', './test/fixtures/transpile-hook'])))
+      var nyc = (new NYC(configUtil.buildYargs(fixtures).parse(['--require', transpileHook])))
       nyc.reset()
       nyc.addAllFiles()
 
@@ -418,7 +415,7 @@ describe('nyc', function () {
       )
 
       var nyc = (new NYC(configUtil.buildYargs(fixtures).parse([
-        '--require=./test/fixtures/transpile-hook',
+        `--require=${transpileHook}`,
         '--extension=.do-not-transpile',
         '--include=needs-transpile.do-not-transpile'
       ])))
@@ -438,7 +435,7 @@ describe('nyc', function () {
     )
 
     var nyc = (new NYC(configUtil.buildYargs(fixtures).parse([
-      '--require=./test/fixtures/transpile-hook',
+      `--require=${transpileHook}`,
       '--extension=.whatever'
     ])))
 
diff --git a/test/nyc-integration.js b/test/nyc-integration.js
index 95fc8d3..8124f67 100644
--- a/test/nyc-integration.js
+++ b/test/nyc-integration.js
@@ -935,6 +935,47 @@ describe('the nyc cli', function () {
     })
   })
 
+  describe('--build-process-tree', function () {
+    it('builds, but does not display, a tree of spawned processes', function (done) {
+      var args = [bin, '--build-process-tree', process.execPath, 'selfspawn-fibonacci.js', '5']
+
+      var proc = spawn(process.execPath, args, {
+        cwd: fixturesCLI,
+        env: env
+      })
+
+      var stdout = ''
+      proc.stdout.setEncoding('utf8')
+      proc.stdout.on('data', function (chunk) {
+        stdout += chunk
+      })
+
+      proc.on('close', function (code) {
+        code.should.equal(0)
+        stdout.should.not.match(new RegExp('└─'))
+        fs.statSync(path.resolve(fixturesCLI, '.nyc_output', 'processinfo'))
+        done()
+      })
+    })
+
+    it('doesn’t create the temp directory for process info files when not present', function (done) {
+      var args = [bin, process.execPath, 'selfspawn-fibonacci.js', '5']
+
+      var proc = spawn(process.execPath, args, {
+        cwd: fixturesCLI,
+        env: env
+      })
+
+      proc.on('exit', function (code) {
+        code.should.equal(0)
+        fs.stat(path.resolve(fixturesCLI, '.nyc_output', 'processinfo'), function (err, stat) {
+          err.code.should.equal('ENOENT')
+          done()
+        })
+      })
+    })
+  })
+
   describe('--temp-dir', function () {
     beforeEach(() => {
       rimraf.sync(path.resolve(fixturesCLI, '.nyc_output'))
diff --git a/test/process-args.js b/test/process-args.js
index 4509bc5..fe5a2f8 100644
--- a/test/process-args.js
+++ b/test/process-args.js
@@ -3,7 +3,7 @@
 require('chai').should()
 require('tap').mochaGlobals()
 
-const processArgs = require('../lib/process-args')
+const processArgs = require('../self-coverage/lib/process-args')
 
 describe('process-args', function () {
   describe('hideInstrumenterArgs', function () {
diff --git a/test/src/nyc-tap.js b/test/src/nyc-tap.js
index 1cf3843..9cf644c 100644
--- a/test/src/nyc-tap.js
+++ b/test/src/nyc-tap.js
@@ -2,12 +2,12 @@
 
 require('source-map-support').install({ hookRequire: true })
 
+const fs = require('fs')
 const _ = require('lodash')
 const ap = require('any-path')
-const configUtil = require('../../lib/config-util')
-const fs = require('fs')
 const enableCache = false
 
+const configUtil = require('../../self-coverage/lib/config-util')
 const _NYC = require('../../self-coverage')
 
 function NYC (opts) {