Comparing version 4.0.1 to 5.0.0
## Change Log | ||
### v5.0.0 (2015/12/09 11:03 -07:00) | ||
- [#87](https://github.com/bcoe/nyc/pull/87) make spawn() work on Windows (@bcoe) | ||
- [#84](https://github.com/bcoe/nyc/pull/84) glob based include/exclude of files (@Lalem001) | ||
- [#78](https://github.com/bcoe/nyc/pull/78) improvements to sourcemap tests (@novemberborn) | ||
- [#73](https://github.com/bcoe/nyc/pull/73) improvements to require tests (@novemberborn) | ||
- [#65](https://github.com/bcoe/nyc/pull/65) significant improvements to require hooks (@novemberborn) | ||
- [#64](https://github.com/bcoe/nyc/pull/64) upgrade Istanbul (@novemberborn) | ||
### v4.0.0 (2015/11/29 10:13 -07:00) | ||
@@ -4,0 +13,0 @@ |
123
index.js
@@ -5,3 +5,5 @@ /* global __coverage__ */ | ||
var glob = require('glob') | ||
var micromatch = require('micromatch') | ||
var mkdirp = require('mkdirp') | ||
var Module = require('module') | ||
var path = require('path') | ||
@@ -34,7 +36,8 @@ var rimraf = require('rimraf') | ||
// load exclude stanza from config. | ||
this.exclude = config.exclude || ['node_modules[\/\\\\]', 'test[\/\\\\]', 'test\\.js'] | ||
this.include = config.include || ['**'] | ||
this.include = this._prepGlobPatterns(this.include) | ||
this.exclude = ['**/node_modules/**'].concat(config.exclude || ['test/**', 'test{,-*}.js']) | ||
if (!Array.isArray(this.exclude)) this.exclude = [this.exclude] | ||
this.exclude = _.map(this.exclude, function (p) { | ||
return new RegExp(p) | ||
}) | ||
this.exclude = this._prepGlobPatterns(this.exclude) | ||
@@ -49,5 +52,12 @@ // require extensions can be provided as config in package.json. | ||
NYC.prototype._loadAdditionalModules = function () { | ||
require.main.paths.push(path.resolve(this.cwd, '/node_modules')) | ||
var _this = this | ||
this.require.forEach(function (r) { | ||
require(r) | ||
try { | ||
// first attempt to require the module relative to | ||
// the directory being instrumented. | ||
require(path.resolve(_this.cwd, './node_modules', r)) | ||
} catch (e) { | ||
// now try other locations, .e.g, the nyc node_modules folder. | ||
require(r) | ||
} | ||
}) | ||
@@ -71,8 +81,24 @@ } | ||
NYC.prototype._prepGlobPatterns = function (patterns) { | ||
if (!patterns) return patterns | ||
var directories = [] | ||
patterns = _.map(patterns, function (pattern) { | ||
// Allow gitignore style of directory exclusion | ||
if (!_.endsWith(pattern, '/**')) { | ||
directories.push(pattern.replace(/\/$/, '').concat('/**')) | ||
} | ||
return pattern | ||
}) | ||
return _.union(patterns, directories) | ||
} | ||
NYC.prototype.addFile = function (filename, returnImmediately) { | ||
var relFile = path.relative(this.cwd, filename) | ||
var instrument = this.shouldInstrumentFile(relFile) | ||
var instrument = this.shouldInstrumentFile(filename, relFile) | ||
var content = stripBom(fs.readFileSync(filename, 'utf8')) | ||
if (instrument) { | ||
this.sourceMapCache.add(filename, content) | ||
content = this.instrumenter.instrumentSync(content, './' + relFile) | ||
@@ -92,3 +118,3 @@ } else if (returnImmediately) { | ||
var relFile = path.relative(this.cwd, filename) | ||
var instrument = this.shouldInstrumentFile(relFile) | ||
var instrument = this.shouldInstrumentFile(filename, relFile) | ||
@@ -106,10 +132,7 @@ if (instrument) { | ||
NYC.prototype.shouldInstrumentFile = function (relFile, returnImmediately) { | ||
// only instrument a file if it's not on the exclude list. | ||
for (var i = 0, exclude; (exclude = this.exclude[i]) !== undefined; i++) { | ||
if (exclude.test(relFile)) { | ||
return false | ||
} | ||
} | ||
return true | ||
NYC.prototype.shouldInstrumentFile = function (filename, relFile) { | ||
relFile = relFile.replace(/^\.\//, '') // remove leading './'. | ||
return (micromatch.any(filename, this.include) || micromatch.any(relFile, this.include)) && | ||
!(micromatch.any(filename, this.exclude) || micromatch.any(relFile, this.exclude)) | ||
} | ||
@@ -122,3 +145,3 @@ | ||
glob.sync('**/*.js', {nodir: true}).forEach(function (filename) { | ||
glob.sync('**/*.js', {nodir: true, ignore: this.exclude}).forEach(function (filename) { | ||
var obj = _this.addFile(filename, true) | ||
@@ -139,30 +162,37 @@ if (obj.instrument) { | ||
var babelRequireHook = null | ||
var requireHook = function (module, filename) { | ||
// allow babel's compile hoook to compile | ||
// the code -- ignore node_modules, this | ||
// helps avoid cyclical require behavior. | ||
var content = null | ||
if (babelRequireHook && filename.indexOf('node_modules/') === -1) { | ||
babelRequireHook({ | ||
_compile: function (compiledSrc) { | ||
_this.sourceMapCache.add(filename, compiledSrc) | ||
content = compiledSrc | ||
} | ||
}, filename) | ||
} | ||
var defaultHook = function (module, filename) { | ||
// instrument the required file. | ||
var obj = _this.addFile(filename, false) | ||
// now instrument the compiled code. | ||
var obj = null | ||
if (content) { | ||
obj = _this.addContent(filename, content) | ||
} else { | ||
obj = _this.addFile(filename, false) | ||
// always use node's original _compile method to compile the instrumented | ||
// code. if a custom hook invoked the default hook the code should not be | ||
// compiled using the custom hook. | ||
Module.prototype._compile.call(module, obj.content, filename) | ||
} | ||
var wrapCustomHook = function (hook) { | ||
return function (module, filename) { | ||
// override the _compile method so the code can be instrumented first. | ||
module._compile = function (compiledSrc) { | ||
_this.sourceMapCache.add(filename, compiledSrc) | ||
// now instrument the compiled code. | ||
var obj = _this.addContent(filename, compiledSrc) | ||
Module.prototype._compile.call(module, obj.content, filename) | ||
} | ||
// allow the custom hook to compile the code. it can fall back to the | ||
// default hook if necessary (accessed via require.extensions['.js'] prior | ||
// to setting itself) | ||
hook(module, filename) | ||
} | ||
module._compile(obj.content, filename) | ||
} | ||
// use a getter and setter to capture any external | ||
// require hooks that are registered, e.g., babel-core/register | ||
var requireHook = defaultHook | ||
// track existing hooks so they can be restored without wrapping them a second | ||
// time. | ||
var hooks = [requireHook] | ||
// use a getter and setter to capture any external require hooks that are | ||
// registered, e.g., babel-core/register | ||
require.extensions.__defineGetter__('.js', function () { | ||
@@ -172,4 +202,11 @@ return requireHook | ||
require.extensions.__defineSetter__('.js', function (value) { | ||
babelRequireHook = value | ||
require.extensions.__defineSetter__('.js', function (hook) { | ||
var restoreIndex = hooks.indexOf(hook) | ||
if (restoreIndex !== -1) { | ||
requireHook = hook | ||
hooks.splice(restoreIndex + 1, hooks.length) | ||
} else { | ||
requireHook = wrapCustomHook(hook) | ||
hooks.push(requireHook) | ||
} | ||
}) | ||
@@ -176,0 +213,0 @@ } |
@@ -14,3 +14,3 @@ var _ = require('lodash') | ||
SourceMapCache.prototype.add = function (filename, source) { | ||
var sourceMap = convertSourceMap.fromSource(source) | ||
var sourceMap = convertSourceMap.fromSource(source) || convertSourceMap.fromMapFileSource(source, path.dirname(filename)) | ||
if (sourceMap) this.cache['./' + path.relative(this.cwd, filename)] = new SourceMapConsumer(sourceMap.sourcemap) | ||
@@ -24,7 +24,12 @@ } | ||
Object.keys(coverage).forEach(function (key) { | ||
if (_this.cache[key]) { | ||
_this._rewriteStatements(mappedCoverage[key], _this.cache[key]) | ||
_this._rewriteFunctions(mappedCoverage[key], _this.cache[key]) | ||
_this._rewriteBranches(mappedCoverage[key], _this.cache[key]) | ||
var sourceMap = _this.cache[key] | ||
if (!sourceMap) { | ||
return | ||
} | ||
var fileCoverage = mappedCoverage[key] | ||
_this._rewritePath(mappedCoverage, fileCoverage, sourceMap) | ||
_this._rewriteStatements(fileCoverage, sourceMap) | ||
_this._rewriteFunctions(fileCoverage, sourceMap) | ||
_this._rewriteBranches(fileCoverage, sourceMap) | ||
}) | ||
@@ -35,2 +40,12 @@ | ||
SourceMapCache.prototype._rewritePath = function (mappedCoverage, coverage, sourceMap) { | ||
// only rewrite the path if the file comes from a single source | ||
if (sourceMap.sources.length !== 1) return | ||
var originalPath = './' + path.join(path.dirname(coverage.path), sourceMap.sources[0]) | ||
delete mappedCoverage[coverage.path] | ||
coverage.path = originalPath | ||
mappedCoverage[originalPath] = coverage | ||
} | ||
SourceMapCache.prototype._rewriteStatements = function (coverage, sourceMap) { | ||
@@ -37,0 +52,0 @@ var start = null |
@@ -130,2 +130,4 @@ module.exports = wrap | ||
if (isWindows) fixWindowsBins(workingDir, options) | ||
return spawn.call(this, options) | ||
@@ -137,2 +139,19 @@ } | ||
// by default Windows will reference the full | ||
// path to the node.exe or iojs.exe as the bin, | ||
// we should instead point spawn() at our .cmd shim. | ||
function fixWindowsBins (workingDir, options) { | ||
var renode = new RegExp('.*node\\.exe$') | ||
var reiojs = new RegExp('.*iojs\\.exe$') | ||
options.file = options.file.replace(renode, workingDir + '/node.cmd') | ||
options.file = options.file.replace(reiojs, workingDir + '/node.cmd') | ||
options.args = options.args.map(function (a) { | ||
a = a.replace(renode, workingDir + '/node.cmd') | ||
a = a.replace(reiojs, workingDir + '/node.cmd') | ||
return a | ||
}) | ||
} | ||
function setup (argv, env) { | ||
@@ -139,0 +158,0 @@ if (argv && typeof argv === 'object' && !env && !Array.isArray(argv)) { |
{ | ||
"name": "nyc", | ||
"version": "4.0.1", | ||
"version": "5.0.0", | ||
"description": "a code coverage tool that works well with subprocesses.", | ||
@@ -17,3 +17,8 @@ "main": "index.js", | ||
"node_modules", | ||
"bin" | ||
"bin", | ||
"coverage", | ||
"test/fixtures/coverage.js", | ||
"test/nyc-test.js", | ||
"test/source-map-cache.js", | ||
"test/fixtures/_generateCoverage.js" | ||
] | ||
@@ -47,6 +52,7 @@ } | ||
"convert-source-map": "^1.1.2", | ||
"foreground-child": "1.3.0", | ||
"foreground-child": "^1.3.0", | ||
"glob": "^5.0.14", | ||
"istanbul": "^0.3.19", | ||
"istanbul": "^0.4.1", | ||
"lodash": "^3.10.0", | ||
"micromatch": "~2.1.6", | ||
"mkdirp": "^0.5.0", | ||
@@ -61,6 +67,5 @@ "rimraf": "^2.4.2", | ||
"devDependencies": { | ||
"babel-core": "^6.2.1", | ||
"babel-preset-es2015": "^6.1.18", | ||
"chai": "^3.0.0", | ||
"sinon": "^1.15.3", | ||
"source-map-fixtures": "^0.2.0", | ||
"standard": "^5.2.1", | ||
@@ -70,3 +75,2 @@ "tap": "^1.3.4" | ||
"bundleDependencies": [ | ||
"foreground-child", | ||
"spawn-wrap" | ||
@@ -73,0 +77,0 @@ ], |
@@ -39,25 +39,14 @@ # nyc | ||
## Support For Babel/ES2015 | ||
## Support For Custom Require Hooks (Babel! ES2015!) | ||
nyc is the easiest way to add ES2015 support to your project: | ||
nyc supports custom require hooks like | ||
[`babel-register`](http://babeljs.io/docs/usage/require/). If necessary nyc can | ||
load the hooks for you, [using the `--require` | ||
flag](#require-additional-modules). | ||
1. install the appropriate babel dependencies for your project (`npm i babel-core babel-preset-es2015 --save`). | ||
2. create a `.babelrc` file: | ||
Source maps are used to map coverage information back to the appropriate lines | ||
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`. | ||
```json | ||
{ | ||
"presets": ["es2015"] | ||
} | ||
``` | ||
3. install nyc, and run it with the appropriate `--require` flags: | ||
```sh | ||
nyc --require babel-core/register mocha | ||
``` | ||
nyc uses source-maps to map coverage information back to the appropriate lines of the pre-transpiled code: | ||
<img width="350" src="screen.png"> | ||
## Checking Coverage | ||
@@ -108,11 +97,21 @@ | ||
By default nyc does not instrument files in `node_modules`, or `test` | ||
for coverage. You can override this setting in your package.json, by | ||
adding the following configuration: | ||
You can tell nyc to exclude specific files and directories by adding | ||
an `config.nyc.exclude` array to your `package.json`. Each element of | ||
the array is a glob pattern indicating which paths should be omitted. | ||
```js | ||
Globs are matched using [micromatch](https://www.npmjs.com/package/micromatch) | ||
In addition to patterns specified in the package, nyc will always exclude | ||
files in `node_modules`. | ||
For example, the following config will exclude all `node_modules`, | ||
any files with the extension `.spec.js`, and anything in the `build` | ||
directory: | ||
```json | ||
{"config": { | ||
"nyc": { | ||
"exclude": [ | ||
"node_modules/" | ||
"**/*.spec.js", | ||
"build" | ||
] | ||
@@ -123,2 +122,20 @@ } | ||
> Note: exclude defaults to `['test', 'test{,-*}.js']`, which would exclude | ||
the `test` directory as well as `test.js` and `test-*.js` files | ||
## Including Files | ||
As an alternative to providing a list of files to `exclude`, you can provide | ||
an `include` key to specify specific files that should be covered: | ||
```json | ||
{"config": { | ||
"nyc": { | ||
"include": ["**/build/umd/moment.js"] | ||
} | ||
}} | ||
``` | ||
> Note: include defaults to `['**']` | ||
## Include Reports For Files That Are Not Required | ||
@@ -165,3 +182,3 @@ | ||
"test": "nyc tap ./test/*.js", | ||
"coverage": "nyc report --reporter=text-lcov | coveralls", | ||
"coverage": "nyc npm test && nyc report --reporter=text-lcov | coveralls", | ||
} | ||
@@ -171,4 +188,3 @@ } | ||
3. add the environment variable `COVERALLS_REPO_TOKEN` to travis, this is used by | ||
the coveralls bin. | ||
3. For private repos, add the environment variable `COVERALLS_REPO_TOKEN` to travis. | ||
@@ -183,3 +199,2 @@ 4. add the following to your `.travis.yml`: | ||
_Note: by default coveralls.io adds comments to pull-requests on GitHub, this can | ||
feel intrusive. To disable this, click on your repo on coveralls.io and uncheck `LEAVE COMMENTS?`._ | ||
> Note: by default coveralls.io adds comments to pull-requests on GitHub, this can feel intrusive. To disable this, click on your repo on coveralls.io and uncheck `LEAVE COMMENTS?`._ |
@@ -13,5 +13,4 @@ { | ||
"exclude": [ | ||
"node_modules/", | ||
"blarg/", | ||
"blerg/" | ||
"**/blarg", | ||
"**/blerg" | ||
] | ||
@@ -18,0 +17,0 @@ } |
@@ -17,26 +17,2 @@ /* global describe, it */ | ||
describe('babel', function () { | ||
it('collects coverage when the babel require hook is installed', function (done) { | ||
var nyc = (new NYC({ | ||
cwd: process.cwd() | ||
})).wrap() | ||
delete require.cache[require.resolve('babel-core/register')] | ||
require('babel-core/register') | ||
require('./fixtures/es6-not-loaded.js') | ||
nyc.writeCoverageFile() | ||
var reports = _.filter(nyc._loadReports(), function (report) { | ||
return report['./test/fixtures/es6-not-loaded.js'] | ||
}) | ||
var report = reports[0]['./test/fixtures/es6-not-loaded.js'] | ||
reports.length.should.equal(1) | ||
report.s['1'].should.equal(1) | ||
report.s['2'].should.equal(1) | ||
return done() | ||
}) | ||
}) | ||
describe('cwd', function () { | ||
@@ -71,13 +47,100 @@ function afterEach () { | ||
nyc.exclude.length.should.eql(3) | ||
nyc.exclude.length.should.eql(5) | ||
}) | ||
}) | ||
describe('_prepGlobPatterns', function () { | ||
it('should adjust patterns appropriately', function () { | ||
var _prepGlobPatterns = NYC.prototype._prepGlobPatterns | ||
var result = _prepGlobPatterns(['./foo', 'bar/**', 'baz/']) | ||
result.should.deep.equal([ | ||
'./foo', | ||
'bar/**', | ||
'baz/', | ||
'./foo/**', // Appended `/**` | ||
'baz/**' // Removed trailing slash before appending `/**` | ||
]) | ||
}) | ||
}) | ||
describe('shouldInstrumentFile', function () { | ||
it('should exclude appropriately with defaults', function () { | ||
var nyc = new NYC() | ||
// Root package contains config.exclude | ||
// Restore exclude to default patterns | ||
nyc.exclude = nyc._prepGlobPatterns([ | ||
'**/node_modules/**', | ||
'test/**', | ||
'test{,-*}.js' | ||
]) | ||
var shouldInstrumentFile = nyc.shouldInstrumentFile.bind(nyc) | ||
// nyc always excludes "node_modules/**" | ||
shouldInstrumentFile('foo', 'foo').should.equal(true) | ||
shouldInstrumentFile('node_modules/bar', 'node_modules/bar').should.equal(false) | ||
shouldInstrumentFile('foo/node_modules/bar', 'foo/node_modules/bar').should.equal(false) | ||
shouldInstrumentFile('test.js', 'test.js').should.equal(false) | ||
shouldInstrumentFile('testfoo.js', 'testfoo.js').should.equal(true) | ||
shouldInstrumentFile('test-foo.js', 'test-foo.js').should.equal(false) | ||
shouldInstrumentFile('lib/test.js', 'lib/test.js').should.equal(true) | ||
shouldInstrumentFile('/foo/bar/test.js', './test.js').should.equal(false) | ||
}) | ||
it('should exclude appropriately with config.exclude', function () { | ||
var nyc = new NYC({ | ||
cwd: fixtures | ||
}) | ||
var shouldInstrumentFile = nyc.shouldInstrumentFile.bind(nyc) | ||
// config.excludes: "blarg", "blerg" | ||
shouldInstrumentFile('blarg', 'blarg').should.equal(false) | ||
shouldInstrumentFile('blarg/foo.js', 'blarg/foo.js').should.equal(false) | ||
shouldInstrumentFile('blerg', 'blerg').should.equal(false) | ||
shouldInstrumentFile('./blerg', './blerg').should.equal(false) | ||
}) | ||
it('should handle example symlinked node_module', function () { | ||
var nyc = new NYC({ | ||
cwd: fixtures | ||
}) | ||
var shouldInstrumentFile = nyc.shouldInstrumentFile.bind(nyc) | ||
var relPath = '../../nyc/node_modules/glob/glob.js' | ||
var fullPath = '/Users/user/nyc/node_modules/glob/glob.js' | ||
shouldInstrumentFile(fullPath, relPath).should.equal(false) | ||
// Full path should be excluded (node_modules) | ||
shouldInstrumentFile(fullPath, relPath).should.equal(false) | ||
// Send both relative and absolute path | ||
// Results in exclusion (include = false) | ||
shouldInstrumentFile(fullPath, relPath).should.equal(false) | ||
}) | ||
it('allows a file to be included rather than excluded', function () { | ||
var nyc = new NYC() | ||
// Root package contains config.exclude | ||
// Restore exclude to default patterns | ||
nyc.include = nyc._prepGlobPatterns([ | ||
'test.js' | ||
]) | ||
var shouldInstrumentFile = nyc.shouldInstrumentFile.bind(nyc) | ||
shouldInstrumentFile('test.js', 'test.js').should.equal(true) | ||
shouldInstrumentFile('index.js', 'index.js').should.equal(false) | ||
}) | ||
}) | ||
describe('wrap', function () { | ||
var nyc | ||
it('wraps modules with coverage counters when they are required', function () { | ||
nyc = (new NYC({ | ||
var nyc = new NYC({ | ||
cwd: process.cwd() | ||
})).wrap() | ||
}) | ||
nyc.wrap() | ||
@@ -94,3 +157,35 @@ // clear the module cache so that | ||
describe('custom require hooks are installed', function () { | ||
it('wraps modules with coverage counters when the custom require hook compiles them', function () { | ||
var hook = sinon.spy(function (module, filename) { | ||
module._compile(fs.readFileSync(filename, 'utf8')) | ||
}) | ||
var nyc = new NYC({ | ||
cwd: process.cwd() | ||
}) | ||
nyc.wrap() | ||
// clear the module cache so that | ||
// we pull index.js in again and wrap it. | ||
var name = require.resolve('../') | ||
delete require.cache[name] | ||
// install the custom require hook | ||
require.extensions['.js'] = hook | ||
// when we require index.js it should be wrapped. | ||
var index = require('../') | ||
index.should.match(/__cov_/) | ||
// and the hook should have been called | ||
hook.calledOnce.should.be.true | ||
}) | ||
}) | ||
function testSignal (signal, done) { | ||
var nyc = (new NYC({ | ||
cwd: process.cwd() | ||
})).wrap() | ||
var proc = spawn(process.execPath, ['./test/fixtures/' + signal + '.js'], { | ||
@@ -120,2 +215,6 @@ cwd: process.cwd(), | ||
it('does not output coverage for files that have not been included, by default', function (done) { | ||
var nyc = (new NYC({ | ||
cwd: process.cwd() | ||
})).wrap() | ||
var reports = _.filter(nyc._loadReports(), function (report) { | ||
@@ -122,0 +221,0 @@ return report['./test/fixtures/not-loaded.js'] |
/* global describe, it */ | ||
var _ = require('lodash') | ||
var fs = require('fs') | ||
var path = require('path') | ||
var coverage = JSON.parse(fs.readFileSync('./test/fixtures/coverage-to-map.json', 'utf-8')) | ||
var sourceMapFixtures = require('source-map-fixtures') | ||
// Load source map fixtures. | ||
var covered = _.mapValues({ | ||
bundle: sourceMapFixtures.inline('bundle'), | ||
inline: sourceMapFixtures.inline('branching'), | ||
none: sourceMapFixtures.none('branching') | ||
}, function (fixture) { | ||
return _.assign({ | ||
// Coverage for the fixture is stored relative to the root directory. Here | ||
// compute the path to the fixture file relative to the root directory. | ||
relpath: './' + path.relative(path.join(__dirname, '..'), fixture.file), | ||
// the sourcemap itself remaps the path. | ||
mappedPath: './' + path.relative(path.join(__dirname, '..'), fixture.sourceFile), | ||
// Compute the number of lines in the original source, excluding any line | ||
// break at the end of the file. | ||
maxLine: fixture.sourceContentSync().trimRight().split(/\r?\n/).length | ||
}, fixture) | ||
}) | ||
var SourceMapCache = require('../lib/source-map-cache') | ||
var sourceMapCache = new SourceMapCache() | ||
sourceMapCache.add('./test/fixtures/es6-not-loaded.js', fs.readFileSync('./test/fixtures/code-with-map.js', 'utf-8')) | ||
_.forOwn(covered, function (fixture) { | ||
sourceMapCache.add(fixture.relpath, fixture.contentSync()) | ||
}) | ||
var coverage = require('./fixtures/coverage') | ||
var fixture = covered.inline | ||
require('chai').should() | ||
require('tap').mochaGlobals() | ||
// Note: original source code was 20 lines of es6 | ||
// compiled code is 31 lines of es5 code. | ||
describe('source-map-cache', function () { | ||
it('does not rewrite if there is no source map', function () { | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
mappedCoverage[covered.none.relpath].should.eql(coverage[covered.none.relpath]) | ||
}) | ||
describe('path', function () { | ||
it('does not rewrite path if the source map has more than one source', function () { | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
mappedCoverage.should.have.property(covered.bundle.relpath) | ||
mappedCoverage[covered.bundle.relpath].should.not.eql(coverage[covered.bundle.relpath]) | ||
}) | ||
it('rewrites path if the source map exactly one source', function () { | ||
var mappedCoverage = sourceMapCache.applySourceMaps(_.pick(coverage, fixture.relpath)) | ||
mappedCoverage.should.have.property(fixture.mappedPath) | ||
}) | ||
}) | ||
describe('statements', function () { | ||
it('drops statements that have no mapping back to the original source code', function () { | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
Object.keys(mappedCoverage['./test/fixtures/es6-not-loaded.js'].s).should.be.lt( | ||
coverage['./test/fixtures/es6-not-loaded.js'].s | ||
) | ||
Object.keys( | ||
mappedCoverage['./test/fixtures/es6-not-loaded.js'].statementMap | ||
).length.should.equal( | ||
Object.keys(mappedCoverage['./test/fixtures/es6-not-loaded.js'].s).length | ||
) | ||
Object.keys(mappedCoverage[fixture.mappedPath].s) | ||
.should.be.lt(coverage[fixture.relpath].s) | ||
Object.keys(mappedCoverage[fixture.mappedPath].statementMap).length | ||
.should.equal(Object.keys(mappedCoverage[fixture.mappedPath].s).length) | ||
}) | ||
@@ -32,7 +68,7 @@ | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
var statements = _.values(mappedCoverage['./test/fixtures/es6-not-loaded.js'].statementMap) | ||
var statements = _.values(mappedCoverage[fixture.mappedPath].statementMap) | ||
var maxStatement = _.max(statements, function (s) { | ||
return Math.max(s.start.line, s.end.line) | ||
}) | ||
Math.max(maxStatement.start.line, maxStatement.end.line).should.be.lte(20) | ||
Math.max(maxStatement.start.line, maxStatement.end.line).should.be.lte(fixture.maxLine) | ||
}) | ||
@@ -44,20 +80,15 @@ }) | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
Object.keys(mappedCoverage['./test/fixtures/es6-not-loaded.js'].f).should.be.lt( | ||
coverage['./test/fixtures/es6-not-loaded.js'].f | ||
) | ||
Object.keys( | ||
mappedCoverage['./test/fixtures/es6-not-loaded.js'].fnMap | ||
).length.should.equal( | ||
Object.keys(mappedCoverage['./test/fixtures/es6-not-loaded.js'].f).length | ||
) | ||
Object.keys(mappedCoverage[fixture.mappedPath].f) | ||
.should.be.lt(coverage[fixture.relpath].f) | ||
Object.keys(mappedCoverage[fixture.mappedPath].fnMap).length | ||
.should.equal(Object.keys(mappedCoverage[fixture.mappedPath].f).length) | ||
}) | ||
it('maps all functions back to their original loc', function () { | ||
var coverage = JSON.parse(fs.readFileSync('./test/fixtures/coverage-to-map.json', 'utf-8')) | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
var functions = _.values(mappedCoverage['./test/fixtures/es6-not-loaded.js'].fnMap) | ||
var functions = _.values(mappedCoverage[fixture.mappedPath].fnMap) | ||
var maxFunction = _.max(functions, function (f) { | ||
return f.line | ||
}) | ||
Math.max(maxFunction.line).should.be.lte(20) | ||
Math.max(maxFunction.line).should.be.lte(fixture.maxLine) | ||
}) | ||
@@ -69,22 +100,17 @@ }) | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
Object.keys(mappedCoverage['./test/fixtures/es6-not-loaded.js'].b).should.be.lt( | ||
coverage['./test/fixtures/es6-not-loaded.js'].b | ||
) | ||
Object.keys( | ||
mappedCoverage['./test/fixtures/es6-not-loaded.js'].branchMap | ||
).length.should.equal( | ||
Object.keys(mappedCoverage['./test/fixtures/es6-not-loaded.js'].b).length | ||
) | ||
Object.keys(mappedCoverage[fixture.mappedPath].b) | ||
.should.be.lt(coverage[fixture.relpath].b) | ||
Object.keys(mappedCoverage[fixture.mappedPath].branchMap).length | ||
.should.equal(Object.keys(mappedCoverage[fixture.mappedPath].b).length) | ||
}) | ||
it('maps all branches back to their original loc', function () { | ||
var coverage = JSON.parse(fs.readFileSync('./test/fixtures/coverage-to-map.json', 'utf-8')) | ||
var mappedCoverage = sourceMapCache.applySourceMaps(coverage) | ||
var branches = _.values(mappedCoverage['./test/fixtures/es6-not-loaded.js'].branchMap) | ||
var branches = _.values(mappedCoverage[fixture.mappedPath].branchMap) | ||
var maxBranch = _.max(branches, function (b) { | ||
return b.line | ||
}) | ||
Math.max(maxBranch.line).should.be.lte(20) | ||
Math.max(maxBranch.line).should.be.lte(fixture.maxLine) | ||
}) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
5
195
39
84630
13
35
1982
+ Addedmicromatch@~2.1.6
+ Addedarr-diff@1.1.0(transitive)
+ Addedarr-flatten@1.1.0(transitive)
+ Addedarray-slice@0.2.3(transitive)
+ Addedbraces@1.8.5(transitive)
+ Addedcross-spawn@4.0.2(transitive)
+ Addeddebug@2.6.9(transitive)
+ Addedescodegen@1.8.1(transitive)
+ Addedesprima@2.7.3(transitive)
+ Addedexpand-brackets@0.1.5(transitive)
+ Addedexpand-range@1.8.2(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedfilename-regex@2.0.1(transitive)
+ Addedfill-range@2.2.4(transitive)
+ Addedfor-in@1.0.2(transitive)
+ Addedfor-own@0.1.5(transitive)
+ Addedforeground-child@1.5.6(transitive)
+ Addedglob-base@0.3.0(transitive)
+ Addedglob-parent@2.0.0(transitive)
+ Addedis-buffer@1.1.6(transitive)
+ Addedis-dotfile@1.0.3(transitive)
+ Addedis-equal-shallow@0.1.3(transitive)
+ Addedis-extglob@1.0.0(transitive)
+ Addedis-glob@1.1.32.0.1(transitive)
+ Addedis-number@2.1.04.0.0(transitive)
+ Addedis-posix-bracket@0.1.1(transitive)
+ Addedis-primitive@2.0.0(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedisobject@0.2.02.1.0(transitive)
+ Addedistanbul@0.4.5(transitive)
+ Addedkind-of@1.1.03.2.26.0.3(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedlru-cache@4.1.5(transitive)
+ Addedmath-random@1.0.4(transitive)
+ Addedmicromatch@2.1.6(transitive)
+ Addedms@2.0.0(transitive)
+ Addedobject.omit@0.2.1(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedparse-glob@3.0.4(transitive)
+ Addedpreserve@0.2.0(transitive)
+ Addedpseudomap@1.0.2(transitive)
+ Addedrandomatic@3.1.1(transitive)
+ Addedregex-cache@0.4.4(transitive)
+ Addedrepeat-element@1.1.4(transitive)
+ Addedrepeat-string@1.6.1(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedword-wrap@1.2.5(transitive)
+ Addedyallist@2.1.2(transitive)
- Removedescodegen@1.7.1(transitive)
- Removedesprima@1.2.52.5.0(transitive)
- Removedfast-levenshtein@1.0.7(transitive)
- Removedfileset@0.2.1(transitive)
- Removedistanbul@0.3.22(transitive)
- Removedlevn@0.2.5(transitive)
- Removedminimatch@2.0.10(transitive)
- Removedoptionator@0.5.0(transitive)
- Removedwordwrap@0.0.3(transitive)
Updatedforeground-child@^1.3.0
Updatedistanbul@^0.4.1