notes/node_modules/yargs/test/usage.js

774 lines
31 KiB
JavaScript

var should = require('chai').should(),
Hash = require('hashish'),
yargs = require('../');
describe('usage', function () {
describe('demand options', function () {
describe('using .demand()', function () {
it ('should show an error along with the missing arguments on demand fail', function () {
var r = checkUsage(function () {
return yargs('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.demand(['x','y'])
.argv;
});
r.result.should.have.property('x', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage -x NUM -y NUM',
'Options:',
' -x [required]',
' -y [required]',
'Missing required arguments: y'
]);
r.logs.should.have.length(0);
r.exit.should.be.ok;
});
describe('using .require()', function() {
it ('should show an error along with the missing arguments on demand fail', function () {
var r = checkUsage(function () {
return yargs('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.require(['x','y'])
.argv;
});
r.result.should.have.property('x', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage -x NUM -y NUM',
'Options:',
' -x [required]',
' -y [required]',
'Missing required arguments: y'
]);
r.logs.should.have.length(0);
r.exit.should.be.ok;
});
});
});
it('should show an error along with a custom message on demand fail', function () {
var r = checkUsage(function () {
return yargs('-z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.demand(['x','y'], 'x and y are both required to multiply all the things')
.argv;
});
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage -x NUM -y NUM',
'Options:',
' -x [required]',
' -y [required]',
'Missing required arguments: x, y',
'x and y are both required to multiply all the things'
]);
r.logs.should.have.length(0);
r.exit.should.be.ok;
});
it('should return valid values when demand passes', function () {
var r = checkUsage(function () {
return yargs('-x 10 -y 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.demand(['x','y'])
.argv;
});
r.should.have.property('result');
r.result.should.have.property('x', 10);
r.result.should.have.property('y', 20)
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit', false);
});
});
it('should return valid values when check passes', function () {
var r = checkUsage(function () {
return yargs('-x 10 -y 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(function (argv) {
if (!('x' in argv)) throw 'You forgot about -x';
if (!('y' in argv)) throw 'You forgot about -y';
})
.argv;
});
r.should.have.property('result');
r.result.should.have.property('x', 10);
r.result.should.have.property('y', 20);
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit', false);
});
it('should display missing arguments when check fails with a thrown exception', function () {
var r = checkUsage(function () {
return yargs('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(function (argv) {
if (!('x' in argv)) throw 'You forgot about -x';
if (!('y' in argv)) throw 'You forgot about -y';
})
.argv;
});
r.should.have.property('result');
r.result.should.have.property('x', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage -x NUM -y NUM',
'You forgot about -y'
]);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
});
it('should display missing arguments when check fails with a return value', function () {
var r = checkUsage(function () {
return yargs('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(function (argv) {
if (!('x' in argv)) return 'You forgot about -x';
if (!('y' in argv)) return 'You forgot about -y';
})
.argv;
});
r.should.have.property('result');
r.result.should.have.property('x', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage -x NUM -y NUM',
'You forgot about -y'
]);
});
exports.checkFailReturn = function () {
var r = checkUsage(function () {
return yargs('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(function (argv) {
if (!('x' in argv)) return 'You forgot about -x';
if (!('y' in argv)) return 'You forgot about -y';
})
.argv;
});
r.should.have.property('result');
r.result.should.have.property('x', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage -x NUM -y NUM',
'You forgot about -y'
]);
};
it('should return a valid result when check condition passes', function () {
function checker (argv) {
return 'x' in argv && 'y' in argv;
}
var r = checkUsage(function () {
return yargs('-x 10 -y 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(checker)
.argv;
});
r.should.have.property('result');
r.result.should.have.property('x', 10);
r.result.should.have.property('y', 20);
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit', false);
});
it('should display a failed message when check condition fails', function () {
function checker (argv) {
return 'x' in argv && 'y' in argv;
}
var r = checkUsage(function () {
return yargs('-x 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM -y NUM')
.check(checker)
.argv;
});
r.should.have.property('result');
r.result.should.have.property('x', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).join('\n').should.equal(
'Usage: ./usage -x NUM -y NUM\n'
+ 'Argument check failed: ' + checker.toString()
);
});
it('should return a valid result when demanding a count of non-hyphenated values', function () {
var r = checkUsage(function () {
return yargs('1 2 3 --moo'.split(' '))
.usage('Usage: $0 [x] [y] [z] {OPTIONS}')
.demand(3)
.argv;
});
r.should.have.property('result');
r.should.have.property('errors').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit', false);
r.result.should.have.property('_').and.deep.equal([1,2,3]);
r.result.should.have.property('moo', true);
});
it('should return a failure message when not enough non-hyphenated arguments are found after a demand count', function () {
var r = checkUsage(function () {
return yargs('1 2 --moo'.split(' '))
.usage('Usage: $0 [x] [y] [z] {OPTIONS}')
.demand(3)
.argv;
});
r.should.have.property('result');
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.result.should.have.property('_').and.deep.equal([1,2]);
r.result.should.have.property('moo', true);
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [x] [y] [z] {OPTIONS}',
'Not enough non-option arguments: got 2, need at least 3'
]);
});
it('should return a custom failure message when not enough non-hyphenated arguments are found after a demand count', function () {
var r = checkUsage(function () {
return yargs('src --moo'.split(' '))
.usage('Usage: $0 [x] [y] [z] {OPTIONS} <src> <dest> [extra_files...]')
.demand(2, 'src and dest files are both required')
.argv;
});
r.should.have.property('result');
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.result.should.have.property('_').and.deep.equal(['src']);
r.result.should.have.property('moo', true);
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [x] [y] [z] {OPTIONS} <src> <dest> [extra_files...]',
'src and dest files are both required'
]);
});
it('should return a valid result when setting defaults for singles', function () {
var r = checkUsage(function () {
return yargs('--foo 50 --baz 70 --powsy'.split(' '))
.default('foo', 5)
.default('bar', 6)
.default('baz', 7)
.argv
;
});
r.should.have.property('result');
r.result.should.have.property('foo', 50);
r.result.should.have.property('bar', 6);
r.result.should.have.property('baz', 70);
r.result.should.have.property('powsy', true);
r.result.should.have.property('_').with.length(0);
});
it('should return a valid result when default is set for an alias', function () {
var r = checkUsage(function () {
return yargs('')
.alias('f', 'foo')
.default('f', 5)
.argv
;
});
r.should.have.property('result');
r.result.should.have.property('f', 5);
r.result.should.have.property('foo', 5);
r.result.should.have.property('_').with.length(0);
});
it('should print a single line when failing and default is set for an alias', function() {
var r = checkUsage(function() {
return yargs('')
.alias('f', 'foo')
.default('f', 5)
.demand(1)
.argv
;
});
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Options:',
' -f, --foo [default: 5]',
'Not enough non-option arguments: got 0, need at least 1',
]);
});
it('should allow you to set default values for a hash of options', function () {
var r = checkUsage(function () {
return yargs('--foo 50 --baz 70'.split(' '))
.default({ foo : 10, bar : 20, quux : 30 })
.argv
;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.result.should.have.property('foo', 50);
r.result.should.have.property('baz', 70);
r.result.should.have.property('bar', 20);
r.result.should.have.property('quux', 30);
});
describe('required arguments', function () {
describe('with options object', function () {
it('should show a failure message if a required option is missing', function () {
var r = checkUsage(function () {
var opts = {
foo: { description: 'foo option', alias: 'f', requiresArg: true },
bar: { description: 'bar option', alias: 'b', requiresArg: true }
};
return yargs('-f --bar 20'.split(' '))
.usage('Usage: $0 [options]', opts)
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors');
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [options]',
'Options:',
' --foo, -f foo option',
' --bar, -b bar option',
'Missing argument value: foo',
]);
});
it('should show a failure message if more than one required option is missing', function () {
var r = checkUsage(function () {
var opts = {
foo: { description: 'foo option', alias: 'f', requiresArg: true },
bar: { description: 'bar option', alias: 'b', requiresArg: true }
};
return yargs('-f --bar'.split(' '))
.usage('Usage: $0 [options]', opts)
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors');
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [options]',
'Options:',
' --foo, -f foo option',
' --bar, -b bar option',
'Missing argument values: foo, bar',
]);
});
});
describe('with requiresArg method', function () {
it('should show a failure message if a required option is missing', function () {
var r = checkUsage(function () {
var opts = {
foo: { description: 'foo option', alias: 'f' },
bar: { description: 'bar option', alias: 'b' }
};
return yargs('-f --bar 20'.split(' '))
.usage('Usage: $0 [options]', opts)
.requiresArg(['foo', 'bar'])
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors');
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [options]',
'Options:',
' --foo, -f foo option',
' --bar, -b bar option',
'Missing argument value: foo',
]);
});
});
});
context("with strict() option set", function () {
it('should fail given an option argument that is not demanded', function () {
var r = checkUsage(function () {
opts = {
foo: { demand: 'foo option', alias: 'f' },
bar: { demand: 'bar option', alias: 'b' }
};
return yargs('-f 10 --bar 20 --baz 30'.split(' '))
.usage('Usage: $0 [options]', opts)
.strict()
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.result.should.have.property('f', 10);
r.result.should.have.property('foo', 10);
r.result.should.have.property('b', 20);
r.result.should.have.property('bar', 20);
r.result.should.have.property('baz', 30);
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [options]',
'Options:',
' --foo, -f [required]',
' --bar, -b [required]',
'Unknown argument: baz',
]);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
});
it('should fail given an option argument without a corresponding description', function () {
var r = checkUsage(function () {
opts = {
foo: { description: 'foo option', alias: 'f' },
bar: { description: 'bar option', alias: 'b' }
};
return yargs('-f 10 --bar 20 --baz 30'.split(' '))
.usage('Usage: $0 [options]', opts)
.strict()
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.result.should.have.property('f', 10);
r.result.should.have.property('foo', 10);
r.result.should.have.property('b', 20);
r.result.should.have.property('bar', 20);
r.result.should.have.property('baz', 30);
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [options]',
'Options:',
' --foo, -f foo option',
' --bar, -b bar option',
'Unknown argument: baz',
]);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
});
it('should fail given multiple option arguments without corresponding descriptions', function () {
var r = checkUsage(function () {
opts = {
foo: { description: 'foo option', alias: 'f' },
bar: { description: 'bar option', alias: 'b' }
};
return yargs('-f 10 --bar 20 --baz 30 -q 40'.split(' '))
.usage('Usage: $0 [options]', opts)
.strict()
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.result.should.have.property('f', 10);
r.result.should.have.property('foo', 10);
r.result.should.have.property('b', 20);
r.result.should.have.property('bar', 20);
r.result.should.have.property('baz', 30);
r.result.should.have.property('q', 40);
r.should.have.property('errors');
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage [options]',
'Options:',
' --foo, -f foo option',
' --bar, -b bar option',
'Unknown arguments: baz, q',
]);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
});
it('should pass given option arguments with corresponding descriptions', function () {
var r = checkUsage(function () {
opts = {
foo: { description: 'foo option' },
bar: { description: 'bar option' }
};
return yargs('--foo 10 --bar 20'.split(' '))
.usage('Usage: $0 [options]', opts)
.strict()
.argv;
});
r.should.have.property('result');
r.result.should.have.property('foo', 10);
r.result.should.have.property('bar', 20)
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors').with.length(0);
r.should.have.property('logs').with.length(0);
r.should.have.property('exit', false);
});
});
it('should display example on fail', function () {
var r = checkUsage(function () {
return yargs('')
.example("$0 something", "description")
.example("$0 something else", "other description")
.demand(['y'])
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors');
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.errors.join('\n').split(/\n+/).should.deep.equal([
'Examples:',
' ./usage something description',
' ./usage something else other description',
'Options:',
' -y [required]',
'Missing required arguments: y'
]);
});
describe('demand option with boolean flag', function () {
describe('with demand option', function () {
it('should report missing required arguments', function () {
var r = checkUsage(function () {
return yargs('-y 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM [-y NUM]')
.options({
'x': { description: 'an option', demand: true },
'y': { description: 'another option', demand: false }
})
.argv;
});
r.result.should.have.property('y', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.errors.join('\n').split(/\n/).should.deep.equal([
'Usage: ./usage -x NUM [-y NUM]',
'',
'Options:',
' -x an option [required]',
' -y another option',
'',
'Missing required arguments: x'
]);
r.logs.should.have.length(0);
r.exit.should.be.ok;
});
});
describe('with required option', function () {
it('should report missing required arguments', function () {
var r = checkUsage(function () {
return yargs('-y 10 -z 20'.split(' '))
.usage('Usage: $0 -x NUM [-y NUM]')
.options({
'x': { description: 'an option', required: true },
'y': { description: 'another option', required: false }
})
.argv;
});
r.result.should.have.property('y', 10);
r.result.should.have.property('z', 20);
r.result.should.have.property('_').with.length(0);
r.errors.join('\n').split(/\n/).should.deep.equal([
'Usage: ./usage -x NUM [-y NUM]',
'',
'Options:',
' -x an option [required]',
' -y another option',
'',
'Missing required arguments: x'
]);
r.logs.should.have.length(0);
r.exit.should.be.ok;
});
});
it('should not report missing required arguments when given an alias', function () {
var r = checkUsage(function () {
return yargs('-w 10'.split(' '))
.usage('Usage: $0 --width NUM [--height NUM]')
.options({
'width': { description: 'Width', alias: 'w', demand: true },
'height': { description: 'Height', alias: 'h', demand: false }
})
.argv;
});
r.result.should.have.property('w', 10);
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors').with.length(0);
r.logs.should.have.length(0);
});
});
describe('help option', function () {
it('should display usage', function () {
var r = checkUsage(function () {
return yargs(['--help'])
.demand(['y'])
.help('help')
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors');
r.should.have.property('logs').with.length(1);
r.should.have.property('exit').and.be.ok;
r.logs.join('\n').split(/\n+/).should.deep.equal([
'Options:',
' --help Show help',
' -y [required]',
''
]);
});
it('should not show both dashed and camelCase aliases', function () {
var r = checkUsage(function () {
return yargs(['--help'])
.usage('Usage: $0 options')
.help('help')
.describe('some-opt', 'Some option')
.default('some-opt', 2)
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('exit').and.be.ok;
r.should.have.property('errors').with.length(0);
r.should.have.property('logs');
r.logs.join('\n').split(/\n+/).should.deep.equal([
'Usage: ./usage options',
'Options:',
' --help Show help ',
' --some-opt Some option [default: 2]',
''
]);
});
});
describe('version option', function () {
it('should display version', function () {
var r = checkUsage(function () {
return yargs(['--version'])
.version('1.0.1', 'version', 'Show version number')
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors');
r.should.have.property('logs').with.length(1);
r.should.have.property('exit').and.be.ok;
r.logs.join('\n').split(/\n+/).should.deep.equal([
'1.0.1'
]);
});
});
describe('showHelpOnFail', function () {
it('should display user supplied message', function () {
var opts = {
foo: { desc: 'foo option', alias: 'f' },
bar: { desc: 'bar option', alias: 'b' }
};
var r = checkUsage(function () {
return yargs(['--foo'])
.usage('Usage: $0 [options]')
.options(opts)
.demand(['foo', 'bar'])
.showHelpOnFail(false, "Specify --help for available options")
.argv;
});
r.should.have.property('result');
r.result.should.have.property('_').with.length(0);
r.should.have.property('errors');
r.should.have.property('logs').with.length(0);
r.should.have.property('exit').and.be.ok;
r.errors.join('\n').split(/\n/).should.deep.equal([
'Missing required arguments: bar',
'',
'Specify --help for available options'
]);
});
});
it('should succeed when rebase', function () {
yargs.rebase('/home/chevex', '/home/chevex/foo/bar/baz').should.equal('./foo/bar/baz');
yargs.rebase('/home/chevex/foo/bar/baz', '/home/chevex').should.equal('../../..');
yargs.rebase('/home/chevex/foo', '/home/chevex/pow/zoom.txt').should.equal('../pow/zoom.txt');
});
function checkUsage (f) {
var exit = false;
process._exit = process.exit;
process._env = process.env;
process._argv = process.argv;
process.stdout._write = process.stdout.write;
process.exit = function () { exit = true };
process.env = Hash.merge(process.env, { _ : 'node' });
process.argv = [ './usage' ];
process.stdout.write = function (msg) { logs.push(msg) };
var errors = [];
var logs = [];
console._error = console.error;
console.error = function (msg) { errors.push(msg) };
console._log = console.log;
console.log = function (msg) { logs.push(msg) };
var result = f();
process.exit = process._exit;
process.env = process._env;
process.argv = process._argv;
process.stdout.write = process.stdout._write;
console.error = console._error;
console.log = console._log;
return {
errors : errors,
logs : logs,
exit : exit,
result : result
};
};
});