Skip to content

Commit

Permalink
chore: update after merge into node.js core
Browse files Browse the repository at this point in the history
  • Loading branch information
Eomm committed Oct 7, 2022
1 parent 7f68c46 commit b2f6a44
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 64 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ changes:
times. If `true`, all values will be collected in an array. If
`false`, values for the option are last-wins. **Default:** `false`.
* `short` {string} A single character alias for the option.
* `default` {string | boolean | string[] | boolean[]} The default option value when it is not set by args.
* `default` {string | boolean | string\[] | boolean\[]} The default option
value when it is not set by args. It must be of the same type as the
the `type` property. When `multiple` is `true`, it must be an array.
* `strict` {boolean} Should an error be thrown when unknown arguments
are encountered, or when arguments are passed that do not match the
`type` configured in `options`.
Expand Down
22 changes: 12 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,17 +331,19 @@ const parseArgs = (config = kEmptyObject) => {
validateBoolean(multipleOption, `options.${longOption}.multiple`);
}

if (ObjectHasOwn(optionConfig, 'default')) {
const defaultValue = objectGetOwn(optionConfig, 'default');
if (optionType === 'string' && !multipleOption) {
validateString(defaultValue, `options.${longOption}.default`);
} else if (optionType === 'string' && multipleOption) {
validateStringArray(defaultValue, `options.${longOption}.default`);
} else if (optionType === 'boolean' && !multipleOption) {
validateBoolean(defaultValue, `options.${longOption}.default`);
} else if (optionType === 'boolean' && multipleOption) {
validateBooleanArray(defaultValue, `options.${longOption}.default`);
const defaultValue = objectGetOwn(optionConfig, 'default');
if (defaultValue !== undefined) {
let validator;
switch (optionType) {
case 'string':
validator = multipleOption ? validateStringArray : validateString;
break;

case 'boolean':
validator = multipleOption ? validateBooleanArray : validateBoolean;
break;
}
validator(defaultValue, `options.${longOption}.default`);
}
}
);
Expand Down
101 changes: 49 additions & 52 deletions test/default-values.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,78 @@
'use strict';

/* global assert */
/* eslint max-len: 0 */
'use strict';

const test = require('tape');
const { test } = require('./utils');
const { parseArgs } = require('../index.js');

