Comparing version 3.3.2 to 4.0.0
4.0.0 / 2017-06-16 | ||
================== | ||
* feat: [BREAKING_CHANGE] use nyc instead of istanbul (#57) | ||
3.3.2 / 2017-05-22 | ||
@@ -3,0 +8,0 @@ ================== |
'use strict'; | ||
var path = require('path'); | ||
var findIstanbul = require('./lib/find_istanbul'); | ||
var Coffee = require('./lib/coffee'); | ||
// child process always use the cwd of the main process | ||
process.env.coffee_cwd = process.cwd(); | ||
// inject script supporting istanbul with multiple process | ||
process.env.istanbul_bin_path = findIstanbul(); | ||
require('childprocess').inject(path.join(__dirname, 'lib/inject_istanbul.js')); | ||
exports.Coffee = Coffee; | ||
@@ -14,0 +6,0 @@ |
'use strict'; | ||
var assert = require('assert'); | ||
var debug = require('debug')('coffee:assert'); | ||
var show = require('./show'); | ||
const assert = require('assert'); | ||
const debug = require('debug')('coffee:assert'); | ||
const show = require('./show'); | ||
module.exports = function(expected, actual, message) { | ||
expected.forEach(function(rule) { | ||
module.exports = coffeeAssert; | ||
function coffeeAssert(expected, actual, message) { | ||
for (let rule of expected) { | ||
const isOpposite = rule.isOpposite; | ||
@@ -13,3 +15,4 @@ rule = rule.value; | ||
if (Array.isArray(rule)) { | ||
return module.exports(rule, actual, message); | ||
coffeeAssert(rule, actual, message); | ||
continue; | ||
} | ||
@@ -27,4 +30,5 @@ | ||
if (rule instanceof RegExp) { | ||
return assert.strictEqual(rule.test(actual), !isOpposite, | ||
assert.strictEqual(rule.test(actual), !isOpposite, | ||
msg + ' expected `' + show(rule) + '` but actual `' + show(actual) + '`'); | ||
continue; | ||
} | ||
@@ -34,3 +38,3 @@ | ||
msg + ' expected `' + show(rule) + '` but actual `' + show(actual) + '`'); | ||
}); | ||
}; | ||
} | ||
} |
'use strict'; | ||
var util = require('util'); | ||
var EventEmitter = require('events'); | ||
var cp = require('child_process'); | ||
var assert = require('assert'); | ||
var debug = require('debug')('coffee'); | ||
var assertion = require('./assert'); | ||
var show = require('./show'); | ||
var Rule = require('./rule'); | ||
const EventEmitter = require('events'); | ||
const cp = require('child_process'); | ||
const assert = require('assert'); | ||
const debug = require('debug')('coffee'); | ||
const assertion = require('./assert'); | ||
const show = require('./show'); | ||
const Rule = require('./rule'); | ||
// init coffee_inject_istanbul env | ||
process.env.coffee_inject_istanbul = 'false'; | ||
// Only accept these type below for assertion | ||
const acceptType = [ 'stdout', 'stderr', 'code', 'error' ]; | ||
module.exports = Coffee; | ||
class Coffee extends EventEmitter { | ||
function Coffee(opt) { | ||
EventEmitter.call(this); | ||
opt || (opt = {}); | ||
assert(opt.method && opt.cmd, 'should specify method and cmd'); | ||
this.method = opt.method; | ||
this.cmd = opt.cmd; | ||
this.args = opt.args; | ||
this.opt = opt.opt; | ||
this.restore(); | ||
constructor(opt) { | ||
opt || (opt = {}); | ||
assert(opt.method && opt.cmd, 'should specify method and cmd'); | ||
super(); | ||
var self = this; | ||
this.on('stdout_data', function(buf) { | ||
debug('output stdout `%s`', show(buf)); | ||
self._debug_stdout && process.stdout.write(buf); | ||
self.stdout += buf; | ||
}); | ||
this.on('stderr_data', function(buf) { | ||
debug('output stderr `%s`', show(buf)); | ||
self._debug_stderr && process.stderr.write(buf); | ||
self.stderr += buf; | ||
}); | ||
this.on('error', function(err) { | ||
self.error = err; | ||
}); | ||
this.once('close', function(code) { | ||
// restore coffee_inject_istanbul | ||
process.env.coffee_inject_istanbul = 'false'; | ||
debug('output code `%s`', show(code)); | ||
self.code = code; | ||
try { | ||
assertion(self.waitAssert.stdout, self.stdout, 'match stdout'); | ||
assertion(self.waitAssert.stderr, self.stderr, 'match stderr'); | ||
assertion(self.waitAssert.code, self.code, 'match code'); | ||
self.error && assertion(self.waitAssert.error, self.error.message, 'match error message'); | ||
} catch (err) { | ||
return done(err); | ||
} | ||
done(); | ||
}); | ||
function done(err) { | ||
self.complete = true; | ||
if (self.cb) { | ||
self.cb.call(self, err, { | ||
stdout: self.stdout, | ||
stderr: self.stderr, | ||
code: self.code, | ||
error: self.error, | ||
}); | ||
} else { | ||
if (err) { | ||
self.emit('complete_error', err); | ||
} else { | ||
self.emit('complete_success', { | ||
this.method = opt.method; | ||
this.cmd = opt.cmd; | ||
this.args = opt.args; | ||
this.opt = opt.opt; | ||
this.restore(); | ||
this.on('stdout_data', buf => { | ||
debug('output stdout `%s`', show(buf)); | ||
this._debug_stdout && process.stdout.write(buf); | ||
this.stdout += buf; | ||
}); | ||
this.on('stderr_data', buf => { | ||
debug('output stderr `%s`', show(buf)); | ||
this._debug_stderr && process.stderr.write(buf); | ||
this.stderr += buf; | ||
}); | ||
this.on('error', err => { | ||
this.error = err; | ||
}); | ||
this.once('close', code => { | ||
debug('output code `%s`', show(code)); | ||
this.code = code; | ||
try { | ||
assertion(this.waitAssert.stdout, this.stdout, 'match stdout'); | ||
assertion(this.waitAssert.stderr, this.stderr, 'match stderr'); | ||
assertion(this.waitAssert.code, this.code, 'match code'); | ||
this.error && assertion(this.waitAssert.error, this.error.message, 'match error message'); | ||
} catch (err) { | ||
return done(err); | ||
} | ||
done(); | ||
}); | ||
const self = this; | ||
function done(err) { | ||
self.complete = true; | ||
if (self.cb) { | ||
self.cb.call(self, err, { | ||
stdout: self.stdout, | ||
stderr: self.stderr, | ||
code: self.code, | ||
error: self.error, | ||
}); | ||
} else { | ||
if (err) { | ||
self.emit('complete_error', err); | ||
} else { | ||
self.emit('complete_success', { | ||
stdout: self.stdout, | ||
stderr: self.stderr, | ||
}); | ||
} | ||
} | ||
} | ||
if (process.env.COFFEE_DEBUG) { | ||
this.debug(process.env.COFFEE_DEBUG); | ||
} | ||
process.nextTick(this._run.bind(this)); | ||
} | ||
if (process.env.COFFEE_DEBUG) { | ||
this.debug(process.env.COFFEE_DEBUG); | ||
coverage() { | ||
// it has not been impelmented | ||
// if (enable === false) { | ||
// process.env.NYC_NO_INSTRUMENT = true; | ||
// } | ||
return this; | ||
} | ||
process.nextTick(this._run.bind(this)); | ||
} | ||
debug(level) { | ||
this._debug_stderr = false; | ||
util.inherits(Coffee, EventEmitter); | ||
// 0 (default) -> stdout + stderr | ||
// 1 -> stdout | ||
// 2 -> stderr | ||
switch (String(level)) { | ||
case '1': | ||
this._debug_stdout = true; | ||
break; | ||
case '2': | ||
this._debug_stderr = true; | ||
break; | ||
case 'false': | ||
this._debug_stdout = false; | ||
this._debug_stderr = false; | ||
break; | ||
default: | ||
this._debug_stdout = true; | ||
this._debug_stderr = true; | ||
} | ||
Coffee.prototype.coverage = function(isCoverage) { | ||
if (isCoverage === false) { | ||
this._isCoverage = false; | ||
return this; | ||
} | ||
return this; | ||
}; | ||
Coffee.prototype.debug = function(level) { | ||
this._debug_stdout = false; | ||
this._debug_stderr = false; | ||
// 0 (default) -> stdout + stderr | ||
// 1 -> stdout | ||
// 2 -> stderr | ||
switch (String(level)) { | ||
case '1': | ||
this._debug_stdout = true; | ||
break; | ||
case '2': | ||
this._debug_stderr = true; | ||
break; | ||
case 'false': | ||
this._debug_stdout = false; | ||
this._debug_stderr = false; | ||
break; | ||
default: | ||
this._debug_stdout = true; | ||
this._debug_stderr = true; | ||
expect(type, value) { | ||
if (acceptType.indexOf(type) > -1) { | ||
const rule = new Rule(value); | ||
if (this.complete) { | ||
assertion([ rule ], this[type], 'match ' + type); | ||
} else { | ||
this.waitAssert[type].push(rule); | ||
} | ||
} | ||
return this; | ||
} | ||
return this; | ||
}; | ||
// Only accept these type below for assertion | ||
var acceptType = [ 'stdout', 'stderr', 'code', 'error' ]; | ||
Coffee.prototype.expect = function(type, value) { | ||
if (acceptType.indexOf(type) > -1) { | ||
var rule = new Rule(value); | ||
if (this.complete) { | ||
assertion([ rule ], this[type], 'match ' + type); | ||
} else { | ||
this.waitAssert[type].push(rule); | ||
notExpect(type, value) { | ||
if (acceptType.indexOf(type) > -1) { | ||
const rule = new Rule(value, true); | ||
if (this.complete) { | ||
assertion([ rule ], this[type], 'match ' + type); | ||
} else { | ||
this.waitAssert[type].push(rule); | ||
} | ||
} | ||
return this; | ||
} | ||
return this; | ||
}; | ||
Coffee.prototype.notExpect = function(type, value) { | ||
if (acceptType.indexOf(type) > -1) { | ||
var rule = new Rule(value, true); | ||
if (this.complete) { | ||
assertion([ rule ], this[type], 'match ' + type); | ||
} else { | ||
this.waitAssert[type].push(rule); | ||
/* | ||
Write data to stdin of the command | ||
*/ | ||
write(value) { | ||
assert(!this._isEndCalled, 'can\'t call write after end'); | ||
this.stdin.push(value); | ||
return this; | ||
} | ||
end(cb) { | ||
this.cb = cb; | ||
if (!cb) { | ||
return new Promise((resolve, reject) => { | ||
this.on('complete_success', resolve); | ||
this.on('complete_error', reject); | ||
}); | ||
} | ||
} | ||
return this; | ||
}; | ||
/* | ||
Write data to stdin of the command | ||
*/ | ||
_run() { | ||
this._isEndCalled = true; | ||
const cmd = this.proc = run(this.method, this.cmd, this.args, this.opt); | ||
Coffee.prototype.write = function(value) { | ||
assert(!this._isEndCalled, 'can\'t call write after end'); | ||
this.stdin.push(value); | ||
return this; | ||
}; | ||
cmd.stdout && cmd.stdout.on('data', this.emit.bind(this, 'stdout_data')); | ||
cmd.stderr && cmd.stderr.on('data', this.emit.bind(this, 'stderr_data')); | ||
cmd.once('error', this.emit.bind(this, 'error')); | ||
cmd.once('close', this.emit.bind(this, 'close')); | ||
Coffee.prototype.end = function(cb) { | ||
this.cb = cb; | ||
if (!cb) { | ||
return new Promise((resolve, reject) => { | ||
this.on('complete_success', resolve); | ||
this.on('complete_error', reject); | ||
}); | ||
if (this.stdin.length) { | ||
this.stdin.forEach(function(buf) { | ||
debug('input stdin `%s`', show(buf)); | ||
cmd.stdin.write(buf); | ||
}); | ||
cmd.stdin.end(); | ||
} | ||
return this; | ||
} | ||
}; | ||
Coffee.prototype._run = function() { | ||
this._isEndCalled = true; | ||
// inject istanbul when start with istanbul and set coverage true | ||
// https://github.com/gotwarlost/istanbul#multiple-process-usage | ||
process.env.coffee_inject_istanbul = process.env.running_under_istanbul ? this._isCoverage : false; | ||
debug('coverage enable: %s', process.env.coffee_inject_istanbul); | ||
var cmd = this.proc = run(this.method, this.cmd, this.args, this.opt); | ||
restore() { | ||
// cache input for command | ||
this.stdin = []; | ||
cmd.stdout && cmd.stdout.on('data', this.emit.bind(this, 'stdout_data')); | ||
cmd.stderr && cmd.stderr.on('data', this.emit.bind(this, 'stderr_data')); | ||
cmd.once('error', this.emit.bind(this, 'error')); | ||
cmd.once('close', this.emit.bind(this, 'close')); | ||
// cache output for command | ||
this.stdout = ''; | ||
this.stderr = ''; | ||
this.code = null; | ||
this.error = null; | ||
if (this.stdin.length) { | ||
this.stdin.forEach(function(buf) { | ||
debug('input stdin `%s`', show(buf)); | ||
cmd.stdin.write(buf); | ||
}); | ||
cmd.stdin.end(); | ||
// cache expected output | ||
this.waitAssert = { | ||
stderr: [], | ||
stdout: [], | ||
code: [], | ||
error: [], | ||
}; | ||
this.complete = false; | ||
this._isEndCalled = false; | ||
this._debug_stdout = false; | ||
this._debug_stderr = false; | ||
this._isCoverage = true; | ||
return this; | ||
} | ||
} | ||
return this; | ||
}; | ||
module.exports = Coffee; | ||
Coffee.prototype.restore = function() { | ||
// cache input for command | ||
this.stdin = []; | ||
// cache output for command | ||
this.stdout = ''; | ||
this.stderr = ''; | ||
this.code = null; | ||
this.error = null; | ||
// cache expected output | ||
this.waitAssert = { | ||
stderr: [], | ||
stdout: [], | ||
code: [], | ||
error: [], | ||
}; | ||
this.complete = false; | ||
this._isEndCalled = false; | ||
this._debug_stdout = false; | ||
this._debug_stderr = false; | ||
this._isCoverage = true; | ||
return this; | ||
}; | ||
function run(method, cmd, args, opt) { | ||
@@ -216,0 +207,0 @@ if (!opt && args && typeof args === 'object' && !Array.isArray(args)) { |
{ | ||
"name": "coffee", | ||
"version": "3.3.2", | ||
"version": "4.0.0", | ||
"description": "Test command line on nodejs", | ||
"main": "index.js", | ||
"dependencies": { | ||
"childprocess": "^2.0.2", | ||
"debug": "^2.6.8" | ||
@@ -15,5 +14,5 @@ }, | ||
"eslint-config-egg": "^4.1.0", | ||
"istanbul": "0", | ||
"mm": "^2.1.0", | ||
"mocha": "2", | ||
"nyc": "^11.0.2", | ||
"spy": "^1.0.0" | ||
@@ -40,12 +39,10 @@ }, | ||
"ci": { | ||
"version": "4, 6, 7" | ||
"version": "4, 6, 8" | ||
}, | ||
"scripts": { | ||
"lint": "eslint index.js lib test", | ||
"test": "mocha -R spec -t 80000", | ||
"cover": "rm -rf coverage && istanbul cover --report none --print none node_modules/mocha/bin/_mocha -- -R spec -t 80000", | ||
"cov": "npm run cover && istanbul report --root coverage text-summary json lcov", | ||
"ci": "npm run lint && npm run cov", | ||
"autod": "autod", | ||
"clean": "rm -rf coverage" | ||
"lint": "eslint .", | ||
"test": "mocha -R spec -t 80000 test/*.js", | ||
"cov": "nyc -r json -r lcov -r text-summary npm test", | ||
"ci": "npm run lint && npm run cov" | ||
}, | ||
@@ -52,0 +49,0 @@ "files": [ |
@@ -53,18 +53,6 @@ # Coffee | ||
## Support multiple process coverage with istanbul | ||
## Support multiple process coverage with nyc | ||
Coffee will detect `istanbul` automatically, and generate coverage-{processId}.json, you should generate reporter by `istanbul report`. | ||
Recommend to use [nyc] for coverage, you can use [any test frammework supported by nyc](https://istanbul.js.org/docs/tutorials/). | ||
```bash | ||
$ rm -rf coverage | ||
$ istanbul cover --report none --print none node_modules/mocha/bin/_mocha -- -R spec -t 5000 | ||
$ istanbul report text-summary json lcov | ||
=============================== Coverage summary =============================== | ||
State## ments : 98.2% ( 109/111 ) | ||
Branches : 97.37% ( 37/38 ) | ||
Functions : 100% ( 20/20 ) | ||
Lines : 98.18% ( 108/110 ) | ||
================================================================================ | ||
``` | ||
## API | ||
@@ -133,5 +121,5 @@ | ||
Copyright (c) 2015 popomore. Licensed under the MIT license. | ||
Copyright (c) 2017 popomore. Licensed under the MIT license. | ||
[istanbul]: https://github.com/gotwarlost/istanbul | ||
[nyc]: https://github.com/istanbuljs/nyc |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
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 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
1
2
14414
8
280
124
- Removedchildprocess@^2.0.2
- Removedchildprocess@2.0.2(transitive)
- Removedcopy-to@2.0.1(transitive)
- Removedescape-html@1.0.3(transitive)
- Removedutility@1.6.0(transitive)