Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

coffee

Package Overview
Dependencies
Maintainers
3
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

coffee - npm Package Compare versions

Comparing version 4.2.0 to 5.0.1

lib/rule_error.js

12

HISTORY.md
5.0.1 / 2018-08-07
==================
5.0.0 / 2018-08-07
==================
**others**
* [[`f7309da`](http://github.com/node-modules/coffee/commit/f7309da0eeb1e400f704024daaab456756890820)] - refactor: [BREAKING] make coffee more extendable (#62) (TZ | 天猪 <<atian25@qq.com>>)
* [[`728418b`](http://github.com/node-modules/coffee/commit/728418b91799ed8c4b6865ca78951ef7288829e6)] - chore: migrate to node-modules (#61) (Haoliang Gao <<sakura9515@gmail.com>>)
4.2.0 / 2018-08-01

@@ -6,3 +16,3 @@ ==================

**features**
* [[`b0e16e0`](http://github.com/popomore/coffee/commit/b0e16e00aa903b53950e28606959719df68539cc)] - feat: support prompt (#60) (TZ | 天猪 <<atian25@qq.com>>)
* [[`b0e16e0`](http://github.com/node-modules/coffee/commit/b0e16e00aa903b53950e28606959719df68539cc)] - feat: support prompt (#60) (TZ | 天猪 <<atian25@qq.com>>)

@@ -9,0 +19,0 @@ 4.1.0 / 2017-06-29

4

index.js
'use strict';
var Coffee = require('./lib/coffee');
const Coffee = require('./lib/coffee');
const Rule = require('./lib/rule');
exports.Coffee = Coffee;
exports.Rule = Rule;

@@ -7,0 +9,0 @@ /**

'use strict';
const fs = require('fs');
const path = require('path');

@@ -10,9 +9,6 @@ const EventEmitter = require('events');

const spawn = require('cross-spawn');
const assertion = require('./assert');
const show = require('./show');
const Rule = require('./rule');
const ErrorRule = require('./rule_error');
// Only accept these type below for assertion
const acceptType = [ 'stdout', 'stderr', 'code', 'error' ];
class Coffee extends EventEmitter {

@@ -29,2 +25,11 @@

this.opt = opt.opt;
// Only accept these type below for assertion
this.RuleMapping = {
stdout: Rule,
stderr: Rule,
code: Rule,
error: ErrorRule,
};
this.restore();

@@ -46,36 +51,23 @@

this.once('close', code => {
this._unpatchHookScripts();
debug('output code `%s`', show(code));
this.code = code;
this.complete = true;
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');
for (const rule of this._waitAssert) {
rule.validate();
}
// suc
const result = {
stdout: this.stdout,
stderr: this.stderr,
code: this.code,
error: this.error,
};
this.emit('complete_success', result);
this.cb && this.cb(undefined, result);
} catch (err) {
return done(err);
this.emit('complete_error', err);
return this.cb && this.cb(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,
});
}
}
}

@@ -97,10 +89,2 @@ if (process.env.COFFEE_DEBUG) {

beforeScript(scriptFile) {
assert(this.method === 'fork', `can't set beforeScript on ${this.method} process`);
assert(path.isAbsolute(this.cmd), `can't set beforeScript, ${this.cmd} must be absolute path`);
this._beforeScriptFile = scriptFile;
return this;
}
debug(level) {

@@ -131,28 +115,50 @@ this._debug_stderr = false;

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);
}
}
/**
* Assert type with expected value
*
* @param {String} type - assertion rule type
* @param {String|RegExp|Array} expected - expected value
* @return {Coffee} return self for chain
*/
expect(type, expected) {
this._addAssertion({ type, expected });
return this;
}
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);
}
}
/**
* Assert type with not expected value, opposite assertion of `expect`.
*
* @param {String} type - assertion rule type
* @param {String|RegExp|Array} expected - not expected value
* @return {Coffee} return self for chain
*/
notExpect(type, expected) {
this._addAssertion({ type, expected, isOpposite: true });
return this;
}
_addAssertion({ type, expected, isOpposite }) {
const RuleClz = this.RuleMapping[type];
assert(RuleClz, `unknown rule type: ${type}`);
const rule = new RuleClz({ ctx: this, type, expected, isOpposite });
if (this.complete) {
rule.validate();
} else {
this._waitAssert.push(rule);
}
}
/**
* allow user to custom rule
* @param {String} type - rule type
* @param {Rule} RuleClz - custom rule class
* @protected
*/
setRule(type, RuleClz) {
this.RuleMapping[type] = RuleClz;
}
/**
* Write data to stdin of the command

@@ -168,2 +174,9 @@ * @param {String} input - input text

/**
* whether set as prompt mode
*
* mark as `prompt`, all stdin call by `write` will wait for `prompt` event then output
* @param {Boolean} [enable] - default to true
* @return {Coffee} return self for chain
*/
waitForPrompt(enable) {

@@ -174,2 +187,8 @@ this._isWaitForPrompt = enable !== false;

/**
* get `end` hook
*
* @param {Function} [cb] - callback, recommended to left undefind and use promise
* @return {Promise} - end promise
*/
end(cb) {

@@ -185,38 +204,26 @@ this.cb = cb;

get _hookScripts() {
if (this._beforeScriptFile) {
return `\n\nrequire(${JSON.stringify(this._beforeScriptFile)}); // !!!!!!!coffee hook script, don't change it!!!!!!!!\n\n`;
}
}
/**
* inject script file for mock purpose
*
* @param {String} scriptFile - script file full path
* @return {Coffee} return self for chain
*/
beforeScript(scriptFile) {
assert(this.method === 'fork', `can't set beforeScript on ${this.method} process`);
assert(path.isAbsolute(this.cmd), `can't set beforeScript, ${this.cmd} must be absolute path`);
this._beforeScriptFile = scriptFile;
_patchHookScripts() {
const hookScriptsContent = this._hookScripts;
if (!hookScriptsContent) return;
let content = fs.readFileSync(this.cmd, 'utf8');
if (!content.includes(hookScriptsContent)) {
// skip shebang
if (content.startsWith('#!')) {
content = content.replace('\n', `\n${hookScriptsContent}`);
} else {
content = hookScriptsContent + content;
}
debug('add hook scripts %j into %s', hookScriptsContent, this.cmd);
fs.writeFileSync(this.cmd, content);
}
return this;
}
_unpatchHookScripts() {
const hookScriptsContent = this._hookScripts;
if (!hookScriptsContent) return;
let content = fs.readFileSync(this.cmd, 'utf8');
if (content.includes(hookScriptsContent)) {
content = content.replace(hookScriptsContent, '');
debug('remove hook scripts %j from %s', hookScriptsContent, this.cmd);
fs.writeFileSync(this.cmd, content);
_run() {
this._isEndCalled = true;
if (this._beforeScriptFile) {
this.opt = this.opt || {};
const execArgv = this.opt.execArgv ? this.opt.execArgv : process.execArgv;
execArgv.push('-r', this._beforeScriptFile);
this.opt.execArgv = execArgv;
}
}
_run() {
this._isEndCalled = true;
this._patchHookScripts();
const cmd = this.proc = run(this.method, this.cmd, this.args, this.opt);

@@ -263,8 +270,3 @@

// cache expected output
this.waitAssert = {
stderr: [],
stdout: [],
code: [],
error: [],
};
this._waitAssert = [];
this.complete = false;

@@ -301,4 +303,5 @@ this._isEndCalled = false;

let handler = cp[method];
/* istanbul ignore next */
if (process.platform === 'win32' && method === 'spawn') handler = spawn;
return handler(cmd, args, opt);
}
'use strict';
function Rule(val, isOpposite) {
if (Array.isArray(val)) {
this.value = val.map(function(item) {
return new Rule(item, isOpposite);
});
} else {
this.value = val;
const is = require('is-type-of');
const assert = require('assert');
const show = require('./show');
class Rule {
constructor({ ctx, type, expected, isOpposite }) {
this.ctx = ctx;
this.type = type;
this.expected = [].concat(expected);
this.isOpposite = isOpposite === true;
}
this.isOpposite = isOpposite === true;
validate(message) {
const actual = this.ctx[this.type];
for (const expected of this.expected) {
message = this.formatMessage(actual, expected, message);
this.assert(actual, expected, message);
}
}
assert(actual, expected, message) {
const assertFn = assert[this.isOpposite ? 'notStrictEqual' : 'strictEqual'];
if (is.regexp(expected)) {
return assertFn(expected.test(actual), true, message);
}
return assertFn(actual, expected, message);
}
formatMessage(actual, expected, message) {
message = message || `match ${this.type}`;
return `should ${this.isOpposite ? 'not ' : ''}${message} expected \`${this.inspectObj(expected)}\` but actual \`${this.inspectObj(actual)}\``;
}
inspectObj(obj) {
return show(obj);
}
restore() {
// do nth
}
}
module.exports = Rule;
{
"name": "coffee",
"version": "4.2.0",
"description": "Test command line on nodejs",
"version": "5.0.1",
"description": "Test command line on Node.js.",
"main": "index.js",
"dependencies": {
"cross-spawn": "^6.0.5",
"debug": "^3.1.0"
"debug": "^3.1.0",
"is-type-of": "^1.2.0"
},
"devDependencies": {
"autod": "^3.0.1",
"egg-bin": "^4.8.1",
"egg-ci": "^1.8.0",
"eslint": "^3.19.0",
"eslint-config-egg": "^4.1.0",
"eslint": "^5.3.0",
"eslint-config-egg": "^7.0.0",
"mm": "^2.2.2",
"mocha": "2",
"mocha": "^5.2.0",
"nyc": "^11.0.2",

@@ -22,7 +24,8 @@ "spy": "^1.0.0"

"type": "git",
"url": "git://github.com/popomore/coffee.git"
"url": "git://github.com/node-modules/coffee.git"
},
"homepage": "https://github.com/popomore/coffee",
"homepage": "https://github.com/node-modules/coffee",
"author": "popomore <sakura9515@gmail.com>",
"keywords": [
"cli",
"test",

@@ -37,6 +40,6 @@ "shell",

"engines": {
"node": ">= 4.0.0"
"node": ">= 6.0.0"
},
"ci": {
"version": "4, 6, 8"
"version": "6, 8, 10"
},

@@ -46,5 +49,6 @@ "scripts": {

"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"
"test": "npm run lint -- --fix && egg-bin pkgfiles && npm run test-local",
"test-local": "egg-bin test",
"cov": "egg-bin cov",
"ci": "npm run lint && egg-bin pkgfiles --check && npm run cov"
},

@@ -51,0 +55,0 @@ "files": [

@@ -8,4 +8,4 @@ # Coffee

[![NPM version](https://img.shields.io/npm/v/coffee.svg?style=flat)](https://npmjs.org/package/coffee)
[![Build Status](https://img.shields.io/travis/popomore/coffee.svg?style=flat)](https://travis-ci.org/popomore/coffee)
[![codecov.io](https://img.shields.io/codecov/c/github/popomore/coffee.svg?style=flat)](http://codecov.io/github/popomore/coffee?branch=master)
[![Build Status](https://img.shields.io/travis/node-modules/coffee.svg?style=flat)](https://travis-ci.org/node-modules/coffee)
[![codecov.io](https://img.shields.io/codecov/c/github/node-modules/coffee.svg?style=flat)](http://codecov.io/github/node-modules/coffee?branch=master)
[![NPM downloads](http://img.shields.io/npm/dm/coffee.svg?style=flat)](https://npmjs.org/package/coffee)

@@ -15,5 +15,5 @@

```bash
$ npm i coffee --save-dev
```
$ npm install coffee -g
```

@@ -27,9 +27,9 @@ ## Usage

it('should concat input', function(done) {
var coffee = require('coffee');
const coffee = require('coffee');
coffee.spawn('cat')
.write('1')
.write('2')
.expect('stdout', '12')
.expect('code', 0)
.end(done);
.write('1')
.write('2')
.expect('stdout', '12')
.expect('code', 0)
.end(done);
})

@@ -42,7 +42,7 @@ })

```js
coffee.fork('/path/to/file.js', ['args '])
.expect('stdout', '12\n')
.expect('stderr', '34\n')
.expect('code', 0)
.end(done);
coffee.fork('/path/to/file.js', [ 'args' ])
.expect('stdout', '12\n')
.expect('stderr', '34\n')
.expect('code', 0)
.end(done);
```

@@ -75,3 +75,3 @@

### Coffee
### coffee.Coffee

@@ -85,7 +85,7 @@ Assertion object

```js
coffee.spawn('echo', ['abcdefg'])
.expect('stdout', 'abcdefg')
.expect('stdout', /^abc/)
.expect('stdout', ['abcdefg', /abc/])
.end(done);
coffee.spawn('echo', [ 'abcdefg' ])
.expect('stdout', 'abcdefg')
.expect('stdout', /^abc/)
.expect('stdout', [ 'abcdefg', /abc/ ])
.end(done);
```

@@ -108,7 +108,7 @@

```js
coffee.fork('/path/to/cli', ['abcdefg'])
.waitForPrompt()
.write('tz\n')
.write('2\n');
.end(done);
coffee.fork('/path/to/cli', [ 'abcdefg' ])
.waitForPrompt()
.write('tz\n')
.write('2\n');
.end(done);
```

@@ -144,2 +144,12 @@

```js
coffee.fork('path/to/cli')
.expect('stdout', 'abcdefg')
.end(done);
// recommended to left undefind and use promise.
const { stdout, stderr, code } = await coffee.fork('path/to/cli').end();
assert(stdout.includes(abcdefg));
```
#### coffee.debug(level)

@@ -166,7 +176,30 @@

### coffee.Rule
Assertion Rule
you could add your custom rule, see `test/fixtures/extendable` for more details.
```js
const { Coffee, Rule } = require('coffee');
class FileRule extends Rule {
assert(actual, expected, message) {
// do sth
return super.assert(content, pattern, message);
}
}
class MyCoffee extends Coffee {
constructor(...args) {
super(...args);
this.setRule('file', FileRule);
}
}
```
## LISENCE
Copyright (c) 2017 popomore. Licensed under the MIT license.
Copyright (c) 2017 node-modules. Licensed under the MIT license.
[nyc]: https://github.com/istanbuljs/nyc
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc