Skip to content

Commit

Permalink
Add support for configurable file extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
lloydcotten committed Feb 11, 2016
1 parent 657f15c commit d3fd19e
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 10 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@ of the pre-transpiled code. You'll have to configure your custom require hook
to inline the source map in the transpiled code. For Babel that means setting
the `sourceMaps` option to `inline`.

## Support For Custom File Extensions (.jsx, .es6)
Supporting file extensions can be configured through either the configuration arguments or with the `nyc` config section in `package.json`.

```shell
nyc --extension .jsx --extension .es6 npm test
```

```json
{"nyc": {
"extensions": [
".jsx",
".es6"
]
}
}
```

## Checking Coverage

nyc exposes istanbul's check-coverage tool. After running your tests with nyc,
Expand Down
9 changes: 9 additions & 0 deletions bin/nyc.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ var yargs = require('yargs')
type: 'boolean',
describe: 'cache instrumentation results for improved performance'
})
.options('e', {
alias: 'extension',
default: [],
describe: 'a list of extensions that nyc should handle in addition to .js'
})
.option('check-coverage', {
type: 'boolean',
default: false,
Expand Down Expand Up @@ -128,6 +133,7 @@ if (argv._[0] === 'report') {
} else if (argv._.length) {
// wrap subprocesses and execute argv[1]
if (!Array.isArray(argv.require)) argv.require = [argv.require]
if (!Array.isArray(argv.extension)) argv.extension = [argv.extension]

var nyc = (new NYC({
require: argv.require
Expand All @@ -143,6 +149,9 @@ if (argv._[0] === 'report') {
if (argv.require.length) {
env.NYC_REQUIRE = argv.require.join(',')
}
if (argv.extension.length) {
env.NYC_EXTENSION = argv.extension.join(',')
}
sw([wrapper], env)

foreground(nyc.mungeArgs(argv), function (done) {
Expand Down
1 change: 1 addition & 0 deletions bin/wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ try {

;(new NYC({
require: process.env.NYC_REQUIRE ? process.env.NYC_REQUIRE.split(',') : [],
extension: process.env.NYC_EXTENSION ? process.env.NYC_EXTENSION.split(',') : [],
enableCache: process.env.NYC_CACHE === 'enable'
})).wrap()

Expand Down
38 changes: 30 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var md5hex = require('md5-hex')
var findCacheDir = require('find-cache-dir')
var pkgUp = require('pkg-up')
var readPkg = require('read-pkg')
var js = require('default-require-extensions/js')

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

this.transform = this._createTransform()
this.extensions = arrify(config.extension || opts.extension).concat('.js').map(function (ext) {
return ext.toLowerCase()
})

this.transforms = this.extensions.reduce(function (transforms, ext) {
transforms[ext] = this._createTransform(ext)
return transforms
}.bind(this), {})

this.sourceMapCache = new SourceMapCache()

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

NYC.prototype._createTransform = function () {
NYC.prototype._createTransform = function (ext) {
var _this = this
return cachingTransform({
salt: JSON.stringify({
Expand All @@ -94,7 +102,7 @@ NYC.prototype._createTransform = function () {
factory: this._transformFactory.bind(this),
cacheDir: this.cacheDirectory,
disableCache: !this.enableCache,
ext: '.js'
ext: ext
})
}

Expand Down Expand Up @@ -212,7 +220,15 @@ NYC.prototype._maybeInstrumentSource = function (code, filename, relFile) {
return null
}

return this.transform(code, {filename: filename, relFile: relFile})
var ext, transform
for (ext in this.transforms) {
if (filename.toLowerCase().substr(-ext.length) === ext) {
transform = this.transforms[ext]
break
}
}

return transform ? transform(code, {filename: filename, relFile: relFile}) : null
}

NYC.prototype._transformFactory = function (cacheDir) {
Expand All @@ -238,11 +254,17 @@ NYC.prototype._transformFactory = function (cacheDir) {
}
}

NYC.prototype._handleJs = function (code, filename) {
var relFile = path.relative(this.cwd, filename)
return this._maybeInstrumentSource(code, filename, relFile) || code
}

NYC.prototype._wrapRequire = function () {
var _this = this
appendTransform(function (code, filename) {
var relFile = path.relative(_this.cwd, filename)
return _this._maybeInstrumentSource(code, filename, relFile) || code
var handleJs = this._handleJs.bind(this)

this.extensions.forEach(function (ext) {
require.extensions[ext] = js
appendTransform(handleJs, ext)
})
}

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"test/source-map-cache.js",
"index.covered.js",
"test/fixtures/_generateCoverage.js"
]
],
"extension": [".es6"]
},
"standard": {
"ignore": [
Expand Down Expand Up @@ -65,6 +66,7 @@
"arrify": "^1.0.1",
"caching-transform": "^1.0.0",
"convert-source-map": "^1.1.2",
"default-require-extensions": "^1.0.0",
"find-cache-dir": "^0.1.1",
"foreground-child": "^1.3.5",
"glob": "^6.0.2",
Expand Down
7 changes: 7 additions & 0 deletions test/fixtures/check-instrumented.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function probe () {}

// When instrumented there will be references to variables like
// __cov_pwkoI2PYHp3LJXkn_erl1Q in the probe() source.
module.exports = function () {
return /\b__cov_\B/.test(probe + '')
}
7 changes: 7 additions & 0 deletions test/fixtures/check-instrumented.foo.bar
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function probe () {}

// When instrumented there will be references to variables like
// __cov_pwkoI2PYHp3LJXkn_erl1Q in the probe() source.
module.exports = function () {
return /\b__cov_\B/.test(probe + '')
}
3 changes: 2 additions & 1 deletion test/fixtures/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"exclude": [
"**/blarg",
"**/blerg"
]
],
"extension": [".es6", ".foo.BAR"]
}
}
}
52 changes: 52 additions & 0 deletions test/src/nyc-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ describe('nyc', function () {

nyc.exclude.length.should.eql(19)
})

it("loads 'extension' patterns from package.json#config.nyc", function () {
var nyc = new NYC({
cwd: path.resolve(__dirname, '../fixtures')
})

nyc.extensions.length.should.eql(3)
})

it("loads 'extension' from package.json#nyc", function () {
var nyc = new NYC({
cwd: path.resolve(__dirname, '../..')
})

nyc.extensions.length.should.eql(2)
})
})

describe('_prepGlobPatterns', function () {
Expand Down Expand Up @@ -232,6 +248,42 @@ describe('nyc', function () {
})
})

describe('compile handlers for custom extensions are assigned', function () {
it('assigns a function to custom extensions', function () {
var nyc = new NYC({
cwd: path.resolve(__dirname, '../fixtures')
})
nyc.reset()
nyc.wrap()

require.extensions['.es6'].should.be.a.function
require.extensions['.foo.bar'].should.be.a.function

// default should still exist
require.extensions['.js'].should.be.a.function
})

it('calls the `_handleJs` function for custom file extensions', function () {
// the `require` call to istanbul is deferred, loaded here so it doesn't mess with the hooks callCount
require('istanbul')

var nyc = new NYC({
cwd: path.resolve(__dirname, '../fixtures')
})

sinon.spy(nyc, '_handleJs')

nyc.reset()
nyc.wrap()

var check1 = require('../fixtures/check-instrumented.es6')
var check2 = require('../fixtures/check-instrumented.foo.bar')
check1().should.be.true
check2().should.be.true
nyc._handleJs.callCount.should.equal(2)
})
})

function testSignal (signal, done) {
var nyc = (new NYC({
cwd: fixtures
Expand Down

0 comments on commit d3fd19e

Please sign in to comment.