Skip to content

Commit

Permalink
Merge pull request #4 from rayje/master
Browse files Browse the repository at this point in the history
Added Object type to convert JSON string value to Object
  • Loading branch information
mac- committed Jan 16, 2014
2 parents 625ab73 + 8532c16 commit c14c0d7
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The object containing the options should be formatted like so:
defaultValue: 'fnord', // optional, the value to set the option to if it wasn't specified in the args or env vars
description: 'Some description', // optional, describes the option,
required: true, // optional, if set to true and no value is found, opter will throw an error. defaults to false.
type: Number // optional, the type to convert the data to. valid values are Boolean, Number, Date, and String. defaults to String.
type: Number // optional, the type to convert the data to. valid values are Boolean, Number, Date, Object and String. defaults to String.
}
}

Expand Down
20 changes: 17 additions & 3 deletions lib/opter.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module.exports = function (options, appVersion) {
}

commander.option('-' + character + ', --' + longOptionStr, description);

}
}

Expand All @@ -155,7 +155,7 @@ module.exports = function (options, appVersion) {
configFile = {};
}
}

// save options to config obj (from command line first, env vars second, opter.json third, and defaults last)
for (optName in options) {
if (options.hasOwnProperty(optName)) {
Expand Down Expand Up @@ -188,10 +188,24 @@ module.exports = function (options, appVersion) {
value = new Date(value);
break;

case Object:
if (typeof value === 'string') {
try {
value = JSON.parse(value);
} catch (e) {
throw new Error('Option "' + optName + '" has a value that cannot be converted to an Object: ' + value);
}
} else {
if (typeof value !== 'object') {
throw new Error('Option "' + optName + '" has a value is not an Object: ' + value);
}
}
break;

default:
value = (value !== null && value !== undefined) ? value.toString() : value;
}

}
if (value === undefined && option.required) {
throw new Error('Option "' + optName + '" is not set and is required.');
Expand Down
90 changes: 77 additions & 13 deletions test/opter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('Opter Unit Tests', function() {
});

it('should throw an error when 2 or more options use the same character', function(done) {

assert.throws(function() {
var cfg = opter({
optA: {
Expand All @@ -56,7 +56,7 @@ describe('Opter Unit Tests', function() {
});

it('should read values from args', function(done) {

setCommandLineArgsAndEnvVars([
'node', './test/opter.test.js',
'--my-option-from-args1', 'args1',
Expand All @@ -79,7 +79,7 @@ describe('Opter Unit Tests', function() {
});

it('should read empty string values from args', function(done) {

setCommandLineArgsAndEnvVars([
'node', './test/opter.test.js',
'--my-option-from-args1', ''
Expand All @@ -96,7 +96,7 @@ describe('Opter Unit Tests', function() {
});

it('should read boolean values from args', function(done) {

setCommandLineArgsAndEnvVars([
'node', './test/opter.test.js',
'--my-option-from-args1'
Expand All @@ -116,7 +116,7 @@ describe('Opter Unit Tests', function() {
});

it('should read values from args and convert types', function(done) {

setCommandLineArgsAndEnvVars([
'node', './test/opter.test.js',
'--my-option-from-args1', '100',
Expand Down Expand Up @@ -150,18 +150,42 @@ describe('Opter Unit Tests', function() {
defaultValue: '0',
argument: 'string',
type: String
},
myOptionFromArgs6: {
defaultValue: '[]',
argument: 'object',
type: Object
},
myOptionFromArgs7: {
defaultValue: [],
argument: 'object',
type: Object
},
myOptionFromArgs8: {
defaultValue: '{}',
argument: 'object',
type: Object
},
myOptionFromArgs9: {
defaultValue: {},
argument: 'object',
type: Object
}
}, '0.1.0');
assert.strictEqual(cfg.myOptionFromArgs1, 100, 'myOptionFromArgs1 is: 100');
assert.strictEqual(cfg.myOptionFromArgs2, true, 'myOptionFromArgs2 is: true');
assert.strictEqual(cfg.myOptionFromArgs3.getTime(), 1234567890, 'myOptionFromArgs3 is a date with getTime of: 1234567890');
assert.strictEqual(cfg.myOptionFromArgs4.getTime(), 1374880042882, 'myOptionFromArgs4 is a date with getTime of: 1374880042882');
assert.strictEqual(cfg.myOptionFromArgs5, '0', 'myOptionFromArgs5 is : "0"');
assert.strictEqual(cfg.myOptionFromArgs6 instanceof Array, true, 'expected value to be [], got: ' + JSON.stringify(cfg.myOptionFromArgs6));
assert.strictEqual(cfg.myOptionFromArgs7 instanceof Array, true, 'expected value to be [], got: ' + JSON.stringify(cfg.myOptionFromArgs7));
assert.strictEqual(cfg.myOptionFromArgs8 instanceof Object, true, 'expected value to be {}, got: ' + JSON.stringify(cfg.myOptionFromArgs8));
assert.strictEqual(cfg.myOptionFromArgs9 instanceof Object, true, 'expected value to be {}, got: ' + JSON.stringify(cfg.myOptionFromArgs9));
done();
});

it('should read values from env', function(done) {

setCommandLineArgsAndEnvVars(null, {
myOptionFromEnv1: 'env1',
myOptionFromEnv2: 'env2'
Expand All @@ -183,7 +207,7 @@ describe('Opter Unit Tests', function() {
});

it('should read values from default value', function(done) {

setCommandLineArgsAndEnvVars();

var cfg = opter({
Expand Down Expand Up @@ -231,7 +255,7 @@ describe('Opter Unit Tests', function() {
});

it('should set options and description', function(done) {

setCommandLineArgsAndEnvVars();

var cfg = opter({
Expand Down Expand Up @@ -303,8 +327,48 @@ describe('Opter Unit Tests', function() {
done();
});

it('should throw an error if an argument value is not an object string, and type is Object', function(done) {

assert.throws(function() {
var cfg = opter({
myOptionFromArgs6: {
defaultValue: 'x',
argument: 'object',
type: Object
}
}, '0.1.0');
}, /Option .*? has a value that cannot be converted to an Object: .*?/, 'throws error');
done();
});

it('should throw an error if an argument value is not an object, and type is Object', function(done) {

assert.throws(function() {
var cfg = opter({
myOptionFromArgs6: {
defaultValue: true,
argument: 'object',
type: Object
}
}, '0.1.0');
}, /Option .*? has a value is not an Object: .*?/, 'throws error');
done();
});

it('should not throw an error if an argument value is an object string, and type is Object', function(done) {

var cfg = opter({
myOptionFromArgs6: {
defaultValue: [{"appName": "test"}],
argument: 'object',
type: Object
}
}, '0.1.0');
done();
});

it('should set options and description without default and argument', function(done) {

setCommandLineArgsAndEnvVars();

var cfg = opter({
Expand All @@ -326,7 +390,7 @@ describe('Opter Unit Tests', function() {
});

it('should automatically pick a character', function(done) {

setCommandLineArgsAndEnvVars();

var cfg = opter({
Expand Down Expand Up @@ -391,7 +455,7 @@ describe('Opter Unit Tests', function() {

done();
});

it('should read config from an opter.json file', function(done) {

// change the location of the "running file"
Expand All @@ -412,15 +476,15 @@ describe('Opter Unit Tests', function() {
});

it('should read nested config from any place', function(done) {

// change the location of the "running file"
setCommandLineArgsAndEnvVars([
'node', __dirname + '/support/opter.test.js',
'--nested.config.args', 'args1'
], {
nested_config_env: 'env1'
});

var cfg = opter({
'nested.config.file': {
defaultValue: 'default1',
Expand Down

0 comments on commit c14c0d7

Please sign in to comment.