Skip to content

Commit f2017de

Browse files
committed
Add support for configurable file extensions
1 parent 89098db commit f2017de

File tree

9 files changed

+128
-10
lines changed

9 files changed

+128
-10
lines changed

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,23 @@ of the pre-transpiled code. You'll have to configure your custom require hook
5959
to inline the source map in the transpiled code. For Babel that means setting
6060
the `sourceMaps` option to `inline`.
6161

62+
## Support For Custom File Extensions (.jsx, .es6)
63+
Supporting file extensions can be configured through either the configuration arguments or with the `nyc` config section in `package.json`.
64+
65+
```shell
66+
nyc --extension .jsx --extension .es6 npm test
67+
```
68+
69+
```json
70+
{"nyc": {
71+
"extensions": [
72+
".jsx",
73+
".es6"
74+
]
75+
}
76+
}
77+
```
78+
6279
## Checking Coverage
6380

6481
nyc exposes istanbul's check-coverage tool. After running your tests with nyc,

bin/nyc.js

+9
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ var yargs = require('yargs')
8888
type: 'boolean',
8989
describe: 'cache instrumentation results for improved performance'
9090
})
91+
.options('e', {
92+
alias: 'extension',
93+
default: [],
94+
describe: 'a list of extensions that nyc should handle in addition to .js'
95+
})
9196
.option('check-coverage', {
9297
type: 'boolean',
9398
default: false,
@@ -128,6 +133,7 @@ if (argv._[0] === 'report') {
128133
} else if (argv._.length) {
129134
// wrap subprocesses and execute argv[1]
130135
if (!Array.isArray(argv.require)) argv.require = [argv.require]
136+
if (!Array.isArray(argv.extension)) argv.extension = [argv.extension]
131137

132138
var nyc = (new NYC({
133139
require: argv.require
@@ -143,6 +149,9 @@ if (argv._[0] === 'report') {
143149
if (argv.require.length) {
144150
env.NYC_REQUIRE = argv.require.join(',')
145151
}
152+
if (argv.extension.length) {
153+
env.NYC_EXTENSION = argv.extension.join(',')
154+
}
146155
sw([wrapper], env)
147156

148157
foreground(nyc.mungeArgs(argv), function (done) {

bin/wrap.js

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ try {
88

99
;(new NYC({
1010
require: process.env.NYC_REQUIRE ? process.env.NYC_REQUIRE.split(',') : [],
11+
extension: process.env.NYC_EXTENSION ? process.env.NYC_EXTENSION.split(',') : [],
1112
enableCache: process.env.NYC_CACHE === 'enable'
1213
})).wrap()
1314

index.js

+30-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var md5hex = require('md5-hex')
1717
var findCacheDir = require('find-cache-dir')
1818
var pkgUp = require('pkg-up')
1919
var readPkg = require('read-pkg')
20+
var js = require('default-require-extensions/js')
2021

2122
/* istanbul ignore next */
2223
if (/index\.covered\.js$/.test(__filename)) {
@@ -53,7 +54,14 @@ function NYC (opts) {
5354
// require extensions can be provided as config in package.json.
5455
this.require = arrify(config.require || opts.require)
5556

56-
this.transform = this._createTransform()
57+
this.extensions = arrify(config.extension || opts.extension).concat('.js').map(function (ext) {
58+
return ext.toLowerCase()
59+
})
60+
61+
this.transforms = this.extensions.reduce(function (transforms, ext) {
62+
transforms[ext] = this._createTransform(ext)
63+
return transforms
64+
}.bind(this), {})
5765

5866
this.sourceMapCache = new SourceMapCache()
5967

@@ -79,7 +87,7 @@ NYC.prototype._loadConfig = function (opts) {
7987
return config
8088
}
8189

82-
NYC.prototype._createTransform = function () {
90+
NYC.prototype._createTransform = function (ext) {
8391
var _this = this
8492
return cachingTransform({
8593
salt: JSON.stringify({
@@ -94,7 +102,7 @@ NYC.prototype._createTransform = function () {
94102
factory: this._transformFactory.bind(this),
95103
cacheDir: this.cacheDirectory,
96104
disableCache: !this.enableCache,
97-
ext: '.js'
105+
ext: ext
98106
})
99107
}
100108

@@ -212,7 +220,15 @@ NYC.prototype._maybeInstrumentSource = function (code, filename, relFile) {
212220
return null
213221
}
214222

215-
return this.transform(code, {filename: filename, relFile: relFile})
223+
var ext, transform
224+
for (ext in this.transforms) {
225+
if (filename.toLowerCase().substr(-ext.length) === ext) {
226+
transform = this.transforms[ext]
227+
break
228+
}
229+
}
230+
231+
return transform ? transform(code, {filename: filename, relFile: relFile}) : null
216232
}
217233

218234
NYC.prototype._transformFactory = function (cacheDir) {
@@ -238,11 +254,17 @@ NYC.prototype._transformFactory = function (cacheDir) {
238254
}
239255
}
240256

257+
NYC.prototype._handleJs = function (code, filename) {
258+
var relFile = path.relative(this.cwd, filename)
259+
return this._maybeInstrumentSource(code, filename, relFile) || code
260+
}
261+
241262
NYC.prototype._wrapRequire = function () {
242-
var _this = this
243-
appendTransform(function (code, filename) {
244-
var relFile = path.relative(_this.cwd, filename)
245-
return _this._maybeInstrumentSource(code, filename, relFile) || code
263+
var handleJs = this._handleJs.bind(this)
264+
265+
this.extensions.forEach(function (ext) {
266+
require.extensions[ext] = js
267+
appendTransform(handleJs, ext)
246268
})
247269
}
248270

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"test/source-map-cache.js",
3535
"index.covered.js",
3636
"test/fixtures/_generateCoverage.js"
37-
]
37+
],
38+
"extension": [".es6"]
3839
},
3940
"standard": {
4041
"ignore": [
@@ -65,6 +66,7 @@
6566
"arrify": "^1.0.1",
6667
"caching-transform": "^1.0.0",
6768
"convert-source-map": "^1.1.2",
69+
"default-require-extensions": "^1.0.0",
6870
"find-cache-dir": "^0.1.1",
6971
"foreground-child": "^1.3.5",
7072
"glob": "^6.0.2",

test/fixtures/check-instrumented.es6

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function probe () {}
2+
3+
// When instrumented there will be references to variables like
4+
// __cov_pwkoI2PYHp3LJXkn_erl1Q in the probe() source.
5+
module.exports = function () {
6+
return /\b__cov_\B/.test(probe + '')
7+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function probe () {}
2+
3+
// When instrumented there will be references to variables like
4+
// __cov_pwkoI2PYHp3LJXkn_erl1Q in the probe() source.
5+
module.exports = function () {
6+
return /\b__cov_\B/.test(probe + '')
7+
}

test/fixtures/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"exclude": [
1313
"**/blarg",
1414
"**/blerg"
15-
]
15+
],
16+
"extension": [".es6", ".foo.BAR"]
1617
}
1718
}
1819
}

test/src/nyc-test.js

+52
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,22 @@ describe('nyc', function () {
8383

8484
nyc.exclude.length.should.eql(19)
8585
})
86+
87+
it("loads 'extension' patterns from package.json#config.nyc", function () {
88+
var nyc = new NYC({
89+
cwd: path.resolve(__dirname, '../fixtures')
90+
})
91+
92+
nyc.extensions.length.should.eql(3)
93+
})
94+
95+
it("loads 'extension' from package.json#nyc", function () {
96+
var nyc = new NYC({
97+
cwd: path.resolve(__dirname, '../..')
98+
})
99+
100+
nyc.extensions.length.should.eql(2)
101+
})
86102
})
87103

88104
describe('_prepGlobPatterns', function () {
@@ -232,6 +248,42 @@ describe('nyc', function () {
232248
})
233249
})
234250

251+
describe('compile handlers for custom extensions are assigned', function () {
252+
it('assigns a function to custom extensions', function () {
253+
var nyc = new NYC({
254+
cwd: path.resolve(__dirname, '../fixtures')
255+
})
256+
nyc.reset()
257+
nyc.wrap()
258+
259+
require.extensions['.es6'].should.be.a.function
260+
require.extensions['.foo.bar'].should.be.a.function
261+
262+
// default should still exist
263+
require.extensions['.js'].should.be.a.function
264+
})
265+
266+
it('calls the `_handleJs` function for custom file extensions', function () {
267+
// the `require` call to istanbul is deferred, loaded here so it doesn't mess with the hooks callCount
268+
require('istanbul')
269+
270+
var nyc = new NYC({
271+
cwd: path.resolve(__dirname, '../fixtures')
272+
})
273+
274+
sinon.spy(nyc, '_handleJs')
275+
276+
nyc.reset()
277+
nyc.wrap()
278+
279+
var check1 = require('../fixtures/check-instrumented.es6')
280+
var check2 = require('../fixtures/check-instrumented.foo.bar')
281+
check1().should.be.true
282+
check2().should.be.true
283+
nyc._handleJs.callCount.should.equal(2)
284+
})
285+
})
286+
235287
function testSignal (signal, done) {
236288
var nyc = (new NYC({
237289
cwd: fixtures

0 commit comments

Comments
 (0)