Skip to content

Commit

Permalink
Document api
Browse files Browse the repository at this point in the history
  • Loading branch information
mklabs committed Apr 25, 2016
1 parent 6c22c97 commit d7dd12f
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 126 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
api.md
.tern-port
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -4,7 +4,8 @@
"description": "CLI assertions made easy",
"main": "main.js",
"scripts": {
"test": "ava test/*.js"
"test": "DEBUG=gentle-cli ava test/*.js",
"docs": "tomdox test.js --json | node scripts/docs.js > api.md"
},
"devDependencies": {
"ava": "^0.14.0",
Expand Down
187 changes: 84 additions & 103 deletions readme.md
@@ -1,38 +1,39 @@
clt
===
gentle-cli
==========

**Inspired / Based off both
[cli-easy](https://github.com/flatiron/cli-easy) and
[supertest](https://github.com/visionmedia/supertest)**
**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
-----------
> CLI assertions made easy.
- 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.
- 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
gentle-cli 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.
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
-------
## Documentation

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

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

// promise
cli()
.use('whoami')
.expect(0, 'A fool')
.then(function(res) {
console.log(res.status);
console.log(res.text);
console.log(res.err);
});

// callback
cli()
.use('uname')
.expect(0, 'Linux\n')
Expand All @@ -41,6 +42,35 @@ cli()
});
```

#### ava

Check [gentle cli tests](./test), they're using ava:

```js
import test from 'ava';
import cli from '..';
import constants from 'constants';

test('Testing on uname', t => {
return cli()
.use('uname')
.expect(0, process.platform === 'darwin' ? 'Darwin' : 'Linux')
.end();
});

test('Testing on a wtf thing', t => {
return cli()
.use('wtfBinary')
.expect(constants.ENOENT)
.throws('ENOENT')
.end();
});
```

`cli().end()` returns a promise you can pass through ava, as well as `.then()` and `.catch()`.

#### mocha

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

Expand Down Expand Up @@ -68,120 +98,71 @@ describe('Testing on a wtf thing', function() {
});
```

API
---
### API

<p>Main assertion thingy. First rough work.</p>
#### module.exports = Runnable;

<p>Thx to @visionmedia, based off supertest's Runnable object:<br /><a href='https://github.com/visionmedia/supertest/blob/master/lib/Runnable.js'>https://github.com/visionmedia/supertest/blob/master/lib/Runnable.js</a></p>
Main assertion thingy

<pre><code>
</code></pre>
Thx to @visionmedia, based off supertest's Runnable object:
https://github.com/visionmedia/supertest/blob/master/lib/Runnable.js


<p>inherits from EventEmitter</p>
#### function Runnable(cmds, options)

<pre><code>
util.inherits(Runnable, events.EventEmitter);</code></pre>
Initialize a new `Runnable` with the given `options` Hash object.


### Runnable.prototype.use()
<p>Setup CLI command.</p>
#### Runnable#use()

<pre><code>
Runnable.prototype.use = function use(command) {
this._command = command;
return this;
};</code></pre>
Setup CLI command.


### Runnable.prototype.expect()
<p>Adds a new expctations to this runnable instance.</p>
#### Runnable#expect()

<h2>Examples</h2>
Adds a new expectation to this runnable instance.

<pre><code>.expect(0)
```js:
.expect(0)
.expect(0, fn)
.expect(0, body)
.expect('Some body')
.expect('Some body', fn)
</code></pre>

<p>Returns the runnable.</p>

<pre><code>
Runnable.prototype.expect = function expect(a, b) {
var self = this;

if (typeof a === 'number') {
this._status = a;
if (b && typeof b !== 'function') this.addExpectation(b);
else if(typeof b === 'function') this.end(b);
return this;
}

this.addExpectation(a);

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

return this;
};</code></pre>


### Runnable.prototype.addExpectation()
<p>Adds a new expectation to the list of expected result. Can be either a<br />regexp or a string, in which case direct indexOf match</p>

<pre><code>
Runnable.prototype.addExpectation = function addExpectation(match) {
this._expects.push(match);
};</code></pre>


### Runnable.prototype.prompt()
<p>Adds a new prompt hook to the list of expected prompts, automatically<br />writes the <code>answer</code> string provided to child's stdin when the<br /><code>matcher</code> RegExp or String match a given prompt in child stdout.</p>
```
#### Runnable#throws()

<pre><code>
Runnable.prototype.prompt = function prompt(matcher, answer) {
matcher = matcher instanceof RegExp ? matcher : new RegExp(matcher, 'i');
this._prompts.push({
matcher: matcher,
answer: (answer || '') + '\n'
});
return this;
};</code></pre>
Adds a new expectation to this runnable instance.

```js:
.throws(0)
.throws('ENOENT')
.throws(require('constants').ENOENT)
```

### Runnable.prototype.end()
<p>Defer invoking <code>.end()</code> until the command is done running.</p>
#### Runnable#end()

<h2>Examples</h2>
Defer invoking `.end()` until the command is done running.

<pre><code>it('test thing', function(done) {
```js:
it('test thing', function(done) {
cli()
.use('thing')
.expect(/run thing/)
.end(done);
});
</code></pre>
```

<p>Returns the runnable instance.</p>
Returns a promise.

<pre><code>
Runnable.prototype.end = function end(fn) {
var self = this;
fn = fn || function() {};
#### Runnable#then()

this.run(function(err, code, stdout, stderr) {
self.emit('done');
self.emit('end');
Automatically invokes `end()` and register the callback.

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


#### Runnable#catch()

return this;
};</code></pre>
Automatically invokes `end()` and register the errback.

Returns a promise.
30 changes: 30 additions & 0 deletions scripts/docs.js
@@ -0,0 +1,30 @@

var stdin = process.stdin;

stdin.setEncoding('utf8');

var json = ''
stdin.on('readable', () => {
var chunk = process.stdin.read();
if (chunk !== null) {
json += chunk;
}
});

stdin.on('end', () => {
var data = JSON.parse(json);

var file = data.find((f) => {
return f.file === 'test';
});

file.tomdocs.forEach((doc) => {
console.log(`#### ${doc.identifier}
${doc.description}
${doc.examples ? '```js' + doc.examples + '```' : ''}`);
});

// console.log(file);
});

0 comments on commit d7dd12f

Please sign in to comment.