Skip to content

Commit f8d9140

Browse files
test: enhance help option tests
1 parent 55b29d5 commit f8d9140

File tree

1 file changed

+253
-124
lines changed

1 file changed

+253
-124
lines changed

test/parallel/test-parse-args.mjs

Lines changed: 253 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,138 +1063,267 @@ test('auto-detect --no-foo as negated when strict:false and allowNegative', () =
10631063
process.execArgv = holdExecArgv;
10641064
});
10651065

1066-
test('help arg value config must be a string', () => {
1067-
const args = ['-f', 'bar'];
1068-
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1069-
const help = true;
1070-
assert.throws(() => {
1071-
parseArgs({ args, options, help });
1072-
}, /The "help" argument must be of type string/
1073-
);
1074-
});
1066+
// Test help option
1067+
{
1068+
test('help arg value config must be a string', () => {
1069+
const args = ['-f', 'bar'];
1070+
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1071+
const help = true;
1072+
assert.throws(() => {
1073+
parseArgs({ args, options, help });
1074+
}, /The "help" argument must be of type string/
1075+
);
1076+
});
10751077

1076-
test('help value for option must be a string', () => {
1077-
const args = [];
1078-
const options = { alpha: { type: 'string', help: true } };
1079-
assert.throws(() => {
1080-
parseArgs({ args, options });
1081-
}, /"options\.alpha\.help" property must be of type string/
1082-
);
1083-
});
1078+
test('help value for option must be a string', () => {
1079+
const args = [];
1080+
const options = { alpha: { type: 'string', help: true } };
1081+
assert.throws(() => {
1082+
parseArgs({ args, options });
1083+
}, /"options\.alpha\.help" property must be of type string/
1084+
);
1085+
});
10841086

1085-
test('when option has help text values but help arg value is not provided, then no help value appear', () => {
1086-
const args = ['-f', 'bar'];
1087-
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1088-
const expected = { values: { __proto__: null, foo: 'bar' }, positionals: [] };
1089-
const result = parseArgs({ args, options, allowPositionals: true });
1090-
assert.deepStrictEqual(result, expected);
1091-
});
1087+
test('when option has help text values but help arg value is not provided, then no help value appear', () => {
1088+
const args = ['-f', 'bar'];
1089+
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1090+
const expected = { values: { __proto__: null, foo: 'bar' }, positionals: [] };
1091+
const result = parseArgs({ args, options, allowPositionals: true });
1092+
assert.deepStrictEqual(result, expected);
1093+
});
10921094

1093-
test('when option has short and long flags, then both appear in usage', () => {
1094-
const args = ['-f', 'bar'];
1095-
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1096-
const help = 'Description for some awesome stuff:';
1097-
const printUsage = help + '\n-f, --foo <arg> help text';
1098-
const expected = { values: { __proto__: null, foo: 'bar', help: printUsage }, positionals: [] };
1099-
const result = parseArgs({ args, options, allowPositionals: true, help });
1100-
assert.deepStrictEqual(result, expected);
1101-
});
1095+
test('when option has short and long flags, then both appear in usage with help option', () => {
1096+
const args = ['-f', 'bar'];
1097+
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1098+
const help = 'Description for some awesome stuff:';
1099+
const printUsage = help + '\n-f, --foo <arg> help text\n-h, --help Show help';
1100+
const expected = { helpText: printUsage, values: { __proto__: null, foo: 'bar' }, positionals: [] };
1101+
const result = parseArgs({ args, options, allowPositionals: true, help });
1102+
assert.deepStrictEqual(result, expected);
1103+
});
11021104

1103-
test('when options has short group flags, then both appear in usage', () => {
1104-
const args = ['-fm', 'bar'];
1105-
const options = { foo: { type: 'boolean', short: 'f', help: 'help text' },
1106-
moo: { type: 'string', short: 'm', help: 'help text' } };
1107-
const help = 'Description for some awesome stuff:';
1108-
const printUsage = help + '\n-f, --foo help text\n-m, --moo <arg> help text';
1109-
const expected = { values: { help: printUsage, __proto__: null, foo: true, moo: 'bar' }, positionals: [] };
1110-
const result = parseArgs({ args, options, allowPositionals: true, help });
1111-
assert.deepStrictEqual(result, expected);
1112-
});
1105+
test('when options has short group flags, then both appear in usage with help option', () => {
1106+
const args = ['-fm', 'bar'];
1107+
const options = { foo: { type: 'boolean', short: 'f', help: 'help text' },
1108+
moo: { type: 'string', short: 'm', help: 'help text' } };
1109+
const help = 'Description for some awesome stuff:';
1110+
const printUsage = help + '\n-f, --foo help text\n' +
1111+
'-m, --moo <arg> help text\n' +
1112+
'-h, --help Show help';
1113+
const expected = { helpText: printUsage, values: { __proto__: null, foo: true, moo: 'bar' }, positionals: [] };
1114+
const result = parseArgs({ args, options, allowPositionals: true, help });
1115+
assert.deepStrictEqual(result, expected);
1116+
});
11131117

1114-
test('when options has short flag with value, then both appear in usage', () => {
1115-
const args = ['-fFILE'];
1116-
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1117-
const help = 'Description for some awesome stuff:';
1118-
const printUsage = help + '\n-f, --foo <arg> help text';
1119-
const expected = { values: { help: printUsage, __proto__: null, foo: 'FILE' }, positionals: [] };
1120-
const result = parseArgs({ args, options, allowPositionals: true, help });
1121-
assert.deepStrictEqual(result, expected);
1122-
});
1118+
test('when options has short flag with value, then both appear in usage with help option', () => {
1119+
const args = ['-fFILE'];
1120+
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1121+
const help = 'Description for some awesome stuff:';
1122+
const printUsage = help + '\n-f, --foo <arg> help text\n-h, --help Show help';
1123+
const expected = { helpText: printUsage, values: { __proto__: null, foo: 'FILE' }, positionals: [] };
1124+
const result = parseArgs({ args, options, allowPositionals: true, help });
1125+
assert.deepStrictEqual(result, expected);
1126+
});
11231127

1124-
test('when options has long flag, then it appear in usage', () => {
1125-
const args = ['--foo', 'bar'];
1126-
const options = { foo: { type: 'string', help: 'help text' } };
1127-
const help = 'Description for some awesome stuff:';
1128-
const printUsage = help + '\n--foo <arg> help text';
1129-
const expected = { values: { help: printUsage, __proto__: null, foo: 'bar' }, positionals: [] };
1130-
const result = parseArgs({ args, options, allowPositionals: true, help });
1131-
assert.deepStrictEqual(result, expected);
1132-
});
1128+
test('when options has long flag, then it appear in usage with help option', () => {
1129+
const args = ['--foo', 'bar'];
1130+
const options = { foo: { type: 'string', help: 'help text' } };
1131+
const help = 'Description for some awesome stuff:';
1132+
const printUsage = help + '\n--foo <arg> help text\n-h, --help Show help';
1133+
const expected = { helpText: printUsage, values: { __proto__: null, foo: 'bar' }, positionals: [] };
1134+
const result = parseArgs({ args, options, allowPositionals: true, help });
1135+
assert.deepStrictEqual(result, expected);
1136+
});
11331137

1134-
test('when options has long flag with value, then both appear in usage', () => {
1135-
const args = ['--foo=bar'];
1136-
const options = { foo: { type: 'string', help: 'help text' } };
1137-
const help = 'Description for some awesome stuff:';
1138-
const printUsage = help + '\n--foo <arg> help text';
1139-
const expected = { values: { help: printUsage, __proto__: null, foo: 'bar' }, positionals: [] };
1140-
const result = parseArgs({ args, options, allowPositionals: true, help });
1141-
assert.deepStrictEqual(result, expected);
1142-
});
1138+
test('when options has long flag with value, then both appear in usage with help option', () => {
1139+
const args = ['--foo=bar'];
1140+
const options = { foo: { type: 'string', help: 'help text' } };
1141+
const help = 'Description for some awesome stuff:';
1142+
const printUsage = help + '\n--foo <arg> help text\n-h, --help Show help';
1143+
const expected = { helpText: printUsage, values: { __proto__: null, foo: 'bar' }, positionals: [] };
1144+
const result = parseArgs({ args, options, allowPositionals: true, help });
1145+
assert.deepStrictEqual(result, expected);
1146+
});
11431147

1144-
test('when options has help values with and without explicit texts, then all appear in usage', () => {
1145-
const args = [
1146-
'-h', '-a', 'val1',
1147-
];
1148-
const options = {
1149-
help: { type: 'boolean', short: 'h', help: 'Prints command line options' },
1150-
alpha: { type: 'string', short: 'a', help: 'Alpha option help' },
1151-
beta: { type: 'boolean', short: 'b', help: 'Beta option help' },
1152-
charlie: { type: 'string', short: 'c' },
1153-
delta: { type: 'string', help: 'Delta option help' },
1154-
echo: { type: 'boolean', short: 'e', help: 'Echo option help' },
1155-
foxtrot: { type: 'string', help: 'Foxtrot option help' },
1156-
golf: { type: 'boolean', help: 'Golf option help' },
1157-
hotel: { type: 'string', help: 'Hotel option help' },
1158-
india: { type: 'string' },
1159-
juliet: { type: 'boolean', short: 'j', help: 'Juliet option help' },
1160-
looooooooooooooongHelpText: {
1161-
type: 'string',
1162-
short: 'L',
1163-
help: 'Very long option help text for demonstration purposes'
1164-
}
1165-
};
1166-
const help = 'Description for some awesome stuff:';
1167-
1168-
const result = parseArgs({ args, options, help });
1169-
const printUsage =
1170-
'Description for some awesome stuff:\n' +
1171-
'-h, --help Prints command line options\n' +
1172-
'-a, --alpha <arg> Alpha option help\n' +
1173-
'-b, --beta Beta option help\n' +
1174-
'-c, --charlie <arg>\n' +
1175-
'--delta <arg> Delta option help\n' +
1176-
'-e, --echo Echo option help\n' +
1177-
'--foxtrot <arg> Foxtrot option help\n' +
1178-
'--golf Golf option help\n' +
1179-
'--hotel <arg> Hotel option help\n' +
1180-
'--india <arg>\n' +
1181-
'-j, --juliet Juliet option help\n' +
1182-
'-L, --looooooooooooooongHelpText <arg>\n' +
1183-
' Very long option help text for demonstration purposes';
1184-
1185-
assert.strictEqual(result.values.help, printUsage);
1186-
});
1187-
1188-
test('when general help text and options with no help values, then all appear in usage', () => {
1189-
const args = ['-a', 'val1', '--help'];
1190-
const help = 'Description for some awesome stuff:';
1191-
const options = { alpha: { type: 'string', short: 'a' }, help: { type: 'boolean' } };
1192-
const printUsage =
1148+
test('when options has help values with and without explicit texts, then all appear in usage', () => {
1149+
const args = [
1150+
'-h', '-a', 'val1',
1151+
];
1152+
const options = {
1153+
help: { type: 'boolean', short: 'h', help: 'Prints command line options' },
1154+
alpha: { type: 'string', short: 'a', help: 'Alpha option help' },
1155+
beta: { type: 'boolean', short: 'b', help: 'Beta option help' },
1156+
charlie: { type: 'string', short: 'c' },
1157+
delta: { type: 'string', help: 'Delta option help' },
1158+
echo: { type: 'boolean', short: 'e', help: 'Echo option help' },
1159+
foxtrot: { type: 'string', help: 'Foxtrot option help' },
1160+
golf: { type: 'boolean', help: 'Golf option help' },
1161+
hotel: { type: 'string', help: 'Hotel option help' },
1162+
india: { type: 'string' },
1163+
juliet: { type: 'boolean', short: 'j', help: 'Juliet option help' },
1164+
looooooooooooooongHelpText: {
1165+
type: 'string',
1166+
short: 'L',
1167+
help: 'Very long option help text for demonstration purposes'
1168+
}
1169+
};
1170+
const help = 'Description for some awesome stuff:';
1171+
1172+
const result = parseArgs({ args, options, help });
1173+
const printUsage =
11931174
'Description for some awesome stuff:\n' +
1194-
'-a, --alpha <arg>\n' +
1195-
'--help';
1175+
'-h, --help Prints command line options\n' +
1176+
'-a, --alpha <arg> Alpha option help\n' +
1177+
'-b, --beta Beta option help\n' +
1178+
'-c, --charlie <arg>\n' +
1179+
'--delta <arg> Delta option help\n' +
1180+
'-e, --echo Echo option help\n' +
1181+
'--foxtrot <arg> Foxtrot option help\n' +
1182+
'--golf Golf option help\n' +
1183+
'--hotel <arg> Hotel option help\n' +
1184+
'--india <arg>\n' +
1185+
'-j, --juliet Juliet option help\n' +
1186+
'-L, --looooooooooooooongHelpText <arg>\n' +
1187+
' Very long option help text for demonstration purposes';
1188+
1189+
assert.strictEqual(result.helpText, printUsage);
1190+
});
11961191

1197-
const result = parseArgs({ args, options, help });
1192+
test('when general help text and options with no help values, then all appear in usage', () => {
1193+
const args = ['-a', 'val1', '--help'];
1194+
const help = 'Description for some awesome stuff:';
1195+
const options = { alpha: { type: 'string', short: 'a' }, help: { type: 'boolean' } };
1196+
const printUsage =
1197+
'Description for some awesome stuff:\n' +
1198+
'-a, --alpha <arg>\n' +
1199+
'--help';
11981200

1199-
assert.strictEqual(result.values.help, printUsage);
1200-
});
1201+
const result = parseArgs({ args, options, help });
1202+
1203+
assert.strictEqual(result.helpText, printUsage);
1204+
});
1205+
1206+
// Test addHelpOption behavior
1207+
test('addHelpOption validation must be boolean', () => {
1208+
const args = ['-f', 'bar'];
1209+
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1210+
1211+
assert.throws(() => {
1212+
parseArgs({ args, options, addHelpOption: 'true' });
1213+
}, /The "addHelpOption" argument must be of type boolean/
1214+
);
1215+
});
1216+
1217+
test('addHelpOption is true auto-injects help option when no existing help option', () => {
1218+
const args = ['--foo', 'bar'];
1219+
const options = { foo: { type: 'string', help: 'use the foo filter' } };
1220+
const help = 'utility to control filters';
1221+
1222+
const result = parseArgs({ args, options, help, addHelpOption: true });
1223+
1224+
assert.ok(result.helpText.includes('-h, --help Show help'));
1225+
const resultWithHelp = parseArgs({ args: ['--help'], options, help, addHelpOption: true });
1226+
assert.strictEqual(resultWithHelp.values.help, true);
1227+
});
1228+
1229+
test('addHelpOption is false prevents auto-injection of help option', () => {
1230+
const args = ['--foo', 'bar'];
1231+
const options = { foo: { type: 'string', help: 'use the foo filter' } };
1232+
const help = 'utility to control filters';
1233+
1234+
const result = parseArgs({ args, options, help, addHelpOption: false });
1235+
1236+
assert.ok(!result.helpText.includes('-h, --help'));
1237+
assert.throws(() => {
1238+
parseArgs({ args: ['--help'], options, help, addHelpOption: false });
1239+
}, { code: 'ERR_PARSE_ARGS_UNKNOWN_OPTION' });
1240+
});
1241+
1242+
test('addHelpOption is false but existing help option should still work', () => {
1243+
const args = ['--help'];
1244+
const options = {
1245+
foo: { type: 'string', help: 'use the foo filter' },
1246+
help: { type: 'boolean', short: '?', help: 'display help' }
1247+
};
1248+
const help = 'utility to control filters';
1249+
1250+
const result = parseArgs({ args, options, help, addHelpOption: false });
1251+
1252+
assert.strictEqual(result.values.help, true);
1253+
assert.ok(result.helpText.includes('-?, --help display help'));
1254+
});
1255+
1256+
// Test returnHelpText behavior
1257+
test('returnHelpText validation must be boolean', () => {
1258+
const args = ['-f', 'bar'];
1259+
const options = { foo: { type: 'string', short: 'f', help: 'help text' } };
1260+
1261+
assert.throws(() => {
1262+
parseArgs({ args, options, returnHelpText: 'true' });
1263+
}, /The "returnHelpText" argument must be of type boolean/
1264+
);
1265+
});
1266+
1267+
test('returnHelpText is false prevents help text generation', () => {
1268+
const args = ['--foo', 'bar'];
1269+
const options = { foo: { type: 'string', help: 'use the foo filter' } };
1270+
const help = 'utility to control filters';
1271+
1272+
const result = parseArgs({ args, options, help, returnHelpText: false });
1273+
1274+
assert.strictEqual(result.helpText, undefined);
1275+
});
1276+
1277+
test('returnHelpText is true forces help text generation even without general help', () => {
1278+
const args = ['--foo', 'bar'];
1279+
const options = { foo: { type: 'string', help: 'use the foo filter' } };
1280+
1281+
const result = parseArgs({ args, options, returnHelpText: true, addHelpOption: true });
1282+
1283+
assert.ok(result.helpText);
1284+
assert.ok(result.helpText.includes('--foo <arg> use the foo filter'));
1285+
assert.ok(result.helpText.includes('-h, --help Show help'));
1286+
});
1287+
1288+
test('postpone help generation until needed', () => {
1289+
const options = {
1290+
foo: { type: 'boolean', short: 'f', help: 'use the foo filter' },
1291+
bar: { type: 'string', help: 'use the specified bar filter' }
1292+
};
1293+
1294+
const result = parseArgs({
1295+
addHelpOption: true,
1296+
returnHelpText: false,
1297+
options
1298+
});
1299+
1300+
assert.strictEqual(result.helpText, undefined);
1301+
1302+
const { helpText } = parseArgs({
1303+
help: 'utility to control filters',
1304+
options
1305+
});
1306+
1307+
assert.ok(helpText);
1308+
assert.ok(helpText.includes('utility to control filters'));
1309+
});
1310+
1311+
test('when both addHelpOption and returnHelpText are false, no help functionality', () => {
1312+
const args = ['--foo', 'bar'];
1313+
const options = { foo: { type: 'string', help: 'help text' } };
1314+
const help = 'Description text';
1315+
1316+
const result = parseArgs({
1317+
args,
1318+
options,
1319+
help,
1320+
addHelpOption: false,
1321+
returnHelpText: false
1322+
});
1323+
1324+
assert.strictEqual(result.helpText, undefined);
1325+
assert.throws(() => {
1326+
parseArgs({ args: ['--help'], options, help, addHelpOption: false });
1327+
}, { code: 'ERR_PARSE_ARGS_UNKNOWN_OPTION' });
1328+
});
1329+
}

0 commit comments

Comments
 (0)