Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: istanbuljs/babel-plugin-istanbul
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4cd34dcd2456c418bdb4373c7e4d7ef3ac5a284e
Choose a base ref
...
head repository: istanbuljs/babel-plugin-istanbul
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2fb91f54c8271936f016fb521b080213bbdb77f7
Choose a head ref
  • 12 commits
  • 22 files changed
  • 3 contributors

Commits on Jul 31, 2019

  1. Copy the full SHA
    6d21bf2 View commit details

Commits on Sep 14, 2019

  1. Copy the full SHA
    c2aecae View commit details

Commits on Sep 29, 2019

  1. Copy the full SHA
    2b7ea02 View commit details

Commits on Oct 8, 2019

  1. feat!: Drop node.js 6 (#226)

    Fixes #209
    coreyfarrell authored Oct 8, 2019
    Copy the full SHA
    93db21a View commit details
  2. feat: Add support for instrumenter options (#227)

    This adds support for:
    * coverageVariable
    * coverageGlobalScope
    * coverageGlobalScopeFunc
    * ignoreClassMethods
    
    Fixes #208, fixes #212
    coreyfarrell authored Oct 8, 2019
    Copy the full SHA
    fe08f5b View commit details

Commits on Oct 9, 2019

  1. Copy the full SHA
    f39924e View commit details

Commits on Nov 7, 2019

  1. Copy the full SHA
    2342557 View commit details

Commits on Dec 7, 2019

  1. Copy the full SHA
    c35ed7b View commit details
  2. chore: Tidelift tasks

    coreyfarrell committed Dec 7, 2019
    Copy the full SHA
    95b2df7 View commit details

Commits on Dec 9, 2019

  1. Copy the full SHA
    99bd2a2 View commit details

Commits on Dec 20, 2019

  1. Copy the full SHA
    063274a View commit details
  2. chore(release): 6.0.0

    coreyfarrell committed Dec 20, 2019
    Copy the full SHA
    2fb91f5 View commit details
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tidelift: "npm/babel-plugin-istanbul"
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@ node_js:
- "node"
- "10"
- "8"
- "6"

matrix:
include:
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,18 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [6.0.0](https://github.com/istanbuljs/babel-plugin-istanbul/compare/v5.2.0...v6.0.0) (2019-12-20)


### ⚠ BREAKING CHANGES

* Drop node.js 6 (#226)

### Features

* Add support for instrumenter options ([#227](https://github.com/istanbuljs/babel-plugin-istanbul/issues/227)) ([fe08f5b](https://github.com/istanbuljs/babel-plugin-istanbul/commit/fe08f5b8282136c7ed9375fa32148586bd6a7e28)), closes [#208](https://github.com/istanbuljs/babel-plugin-istanbul/issues/208) [#212](https://github.com/istanbuljs/babel-plugin-istanbul/issues/212)
* Drop node.js 6 ([#226](https://github.com/istanbuljs/babel-plugin-istanbul/issues/226)) ([93db21a](https://github.com/istanbuljs/babel-plugin-istanbul/commit/93db21aa2bbdbb06fb784f52c24a7847fad6be92)), closes [#209](https://github.com/istanbuljs/babel-plugin-istanbul/issues/209)

## [5.2.0](https://github.com/istanbuljs/babel-plugin-istanbul/compare/v5.1.4...v5.2.0) (2019-07-18)


6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -129,3 +129,9 @@ function instrument(sourceCode, sourceMap, fileName) {
## Credit where credit is due

The approach used in `babel-plugin-istanbul` was inspired by [Thai Pangsakulyanont](https://github.com/dtinth)'s original library [`babel-plugin-__coverage__`](https://github.com/dtinth/babel-plugin-__coverage__).

## `babel-plugin-istanbul` for enterprise

Available as part of the Tidelift Subscription.

The maintainers of `babel-plugin-istanbul` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-babel-plugin-istanbul?utm_source=npm-babel-plugin-istanbul&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
11 changes: 11 additions & 0 deletions fixtures/class-functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class Foo1 {
bar() {}
barz() {}
}

class Foo2 {
bar() {}
barz() {}
}

module.exports = { Foo1, Foo2 }
1 change: 1 addition & 0 deletions fixtures/config/file1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('file1')
1 change: 1 addition & 0 deletions fixtures/config/file2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('file2')
5 changes: 5 additions & 0 deletions fixtures/config/nyc-alt.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict'

module.exports = {
include: ['file2.js']
}
5 changes: 5 additions & 0 deletions fixtures/config/nyc.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict'

module.exports = {
include: ['file1.js']
}
1 change: 1 addition & 0 deletions fixtures/config/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
2 changes: 1 addition & 1 deletion fixtures/node_modules/should-cover.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion fixtures/node_modules/should-not-cover.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion fixtures/plugin-should-cover.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let foo = function () {
const foo = function () {
console.log('foo')
}
foo()
2 changes: 1 addition & 1 deletion fixtures/plugin-should-not-cover.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let bar = function () {
const bar = function () {
console.log('bar')
}
bar()
2 changes: 1 addition & 1 deletion fixtures/should-cover.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let foo = function () {
const foo = function () {
console.log('foo')
}
foo()
2 changes: 1 addition & 1 deletion fixtures/should-not-cover.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let bar = function () {
const bar = function () {
console.log('bar')
}
bar()
2 changes: 1 addition & 1 deletion fixtures/should-respect-cwd.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
let foo = function () {
const foo = function () {
console.log('foo')
}
foo()
3,730 changes: 2,205 additions & 1,525 deletions package-lock.json

Large diffs are not rendered by default.

35 changes: 18 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "babel-plugin-istanbul",
"version": "5.2.0",
"version": "6.0.0",
"author": "Thai Pangsakulyanont @dtinth",
"license": "BSD-3-Clause",
"description": "A babel plugin that adds istanbul instrumentation to ES6 code",
@@ -10,35 +10,36 @@
],
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
"find-up": "^3.0.0",
"istanbul-lib-instrument": "^3.3.0",
"test-exclude": "^5.2.3"
"@istanbuljs/load-nyc-config": "^1.0.0",
"@istanbuljs/schema": "^0.1.2",
"istanbul-lib-instrument": "^4.0.0",
"test-exclude": "^6.0.0"
},
"devDependencies": {
"@babel/cli": "^7.4.3",
"@babel/core": "^7.4.3",
"@babel/plugin-transform-modules-commonjs": "^7.4.3",
"@babel/register": "^7.4.0",
"@babel/cli": "^7.7.5",
"@babel/core": "^7.7.5",
"@babel/plugin-transform-modules-commonjs": "^7.7.5",
"@babel/register": "^7.7.4",
"chai": "^4.2.0",
"coveralls": "^3.0.3",
"cross-env": "^5.2.0",
"mocha": "^6.1.4",
"nyc": "^14.1.0",
"coveralls": "^3.0.9",
"cross-env": "^6.0.3",
"mocha": "^6.2.2",
"nyc": "^15.0.0",
"pmock": "^0.2.3",
"standard": "^12.0.1",
"standard-version": "^6.0.1"
"standard": "^14.3.1",
"standard-version": "^7.1.0"
},
"scripts": {
"coverage": "nyc report --reporter=text-lcov | coveralls",
"release": "babel src --out-dir lib",
"pretest": "standard && npm run release",
"test": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text mocha test/*.js",
"test": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text mocha --timeout 5000 test/*.js",
"prepublish": "npm test && npm run release",
"version": "standard-version"
},
"standard": {
"ignore": [
"fixtures/has-inline-source-map.js"
"fixtures/*.js"
]
},
"repository": {
@@ -67,6 +68,6 @@
},
"homepage": "https://github.com/istanbuljs/babel-plugin-istanbul#readme",
"engines": {
"node": ">=6"
"node": ">=8"
}
}
126 changes: 89 additions & 37 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,112 @@
import path from 'path'
import { realpathSync } from 'fs'
import { dirname } from 'path'
import { execFileSync } from 'child_process'
import { declare } from '@babel/helper-plugin-utils'
import { programVisitor } from 'istanbul-lib-instrument'

const testExclude = require('test-exclude')
const findUp = require('find-up')
import TestExclude from 'test-exclude'
import schema from '@istanbuljs/schema'

function getRealpath (n) {
try {
return realpathSync(n) || n
return realpathSync(n) || /* istanbul ignore next */ n
} catch (e) {
/* istanbul ignore next */
return n
}
}

const memoize = new Map()
/* istanbul ignore next */
const memosep = path.sep === '/' ? ':' : ';'

function loadNycConfig (cwd, opts) {
let memokey = cwd
const args = [
path.resolve(__dirname, 'load-nyc-config-sync.js'),
cwd
]

if ('nycrcPath' in opts) {
args.push(opts.nycrcPath)

memokey += memosep + opts.nycrcPath
}

/* execFileSync is expensive, avoid it if possible! */
if (memoize.has(memokey)) {
return memoize.get(memokey)
}

const result = JSON.parse(execFileSync(process.execPath, args))
const error = result['load-nyc-config-sync-error']
if (error) {
throw new Error(error)
}

const config = {
...schema.defaults.babelPluginIstanbul,
cwd,
...result
}
memoize.set(memokey, config)
return config
}

function findConfig (opts) {
const cwd = getRealpath(opts.cwd || process.env.NYC_CWD || /* istanbul ignore next */ process.cwd())
const keys = Object.keys(opts)
const ignored = Object.keys(opts).filter(s => s === 'nycrcPath' || s === 'cwd')
if (keys.length > ignored.length) {
// explicitly configuring options in babel
// takes precedence.
return {
...schema.defaults.babelPluginIstanbul,
cwd,
...opts
}
}

if (ignored.length === 0 && process.env.NYC_CONFIG) {
// defaults were already applied by nyc
return JSON.parse(process.env.NYC_CONFIG)
}

return loadNycConfig(cwd, opts)
}

function makeShouldSkip () {
let exclude
return function shouldSkip (file, opts) {
if (!exclude || exclude.cwd !== opts.cwd) {
const cwd = getRealpath(process.env.NYC_CWD || process.cwd())
const nycConfig = process.env.NYC_CONFIG ? JSON.parse(process.env.NYC_CONFIG) : {}

let config = {}
if (Object.keys(opts).length > 0) {
// explicitly configuring options in babel
// takes precedence.
config = opts
} else if (nycConfig.include || nycConfig.exclude) {
// nyc was configured in a parent process (keep these settings).
config = {
include: nycConfig.include,
exclude: nycConfig.exclude,
// Make sure this is true unless explicitly set to `false`. `undefined` is still `true`.
excludeNodeModules: nycConfig.excludeNodeModules !== false
}
} else {
// fallback to loading config from key in package.json.
config = {
configKey: 'nyc',
configPath: dirname(findUp.sync('package.json', { cwd }))
}
}

exclude = testExclude(Object.assign(
{ cwd },
config
))
return function shouldSkip (file, nycConfig) {
if (!exclude || (exclude.cwd !== nycConfig.cwd)) {
exclude = new TestExclude({
cwd: nycConfig.cwd,
include: nycConfig.include,
exclude: nycConfig.exclude,
extension: nycConfig.extension,
// Make sure this is true unless explicitly set to `false`. `undefined` is still `true`.
excludeNodeModules: nycConfig.excludeNodeModules !== false
})
}

return !exclude.shouldInstrument(file)
}
}

export default declare(api => {
api.assertVersion(7)

const t = api.types
const shouldSkip = makeShouldSkip()

const t = api.types
return {
visitor: {
Program: {
enter (path) {
this.__dv__ = null
this.nycConfig = findConfig(this.opts)
const realPath = getRealpath(this.file.opts.filename)
if (shouldSkip(realPath, this.opts)) {
if (shouldSkip(realPath, this.nycConfig)) {
return
}
let { inputSourceMap } = this.opts
@@ -71,8 +115,16 @@ export default declare(api => {
inputSourceMap = this.file.inputMap.sourcemap
}
}
const visitorOptions = {}
Object.entries(schema.defaults.instrumentVisitor).forEach(([name, defaultValue]) => {
if (name in this.nycConfig) {
visitorOptions[name] = this.nycConfig[name]
} else {
visitorOptions[name] = schema.defaults.instrumentVisitor[name]
}
})
this.__dv__ = programVisitor(t, realPath, {
coverageVariable: '__coverage__',
...visitorOptions,
inputSourceMap
})
this.__dv__.enter(path)
14 changes: 14 additions & 0 deletions src/load-nyc-config-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env node
'use strict'

const { loadNycConfig } = require('@istanbuljs/load-nyc-config')

async function main () {
const [cwd, nycrcPath] = process.argv.slice(2)

console.log(JSON.stringify(await loadNycConfig({ cwd, nycrcPath })))
}

main().catch(error => {
console.log(JSON.stringify({ 'load-nyc-config-sync-error': error.message }))
})
161 changes: 139 additions & 22 deletions test/babel-plugin-istanbul.js
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@ describe('babel-plugin-istanbul', function () {
context('Babel plugin config', function () {
it('should instrument file if shouldSkip returns false', function () {
var result = babel.transformFileSync('./fixtures/plugin-should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/plugin-should-cover.js']
@@ -21,6 +23,8 @@ describe('babel-plugin-istanbul', function () {

it('should not instrument file if shouldSkip returns true', function () {
var result = babel.transformFileSync('./fixtures/plugin-should-not-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/plugin-should-cover.js']
@@ -33,6 +37,8 @@ describe('babel-plugin-istanbul', function () {
context('local node_modules', function () {
it('should instrument file if shouldSkip returns false', function () {
var result = babel.transformFileSync('./fixtures/node_modules/should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
excludeNodeModules: false,
@@ -46,6 +52,8 @@ describe('babel-plugin-istanbul', function () {

it('should not instrument file if shouldSkip returns true', function () {
var result = babel.transformFileSync('./fixtures/node_modules/should-not-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/node_modules/should-not-cover.js']
@@ -59,6 +67,8 @@ describe('babel-plugin-istanbul', function () {
it('should call onCover callback', function () {
var args
babel.transformFileSync('./fixtures/plugin-should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
onCover: function () {
@@ -76,6 +86,8 @@ describe('babel-plugin-istanbul', function () {
context('source maps', function () {
it('should use inline source map', function () {
var result = babel.transformFileSync('./fixtures/has-inline-source-map.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/has-inline-source-map.js']
@@ -87,6 +99,8 @@ describe('babel-plugin-istanbul', function () {

it('should not use inline source map if inputSourceMap is set to false', function () {
var result = babel.transformFileSync('./fixtures/has-inline-source-map.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/has-inline-source-map.js'],
@@ -99,6 +113,8 @@ describe('babel-plugin-istanbul', function () {

it('should use provided source map', function () {
var result = babel.transformFileSync('./fixtures/has-inline-source-map.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/has-inline-source-map.js'],
@@ -110,10 +126,80 @@ describe('babel-plugin-istanbul', function () {
})
})

context('instrument options', function () {
it('should honor coverageVariable option', function () {
const result = babel.transformFileSync('./fixtures/should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/should-cover.js'],
coverageVariable: '__TEST_VARIABLE__'
}]
]
})
result.code.should.match(/__TEST_VARIABLE__/)
result.code.should.not.match(/__coverage__/)
})

it('should honor coverageGlobalScope option', function () {
const result = babel.transformFileSync('./fixtures/should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/should-cover.js'],
coverageGlobalScope: 'window'
}]
]
})
result.code.should.match(/new Function\("return window"\)/)
result.code.should.not.match(/new Function\("return this"\)/)
})

it('should honor coverageGlobalScope option', function () {
const result = babel.transformFileSync('./fixtures/should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/should-cover.js'],
coverageGlobalScopeFunc: false
}]
]
})
result.code.should.match(/global\s*=\s*this/)
result.code.should.not.match(/global\s*=\s*new Function\("return this"\)/)
})

it('should honor ignoreClassMethods option', function () {
const result = babel.transformFileSync('./fixtures/class-functions.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/class-functions.js'],
ignoreClassMethods: ['bar']
}]
]
})

// bar() is ignored
result.code.should.match(/bar\(\)\s*{\s*}/)
result.code.should.not.match(/bar\(\)\s*{\s*cov_.*/)

// barz() does not get instrumented
result.code.should.match(/barz\(\)\s*{\s*cov_.*/)
result.code.should.not.match(/barz\(\)\s*{\s*}/)
})
})

context('package.json "nyc" config', function () {
context('process.env.NYC_CONFIG is set', function () {
it('should instrument file if shouldSkip returns false', function () {
var result = babel.transformFileSync('./fixtures/should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
makeVisitor
]
@@ -123,6 +209,8 @@ describe('babel-plugin-istanbul', function () {

it('should not instrument file if shouldSkip returns true', function () {
var result = babel.transformFileSync('./fixtures/should-not-cover.js', {
babelrc: false,
configFile: false,
plugins: [
makeVisitor
]
@@ -132,16 +220,23 @@ describe('babel-plugin-istanbul', function () {
})

context('process.env.NYC_CONFIG is not set', function () {
this.timeout(10000)

const OLD_NYC_CONFIG = process.env.NYC_CONFIG
const OLD_NYC_CWD = process.env.NYC_CWD
before(() => {
delete process.env.NYC_CONFIG
delete process.env.NYC_CWD
})
after(() => {
process.env.NYC_CONFIG = OLD_NYC_CONFIG
process.env.NYC_CWD = OLD_NYC_CWD
})

it('should instrument file if shouldSkip returns false', function () {
var result = babel.transformFileSync('./fixtures/should-cover.js', {
babelrc: false,
configFile: false,
plugins: [
makeVisitor
]
@@ -151,12 +246,52 @@ describe('babel-plugin-istanbul', function () {

it('should not instrument file if shouldSkip returns true', function () {
var result = babel.transformFileSync('./fixtures/should-not-cover.js', {
babelrc: false,
configFile: false,
plugins: [
makeVisitor
]
})
result.code.should.not.match(/statementMap/)
})

it('should load config using cwd', function () {
const cwd = path.resolve(__dirname, '..', 'fixtures', 'config')
function helper (file, match, opts) {
const result = babel.transformFileSync(
path.resolve(cwd, file),
{
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, { cwd, ...opts }]
]
}
)
if (match) {
result.code.should.match(/statementMap/)
} else {
result.code.should.not.match(/statementMap/)
}
}

helper('file1.js', true)
helper('file2.js', false)
helper('file1.js', false, { nycrcPath: 'nyc-alt.config.js' })
helper('file2.js', true, { nycrcPath: 'nyc-alt.config.js' })
;(function () {
babel.transformFileSync(
path.resolve(cwd, 'file1.js'),
{
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, { cwd, nycrcPath: 'missing-config.js' }]
]
}
)
}).should.throw(/Requested configuration file missing-config.js not found/)
})
})
})

@@ -166,6 +301,8 @@ describe('babel-plugin-istanbul', function () {
// regression test for https://github.com/istanbuljs/babel-plugin-istanbul/issues/78
it('should instrument: export const foo = () => {}', function () {
var result = babel.transformFileSync('./fixtures/issue-78.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/issue-78.js']
@@ -178,6 +315,8 @@ describe('babel-plugin-istanbul', function () {
// regression test for https://github.com/istanbuljs/babel-plugin-istanbul/issues/201
it('should not conflict with transform-modules-commonjs', function () {
var result = babel.transformFileSync('./fixtures/issue-201.js', {
babelrc: false,
configFile: false,
plugins: [
[makeVisitor, {
include: ['fixtures/issue-201.js']
@@ -188,27 +327,5 @@ describe('babel-plugin-istanbul', function () {
result.code.should.match(/_path.*\.resolve\)\(_path\)/)
result.code.should.not.match(/_path\.resolve\)\(_path\)/)
})

it('should respect a changed cwd in options', function () {
const opts = {
cwd: path.resolve(__dirname, '..', 'lib')
}
const plugins = [
[makeVisitor, opts]
]

var resultBefore = babel.transformFileSync('./fixtures/should-respect-cwd.js', {
plugins
})

resultBefore.code.should.not.match(/statementMap/)

opts.cwd = path.resolve(__dirname, '..', 'fixtures')

var resultAfter = babel.transformFileSync('./fixtures/should-respect-cwd.js', {
plugins
})
resultAfter.code.should.match(/statementMap/)
})
})
})