cline
Version:
Command-line apps building library for Node
301 lines (294 loc) • 11.5 kB
JavaScript
if (module == require.main) {
var mochaPath = 'node_modules/mocha/bin/mocha';
var args = [mochaPath, '--colors', '--growl', '--require', 'should', '--reporter', 'tap', __filename];
var proc = require('child_process').spawn(process.argv[0], args, {stdio: 'inherit'});
proc.on('close', function (code) {
process.exit(code);
});
} else {
var cli = require('./index')(undefined, true);
var should = require('should');
var nop = function () {
};
var stream = function (input, output) {
return {
p: '>',
close: nop,
write: function (str) {
var o = output;
if (Array.isArray(output)) {
o = output.shift();
}
if (o && str !== o) {
throw new Error('Expectations failed:' + o + ' got ' + str);
}
},
print: function (str) {
this.write(str);
},
setPrompt: function (str) {
this.p = str;
},
prompt: function () {
this.write(this.p);
if (this.online) {
var i = input;
if (Array.isArray(input)) {
i = input.shift();
}
if (i) {
this.online(i);
this.write(i);
}
}
},
emit: function(evt, i) {
if (input && evt === 'line') {
this.online(i);
}
},
once: nop,
on: function (evt, fn) {
if (input && evt === 'line') {
this.online = fn;
}
},
removeAllListeners: nop
}
};
describe('cli', function () {
afterEach(function () {
cli.clean();
});
it('should prompt', function () {
cli.init(stream('abc', ['test>', 'abc']));
cli.prompt('test>');
});
it('should fail on wrong expectations', function () {
(function () {
cli.init(stream('abc', ['prompt>', 'abc']));
cli.prompt('test>');
}).should.throw('Expectations failed:prompt> got test>');
});
it('should prompt for password with mask', function () {
cli.init(stream('abc', ['pass', 'abc']));
cli.password('pass', '*');
});
it('should prompt for confirm with false', function (done) {
cli.init(stream('abc'));
cli.confirm('sure?', function (ok) {
ok.should.be.not.ok;
done();
});
});
it('should prompt for confirm with true', function (done) {
cli.init(stream('y'));
cli.confirm('sure?', function (ok) {
ok.should.be.ok;
done();
});
});
it('should interact', function (done) {
cli.init(stream(['abc', '\\q']));
cli.stream.close = function () {
done();
};
cli.interact('i>');
});
it('should allow negotiations during interact', function (done) {
var s = '';
cli.init(stream(['abc', 'aaa']));
cli.interact('i>');
cli.password('pass', function(pass) {
pass.should.eql('try', 'pass');
});
cli.init(stream(['try', '\\q']));
cli.stream.close = function () {
done();
};
});
it('should print usage by command', function () {
cli.init(stream('\\?', ['i>', 'usage:\nstart - start command\nstop \n' +
'exit, \\q - close shell and exit\nhelp, \\? - print this usage\nclear, \\c - clear the terminal screen']));
cli.command('start', 'start command', {}, nop);
cli.command('stop', nop);
cli.prompt('i>');
});
it('should print usage', function () {
cli.init(undefined);
cli.command('start', 'start command', {}, nop);
cli.command('stop', nop);
cli.usage().should.eql('usage:\nstart - start command\nstop \n' +
'exit, \\q - close shell and exit\nhelp, \\? - print this usage\nclear, \\c - clear the terminal screen', 'usage');
});
it('should fire history', function (done) {
cli.init(stream('aaa'));
cli.on('history', function (line) {
line.should.eql('aaa', 'history item');
done();
});
cli.prompt('i>');
});
it('should add history items', function () {
cli.init(undefined);
cli.history(['a', 'b', 'c']);
cli.history().should.eql(['c', 'b', 'a'], 'history');
});
it('should fill completer', function (done) {
cli.init();
cli.command('start', nop);
cli.command('stop', nop);
cli.stream.completer('s', function (err, res) {
res[0].should.eql(['start', 'stop'], 'completions');
done();
});
});
it('should parse command', function (done) {
cli.command('#{number}{cmd}', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-'}, function (input, args) {
args.number.should.eql(12, 'number');
args.cmd.should.eql('x', 'command');
done();
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('#12x');
});
it('should parse command medium declaration', function (done) {
cli.command('#aaa', 'do aaa', function (input) {
input.should.eql('#aaa', 'input');
done();
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('#aaa');
});
it('should parse command short declaration', function (done) {
cli.command('#aaa', function (input) {
input.should.eql('#aaa', 'input');
done();
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('#aaa');
});
it('should respect empty string in command', function (done) {
cli.command('#{number}{cmd}', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-|'}, function (input, args) {
args.number.should.eql(12, 'number');
args.cmd.should.eql('', 'command');
done();
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('#12');
});
it('should respect special chars', function (done) {
cli.command('?{number}+{cmd}$', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-|'}, function (input, args) {
args.number.should.eql(12, 'number');
args.cmd.should.eql('x', 'command');
done();
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('?12+x$');
});
it('should respect inner groups', function (done) {
cli.command('?{numbers}{cmd}', 'task command by numbers', {numbers: '((\\d)+,?)+', cmd:'x|>|<'}, function (input, args) {
args.numbers.should.eql('12,3', 'numbers');
args.cmd.should.eql('>', 'command');
done();
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('?12,3>');
});
it('should parse command and return', function () {
cli.command('#{number}{cmd}', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-'}, function (input, args) {
args.number.should.eql(12, 'number');
args.cmd.should.eql('x', 'command');
return 'cool';
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('#12x').should.eql('cool', 'return');
});
it('should fire command', function (done) {
cli.command('{str}', '', {str:'[A-Za-z]+'});
cli.command('{number}', '', {number:'\\d+'});
cli.once('command', function(input, cmd) {
input.should.eql('aaaa', 'string');
cmd.should.eql('{str}', 'cmd');
done();
});
cli.parse('aaaa');
});
it('should match whole command', function (done) {
cli.command('{str}', '', {str:'[A-Za-z]+'});
cli.command('{str} {str}', '', {str:'\\w+'});
cli.once('command', function(input, cmd) {
cmd.should.eql('{str} {str}', 'cmd');
input.should.eql('aaaa bbb', 'string');
done();
});
cli.parse('aaaa bbb');
});
it('should override command', function (done) {
cli.command('#{number}{cmd}', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-'}, function () {
console.log('wrong');
});
cli.command('#{number}{cmd}', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-'}, function (input, args) {
args.number.should.eql(12, 'number');
args.cmd.should.eql('x', 'command');
done();
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.parse('#12x');
});
it('should respect command order', function (done) {
cli.command('#{number}{cmd}', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-'}, function () {
console.log('wrong');
});
cli.command('*', function (input) {
throw new Error(input);
});
cli.command('#{number}x', 'task command by number', {number: '\\d{1,3}'}, function () {
console.log('wrong');
});
cli.command('#{number}{cmd}', 'task command by number', {number: '\\d{1,3}', cmd: 'x|\\+|-'}, function (input, args) {
args.number.should.eql(12, 'number');
args.cmd.should.eql('x', 'command');
done();
});
cli.parse('#12x');
});
it('should support modes', function (done) {
cli.mode('a', function () {
done();
});
cli.mode('b', function () {
cli.parse('a');
});
cli.parse('b');
});
it('should clean commands on mode', function (done) {
cli.mode('a', function () {
should.not.exist(cli.parse('test'));
done();
});
cli.mode('b', function () {
cli.command('test', nop);
cli.parse('test').should.be.ok;
cli.parse('a');
});
cli.parse('b');
});
});
}