test('default must be a boolean when option type is boolean', (t) => {
test('default must be a boolean when option type is boolean', () => {
const args = [];
const options = { alpha: { type: 'boolean', default: 'not a boolean' } };
t.throws(() => {
assert.throws(() => {
parseArgs({ args, options });
}, /alpha\.default must be Boolean/
}, /options\.alpha\.default must be Boolean/
);
t.end();
});

test('default must be a boolean array when option type is boolean and multiple', (t) => {
test('default must accept undefined value', () => {
const args = [];
const options = { alpha: { type: 'boolean', default: undefined } };
const result = parseArgs({ args, options });
const expected = {
values: {
__proto__: null,
},
positionals: []
};
assert.deepStrictEqual(result, expected);
});

test('default must be a boolean array when option type is boolean and multiple', () => {
const args = [];
const options = { alpha: { type: 'boolean', multiple: true, default: 'not an array' } };
t.throws(() => {
assert.throws(() => {
parseArgs({ args, options });
}, /alpha\.default must be Array/
}, /options\.alpha\.default must be Array/
);
t.end();
});

test('default must be a boolean array when option type is string and multiple is true', (t) => {
test('default must be a boolean array when option type is string and multiple is true', () => {
const args = [];
const options = { alpha: { type: 'boolean', multiple: true, default: [true, true, 42] } };
t.throws(() => {
assert.throws(() => {
parseArgs({ args, options });
}, /alpha\.default\[2\] must be Boolean/
}, /options\.alpha\.default\[2\] must be Boolean/
);
t.end();
});

test('default must be a string when option type is string', (t) => {
test('default must be a string when option type is string', () => {
const args = [];
const options = { alpha: { type: 'string', default: true } };
t.throws(() => {
assert.throws(() => {
parseArgs({ args, options });
}, /alpha\.default must be String/
}, /options\.alpha\.default must be String/
);
t.end();
});

test('default must be an array when option type is string and multiple is true', (t) => {
test('default must be an array when option type is string and multiple is true', () => {
const args = [];
const options = { alpha: { type: 'string', multiple: true, default: 'not an array' } };
t.throws(() => {
assert.throws(() => {
parseArgs({ args, options });
}, /alpha\.default must be Array/
}, /options\.alpha\.default must be Array/
);
t.end();
});

test('default must be a string array when option type is string and multiple is true', (t) => {
test('default must be a string array when option type is string and multiple is true', () => {
const args = [];
const options = { alpha: { type: 'string', multiple: true, default: ['str', 42] } };
t.throws(() => {
assert.throws(() => {
parseArgs({ args, options });
}, /alpha\.default\[1\] must be String/
}, /options\.alpha\.default\[1\] must be String/
);
t.end();
});

test('default accepted input when multiple is true', (t) => {
test('default accepted input when multiple is true', () => {
const args = ['--inputStringArr', 'c', '--inputStringArr', 'd', '--inputBoolArr', '--inputBoolArr'];
const options = {
inputStringArr: { type: 'string', multiple: true, default: ['a', 'b'] },
Expand All @@ -84,11 +91,10 @@ test('default accepted input when multiple is true', (t) => {
fullBoolArr: [false, true, false] },
positionals: [] };
const result = parseArgs({ args, options });
t.deepEqual(result, expected);
t.end();
assert.deepStrictEqual(result, expected);
});

test('when default is set, the option must be added as result', (t) => {
test('when default is set, the option must be added as result', () => {
const args = [];
const options = {
a: { type: 'string', default: 'HELLO' },
Expand All @@ -98,12 +104,10 @@ test('when default is set, the option must be added as result', (t) => {
const expected = { values: { __proto__: null, a: 'HELLO', b: false, c: true }, positionals: [] };

const result = parseArgs({ args, options });

t.deepEqual(result, expected);
t.end();
assert.deepStrictEqual(result, expected);
});

test('when default is set, the args value takes precedence', (t) => {
test('when default is set, the args value takes precedence', () => {
const args = ['--a', 'WORLD', '--b', '-c'];
const options = {
a: { type: 'string', default: 'HELLO' },
Expand All @@ -113,12 +117,10 @@ test('when default is set, the args value takes precedence', (t) => {
const expected = { values: { __proto__: null, a: 'WORLD', b: true, c: true }, positionals: [] };

const result = parseArgs({ args, options });

t.deepEqual(result, expected);
t.end();
assert.deepStrictEqual(result, expected);
});

test('tokens should not include the default options', (t) => {
test('tokens should not include the default options', () => {
const args = [];
const options = {
a: { type: 'string', default: 'HELLO' },
Expand All @@ -129,11 +131,10 @@ test('tokens should not include the default options', (t) => {
const expectedTokens = [];

const { tokens } = parseArgs({ args, options, tokens: true });
t.deepEqual(tokens, expectedTokens);
t.end();
assert.deepStrictEqual(tokens, expectedTokens);
});

test('tokens:true should not include the default options after the args input', (t) => {
test('tokens:true should not include the default options after the args input', () => {
const args = ['--z', 'zero', 'positional-item'];
const options = {
z: { type: 'string' },
Expand All @@ -148,11 +149,10 @@ test('tokens:true should not include the default options after the args input',
];

const { tokens } = parseArgs({ args, options, tokens: true, allowPositionals: true });
t.deepEqual(tokens, expectedTokens);
t.end();
assert.deepStrictEqual(tokens, expectedTokens);
});

test('proto as default value must be ignored', (t) => {
test('proto as default value must be ignored', () => {
const args = [];
const options = Object.create(null);

Expand All @@ -161,17 +161,14 @@ test('proto as default value must be ignored', (t) => {

const result = parseArgs({ args, options, allowPositionals: true });
const expected = { values: { __proto__: null }, positionals: [] };
t.deepEqual(result, expected);
t.end();
assert.deepStrictEqual(result, expected);
});


test('multiple as false should expect a String', (t) => {
test('multiple as false should expect a String', () => {
const args = [];
const options = { alpha: { type: 'string', multiple: false, default: ['array'] } };
t.throws(() => {
assert.throws(() => {
parseArgs({ args, options });
}, /alpha\.default must be String/
);
t.end();
}, / must be String got array/);
});
2 changes: 1 addition & 1 deletion utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function findLongOptionForShort(shortOption, options) {
*/
function useDefaultValueOption(longOption, optionConfig, values) {
return objectGetOwn(optionConfig, 'default') !== undefined &&
values[longOption] === undefined;
values[longOption] === undefined;
}

module.exports = {
Expand Down

0 comments on commit b2f6a44

Please sign in to comment.