Skip to content

Commit

Permalink
1st
Browse files Browse the repository at this point in the history
  • Loading branch information
mklabs committed Jul 18, 2012
0 parents commit 1bd8290
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 0 deletions.
153 changes: 153 additions & 0 deletions lib/test.js
@@ -0,0 +1,153 @@


var exec = require('child_process').exec,
util = require('util'),
events = require('events');


//
// Main assertion thingy. First rough work.
//
// Thx to @visionmedia, based off supertest's Test object:
// https://github.com/visionmedia/supertest/blob/master/lib/test.js
//


module.exports = Test;

// Initialize a new `Test` with the given `options` Hash object.

function Test(o) {
this.options = o || {};
this._body = '';
this._status = 0;
this._command = '';
}

// inherits from EventEmitter

util.inherits(Test, events.EventEmitter);

//
// Expectations:
//
// .expect(0)
// .expect(0, fn)
// .expect(0, body)
// .expect('Some body')
// .expect('Some body', fn)
//

Test.prototype.expect = function(a, b){
var self = this;

// callback
if (typeof b === 'function') this.end(b);

// status
if (typeof a === 'number') {
this._status = a;
// body
if (b && typeof b !== 'function') this._body = b;
return this;
}

// body
this._body = a;

return this;
};

//

Test.prototype.end = function(fn) {
this.assert(res, fn);
return this;
};

//
// Setup CLI location and default arguments.
//

Test.prototype.use = function (command) {
this._command = command;
return this;
};

//
// Defer invoking `.end()` until
// the command is done running.
//

Test.prototype.end = function(fn) {
var self = this;

this.run(function(err, stdout, stderr) {
var code = err ? err.code : 0;

self.emit('done');

self.assert({
status: code,
text: (stdout || stderr),
err: err
}, fn);
});

return this;
};

//
// Add topic to current (or root) vow
//

Test.prototype.run = function (fn) {
var cmd = this._command;

if(!cmd) return this.emit(new Error('Cannot run withou a command. Use .use!'));

this.emit('run');

// Execute defined command with arguments and passed options
exec(cmd, fn);

return this;
};


// Perform assertions and invoke `fn(err)`.

Test.prototype.assert = function(res, fn) {
var status = this._status,
body = this._body,
isregexp = body instanceof RegExp,
expected,
actual,
re;

// status
if (status && res.status !== status) {
return fn(new Error('expected ' + status + ', got ' + res.status), res);
}

// body
if (body != null) {
// string
actual = util.inspect(res.text);
expected = util.inspect(body);

if (body !== res.text) {
// regexp
if (isregexp) {
if (!body.test(res.text)) {
return fn(new Error('expected body ' + res.text + ' to match ' + body));
}
} else {
return fn(new Error('expected ' + expected + ' response body, got ' + actual));
}
}
}

fn(null, res);
};

10 changes: 10 additions & 0 deletions main.js
@@ -0,0 +1,10 @@

var Test = require('./lib/test');

module.exports = cli;
cli.Test = Test;

function cli(o) {
o = o || {};
return new Test(o);
}
16 changes: 16 additions & 0 deletions package.json
@@ -0,0 +1,16 @@
{
"name": "clt",
"version": "0.0.1",
"description": "Easy way to run assertions against CLI tools.",
"main": "main.js",
"directories": {
"test": "test"
:q
},
"scripts": {
"test": "node node_modules/mocha/bin/mocha --reporter spec"
},
"devDependencies": {
"mocha": "~1.3.0"
}
}
80 changes: 80 additions & 0 deletions readme.md
@@ -0,0 +1,80 @@
clt
===

**Inspired / Based off both
[cli-easy](https://github.com/flatiron/cli-easy) and
[supertest](https://github.com/visionmedia/supertest)**

> A fluent (i.e. chainable) syntax for generating vows tests for CLI applications.
> HTTP assertions made easy via super-agent.
Description
-----------

- Struggling with testing cli tools.
- cli-easy is super great, but designed for generating vows
- supertest is super great, but designed to make HTTP assertions via
super-agent.

clt is nothing more than a simple, chainable API to ease the process of
testing CLI applications & tools.

Right now, it doesn't do anything fancy and just allow you to easily
test the exit code and stdout output, and make assertions on top of
that.

Example
-------

It should work with any test framework, here is an example using any
test framework at all.

```js
var cli = require('clt');

cli()
.use('uname')
.expect(0, 'Linux\n')
.end(function(err, stdout, stderr) {
if(err) throw err;
});
```

Here's an example with mocha, note how you can pass done straight to any
of the `.expect()` calls (or `.end()`):

```js
describe('test uname', function() {
it('respond with Linux', function(done) {
cli()
.use('uname')
.expect('should return Linux', 'Linux\n')
.expect(0, done)
});
});
```

fancier example.

```js
describe('Testing on a wtf thing', function() {
it('should fail as expected', function(done) {
cli()
.use('wtfBinary')
.expect(127, /command not found/)
.end(done);
});
});
```

API
---

> tbd
- expect(code, fn)
- expect(code, body, [fn])
- expect(body, [fn])
- end(fn)

21 changes: 21 additions & 0 deletions test/cli.js
@@ -0,0 +1,21 @@

var cli = require('..');

describe('Testing on uname', function() {
it('should return Linux ', function(done) {
cli()
.use('uname')
.expect(0, 'Linux\n')
.end(done);
});
});

describe('Testing on a wtf thing', function() {
it('should fail as expected', function(done) {
cli()
.use('wtfBinary')
.expect(127, /command not found/)
.end(done);
});
});

0 comments on commit 1bd8290

Please sign in to comment.