UNPKG

28.4 kBJavaScriptView Raw
1/*
2 * dashdash tests
3 */
4
5var DEBUG = false;
6if (DEBUG) {
7 var debug = console.warn;
8} else {
9 var debug = function () {};
10}
11
12var format = require('util').format;
13
14
15// node-tap API
16if (require.cache[__dirname + '/tap4nodeunit.js'])
17 delete require.cache[__dirname + '/tap4nodeunit.js'];
18var tap4nodeunit = require('./tap4nodeunit.js');
19var after = tap4nodeunit.after;
20var before = tap4nodeunit.before;
21var test = tap4nodeunit.test;
22
23var dashdash = require('../lib/dashdash');
24
25
26// ---- globals
27
28var TEST_FILTER = process.env.TEST_FILTER;
29
30
31// ---- support stuff
32
33function parseYesNo(option, optstr, arg) {
34 var argLower = arg.toLowerCase()
35 if (~['yes', 'y'].indexOf(argLower)) {
36 return true;
37 } else if (~['no', 'n'].indexOf(argLower)) {
38 return false;
39 } else {
40 throw new Error(format(
41 'arg for "%s" is not "yes" or "no": "%s"',
42 optstr, arg));
43 }
44}
45
46
47// ---- tests
48
49before(function (next) {
50 next();
51});
52
53test('exports', function (t) {
54 t.ok(dashdash.createParser, 'dashdash.createParser');
55 t.ok(dashdash.parse, 'dashdash.parse');
56 t.ok(dashdash.Parser, 'dashdash.Parser');
57 t.end();
58});
59
60test('createParser', function (t) {
61 var options = [ {name: 'help', type: 'bool'} ];
62 var parser = dashdash.createParser({options: options});
63 t.ok(parser);
64 t.end();
65});
66
67test('Parser', function (t) {
68 var options = [ {name: 'help', type: 'bool'} ];
69 var parser = new dashdash.Parser({options: options});
70 t.ok(parser);
71 t.end();
72});
73
74test('parse', function (t) {
75 var options = [ {name: 'help', type: 'bool'} ];
76 var argv = 'node tool.js --help'.split(/\s+/g);
77 var opts = dashdash.parse({options: options, argv: argv});
78 t.ok(opts);
79 t.end();
80});
81
82
83test('old Parser.parse() API', function (t) {
84 var options = [ {name: 'v', type: 'bool'} ];
85 var parser = new dashdash.Parser({options: options});
86 var opts = parser.parse('node tool.js -v'.split(/\s+/g));
87 t.ok(opts.v);
88 opts = parser.parse('-v'.split(/\s+/g), 0);
89 t.ok(opts.v);
90 t.end();
91});
92
93
94test('slice', function (t) {
95 var options = [ {name: 'v', type: 'bool'} ];
96 var parser = new dashdash.Parser({options: options});
97 var opts = parser.parse({argv: 'node tool.js -v'.split(/\s+/g)});
98 t.ok(opts.v);
99 t.equal(opts._args.length, 0);
100 var opts = parser.parse({argv: '-v'.split(/\s+/g), slice: 0});
101 t.ok(opts.v);
102 t.equal(opts._args.length, 0);
103 t.end();
104});
105
106
107var cases = [
108 // no opts
109 {
110 options: [],
111 argv: 'node tool.js',
112 expect: {
113 _args: []
114 }
115 },
116 {
117 options: [],
118 argv: 'node tool.js a b c',
119 expect: {
120 _args: ['a', 'b', 'c']
121 }
122 },
123 {
124 options: [ {name: 'help', type: 'bool'} ],
125 argv: 'node tool.js a b',
126 expect: {
127 _args: ['a', 'b']
128 }
129 },
130
131 // '--'
132 {
133 options: [ {name: 'help', type: 'bool'} ],
134 argv: 'node tool.js -- a',
135 expect: {
136 _args: ['a']
137 }
138 },
139 {
140 options: [ {name: 'help', type: 'bool'} ],
141 argv: 'node tool.js a -- b',
142 expect: {
143 _args: ['a', 'b']
144 }
145 },
146 {
147 options: [ {name: 'help', type: 'bool'} ],
148 argv: 'node tool.js a -- --help',
149 expect: {
150 _args: ['a', '--help']
151 }
152 },
153
154 // '--long-opt'
155 {
156 options: [ {name: 'help', type: 'bool'} ],
157 argv: 'node tool.js --help',
158 expect: {
159 help: true,
160 _args: []
161 }
162 },
163 {
164 options: [ {name: 'help', type: 'bool'} ],
165 argv: 'node tool.js --help a b',
166 expect: {
167 help: true,
168 _args: ['a', 'b']
169 }
170 },
171 {
172 options: [ {name: 'help', type: 'bool'} ],
173 argv: 'node tool.js a --help b',
174 expect: {
175 help: true,
176 _args: ['a', 'b']
177 }
178 },
179 {
180 options: [ {name: 'help', type: 'bool'} ],
181 argv: 'node tool.js a --help b',
182 interspersed: true,
183 expect: {
184 help: true,
185 _args: ['a', 'b']
186 }
187 },
188 {
189 options: [ {name: 'help', type: 'bool'} ],
190 argv: 'node tool.js a --help b',
191 interspersed: false,
192 expect: {
193 _args: ['a', '--help', 'b']
194 }
195 },
196 {
197 options: [ {name: 'help', type: 'bool'} ],
198 argv: 'node tool.js --help=foo',
199 expect: /argument given to .* option that does not take one/,
200 },
201 {
202 options: [ {name: 'file', type: 'string'} ],
203 argv: 'node tool.js --file',
204 expect: /do not have enough args/
205 },
206 {
207 options: [ {name: 'file', type: 'string', default: '/dev/null'} ],
208 argv: 'node tool.js',
209 expect: {
210 file: '/dev/null',
211 _args: []
212 }
213 },
214 {
215 options: [ {name: 'file', type: 'string'} ],
216 argv: 'node tool.js --file foo.txt',
217 expect: {
218 file: 'foo.txt',
219 _args: []
220 }
221 },
222 {
223 options: [ {name: 'file', type: 'string'} ],
224 argv: 'node tool.js --file=foo.txt',
225 expect: {
226 file: 'foo.txt',
227 _args: []
228 }
229 },
230
231 // short opts
232 {
233 options: [ {name: 'h', type: 'bool'} ],
234 argv: 'node tool.js -',
235 expect: {
236 _args: ['-']
237 }
238 },
239 {
240 options: [ {name: 'h', type: 'bool'} ],
241 argv: 'node tool.js -h',
242 expect: {
243 h: true,
244 _args: []
245 }
246 },
247 {
248 options: [ {name: 'f', type: 'string'} ],
249 argv: 'node tool.js -f',
250 expect: /do not have enough args/
251 },
252 {
253 options: [ {name: 'f', type: 'string'} ],
254 argv: 'node tool.js -f foo.txt',
255 expect: {
256 f: 'foo.txt',
257 _args: []
258 }
259 },
260 {
261 options: [ {name: 'f', type: 'string'} ],
262 argv: 'node tool.js -ffoo.txt',
263 expect: {
264 f: 'foo.txt',
265 _args: []
266 }
267 },
268 {
269 options: [ {name: 'l', type: 'bool'},
270 {names: ['all', 'a'], type: 'bool'} ],
271 argv: 'node ls.js -l -a dir',
272 expect: {
273 l: true,
274 all: true,
275 _order: [ {key: 'l', value: true, from: 'argv'},
276 {key: 'all', value: true, from: 'argv'} ],
277 _args: ['dir']
278 }
279 },
280 {
281 options: [ {name: 'l', type: 'bool'},
282 {names: ['all', 'a'], type: 'bool'} ],
283 argv: 'node ls.js -l dir -a',
284 expect: {
285 l: true,
286 all: true,
287 _order: [ {key: 'l', value: true, from: 'argv'},
288 {key: 'all', value: true, from: 'argv'} ],
289 _args: ['dir']
290 }
291 },
292 {
293 options: [ {name: 'l', type: 'bool'},
294 {names: ['all', 'a'], type: 'bool'} ],
295 argv: 'node ls.js -l dir -a',
296 interspersed: false,
297 expect: {
298 l: true,
299 _order: [ {key: 'l', value: true, from: 'argv'} ],
300 _args: ['dir', '-a']
301 }
302 },
303 {
304 options: [ {name: 'l', type: 'bool'},
305 {names: ['all', 'a'], type: 'bool'} ],
306 argv: 'node ls.js -la dir',
307 expect: {
308 l: true,
309 all: true,
310 _args: ['dir']
311 }
312 },
313
314 // type=number
315 {
316 options: [
317 {name: 'a', type: 'number'},
318 {name: 'b', type: 'number'},
319 {name: 'c', type: 'number'},
320 {name: 'd', type: 'number'},
321 {name: 'e', type: 'number'},
322 ],
323 argv: 'node tool.js -a 5 -b4 -c -1 -d -3.14159 -e 1.0e42 foo',
324 expect: {
325 a: 5,
326 b: 4,
327 c: -1,
328 d: -3.14159,
329 e: 1.0e42,
330 _args: ['foo']
331 }
332 },
333 {
334 options: [ {names: ['timeout', 't'], type: 'number'} ],
335 argv: 'node tool.js -t 5a',
336 /* JSSTYLED */
337 expect: /arg for "-t" is not a number/
338 },
339
340 // type: arrayOf*
341 {
342 options: [ {names: ['verbose', 'v'], type: 'arrayOfBool'} ],
343 argv: 'node tool.js -vvv foo bar',
344 expect: {
345 verbose: [true, true, true],
346 _args: ['foo', 'bar']
347 }
348 },
349 {
350 options: [ {names: ['verbose', 'v'], type: 'arrayOfBool'} ],
351 argv: 'node tool.js foo bar',
352 expect: {
353 // verbose: undefined,
354 _args: ['foo', 'bar']
355 }
356 },
357 {
358 options: [ {names: ['weapon', 'w'], type: 'arrayOfString'} ],
359 argv: 'node tool.js -w club --weapon mallet -w sword bang',
360 expect: {
361 weapon: ['club', 'mallet', 'sword'],
362 _args: ['bang']
363 }
364 },
365 {
366 options: [ {names: ['split', 's'], type: 'arrayOfNumber'} ],
367 argv: 'node tool.js --split 10 -s 5 -s 0.01 bang',
368 expect: {
369 split: [10, 5, 0.01],
370 _args: ['bang']
371 }
372 },
373
374 // help
375 {
376 options: [
377 {names: ['help', 'h'], type: 'bool', help: 'Show help and exit.'}
378 ],
379 argv: 'node tool.js --help',
380 expectHelp: /-h, --help\s+Show help and exit./
381 },
382 {
383 options: [
384 { names: ['help', 'h'], type: 'bool' },
385 { group: 'first group' },
386 { names: [ 'first-one', 'f' ], type: 'bool' },
387 { names: [ 'first-two', 'F' ], type: 'bool' },
388 { group: 'second group' },
389 { names: [ 'second-one', 's' ], type: 'bool' },
390 { names: [ 'second-two', 'S' ], type: 'bool' },
391 ],
392 argv: 'node option-groups-tool.js --help',
393 expectHelp: [
394 /--help\n\n\s\sfirst group:/m,
395 /^\s\sfirst group:\n\s\s\s\s-f, --first-one$/m,
396 /first-two\n\n\s\ssecond group:\n\s\s\s\s-s, --second-one$/m,
397 ]
398 },
399
400 // integer
401 {
402 options: [ {name: 't', type: 'integer'} ],
403 argv: 'node tool.js -t 0',
404 expect: { t: 0, _args: [] }
405 },
406 {
407 options: [ {name: 't', type: 'integer'} ],
408 argv: 'node tool.js -t 42',
409 expect: { t: 42, _args: [] }
410 },
411 {
412 options: [ {name: 't', type: 'integer'} ],
413 argv: 'node tool.js -t42',
414 expect: { t: 42, _args: [] }
415 },
416 {
417 options: [ {name: 't', type: 'integer'} ],
418 argv: 'node tool.js -t -5',
419 expect: { t: -5, _args: [] }
420 },
421 {
422 options: [ {name: 't', type: 'integer'} ],
423 argv: 'node tool.js -t-5',
424 expect: { t: -5, _args: [] }
425 },
426 {
427 options: [ {name: 't', type: 'integer'} ],
428 argv: 'node tool.js -t 1e2',
429 /* JSSTYLED */
430 expect: /arg for "-t" is not an integer/
431 },
432 {
433 options: [ {name: 't', type: 'integer'} ],
434 argv: 'node tool.js -t 0x32',
435 /* JSSTYLED */
436 expect: /arg for "-t" is not an integer/
437 },
438 {
439 options: [ {name: 't', type: 'integer'} ],
440 argv: 'node tool.js -t 3.1',
441 /* JSSTYLED */
442 expect: /arg for "-t" is not an integer/
443 },
444 {
445 options: [ {name: 't', type: 'integer'} ],
446 argv: 'node tool.js -t 42.',
447 /* JSSTYLED */
448 expect: /arg for "-t" is not an integer/
449 },
450 {
451 options: [ {name: 't', type: 'integer'} ],
452 argv: 'node tool.js -t 1e-2',
453 /* JSSTYLED */
454 expect: /arg for "-t" is not an integer/
455 },
456 {
457 options: [ {name: 't', type: 'arrayOfInteger'} ],
458 argv: 'node tool.js',
459 expect: { _args: [] }
460 },
461 {
462 options: [ {name: 't', type: 'arrayOfInteger'} ],
463 argv: 'node tool.js -t 42',
464 expect: { t: [42], _args: [] }
465 },
466 {
467 options: [ {name: 't', type: 'arrayOfInteger'} ],
468 argv: 'node tool.js -t 1 -t 2 -t -3',
469 expect: { t: [1, 2, -3], _args: [] }
470 },
471 {
472 options: [ {name: 't', type: 'arrayOfInteger'} ],
473 argv: 'node tool.js -t 1 -t 1e2',
474 /* JSSTYLED */
475 expect: /arg for "-t" is not an integer/
476 },
477
478 // positiveInteger
479 {
480 options: [ {name: 't', type: 'positiveInteger'} ],
481 argv: 'node tool.js -t 0',
482 expect: { t: 0, _args: [] }
483 },
484 {
485 options: [ {name: 't', type: 'positiveInteger'} ],
486 argv: 'node tool.js -t 42',
487 expect: { t: 42, _args: [] }
488 },
489 {
490 options: [ {name: 't', type: 'positiveInteger'} ],
491 argv: 'node tool.js -t42',
492 expect: { t: 42, _args: [] }
493 },
494 {
495 options: [ {name: 't', type: 'positiveInteger'} ],
496 argv: 'node tool.js -t -5',
497 /* JSSTYLED */
498 expect: /arg for "-t" is not a positive integer/
499 },
500 {
501 options: [ {name: 't', type: 'arrayOfPositiveInteger'} ],
502 argv: 'node tool.js -t42',
503 expect: { t: [42], _args: [] }
504 },
505 {
506 options: [ {name: 't', type: 'arrayOfPositiveInteger'} ],
507 argv: 'node tool.js -t 42 -t -5',
508 /* JSSTYLED */
509 expect: /arg for "-t" is not a positive integer/
510 },
511
512 // env
513 {
514 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ],
515 argv: 'node foo.js -v',
516 /* JSSTYLED */
517 expect: {
518 v: true,
519 _args: [],
520 _order: [ {key: 'v', value: true, from: 'argv'} ]
521 }
522 },
523 {
524 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ],
525 argv: 'node foo.js -v',
526 env: {FOO_VERBOSE: '1'},
527 /* JSSTYLED */
528 expect: {
529 v: true,
530 _args: [],
531 _order: [ {key: 'v', value: true, from: 'argv'} ]
532 }
533 },
534 {
535 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ],
536 argv: 'node foo.js',
537 env: {FOO_VERBOSE: '1'},
538 expect: {
539 v: true,
540 _args: [],
541 _order: [ {key: 'v', value: true, from: 'env'} ]
542 }
543 },
544 {
545 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ],
546 argv: 'node foo.js',
547 env: {FOO_VERBOSE: '0'},
548 expect: {
549 v: false,
550 _args: [],
551 _order: [ {key: 'v', value: false, from: 'env'} ]
552 }
553 },
554 {
555 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ],
556 argv: 'node foo.js',
557 env: {FOO_VERBOSE: ''},
558 /* JSSTYLED */
559 expect: { _args: [] }
560 },
561
562 // env help
563 {
564 options: [
565 {names: ['a'], type: 'string', env: 'A', help: 'Phrase'},
566 {names: ['b'], type: 'string', env: 'B', help: 'Sentence.'},
567 {names: ['c'], type: 'string', env: 'C', help: 'Question?'},
568 {names: ['d'], type: 'string', env: 'D', help: 'Exclamation!'},
569 {names: ['e'], type: 'string', env: 'E', help: ' '},
570 {names: ['f'], type: 'string', env: 'F', help: ''},
571 {names: ['g'], type: 'string', env: 'G'},
572 {names: ['h'], type: 'bool', env: 'H'},
573 ],
574 argv: 'node tool.js --help',
575 helpOptions: { includeEnv: true },
576 /* BEGIN JSSTYLED */
577 expectHelp: [
578 /-a ARG\s+Phrase. Environment: A=ARG/,
579 /-b ARG\s+Sentence. Environment: B=ARG/,
580 /-c ARG\s+Question\? Environment: C=ARG/,
581 /-d ARG\s+Exclamation! Environment: D=ARG/,
582 /-e ARG\s+Environment: E=ARG/,
583 /-f ARG\s+Environment: F=ARG/,
584 /-g ARG\s+Environment: G=ARG/,
585 /-h\s+Environment: H=1/,
586 ]
587 /* END JSSTYLED */
588 },
589
590 // env (number)
591 {
592 options: [
593 {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'}
594 ],
595 argv: 'node foo.js -t 42',
596 env: {},
597 /* JSSTYLED */
598 expect: { timeout: 42, _args: [] }
599 },
600 {
601 options: [
602 {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'}
603 ],
604 argv: 'node foo.js',
605 env: {FOO_TIMEOUT: '32'},
606 /* JSSTYLED */
607 expect: { timeout: 32, _args: [] }
608 },
609 {
610 options: [
611 {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'}
612 ],
613 argv: 'node foo.js -t 52',
614 env: {FOO_TIMEOUT: '32'},
615 /* JSSTYLED */
616 expect: { timeout: 52, _args: [] }
617 },
618
619 // Test that a validation fail in env throws, but NOT if a valid
620 // value is given in CLI opts (i.e. when env is ignored).
621 {
622 options: [
623 {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'}
624 ],
625 argv: 'node foo.js -t 52',
626 env: {FOO_TIMEOUT: 'wallawalla'},
627 /* JSSTYLED */
628 expect: { timeout: 52, _args: [] }
629 },
630 {
631 options: [
632 {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'}
633 ],
634 argv: 'node foo.js',
635 env: {FOO_TIMEOUT: 'wallawalla'},
636 /* JSSTYLED */
637 expect: /arg for "FOO_TIMEOUT" is not a number: "wallawalla"/
638 },
639
640 // env (arrayOfBool)
641 {
642 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'arrayOfBool'} ],
643 argv: 'node foo.js',
644 env: {FOO_VERBOSE: 'blah'},
645 /* JSSTYLED */
646 expect: { v: [true], _args: [] }
647 },
648 {
649 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'arrayOfBool'} ],
650 argv: 'node foo.js -v',
651 env: {FOO_VERBOSE: 'blah'},
652 /* JSSTYLED */
653 expect: { v: [true], _args: [] }
654 },
655 {
656 options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'arrayOfBool'} ],
657 argv: 'node foo.js -vv',
658 env: {FOO_VERBOSE: 'blah'},
659 /* JSSTYLED */
660 expect: { v: [true, true], _args: [] }
661 },
662
663 // key name transformation
664 {
665 options: [ {names: ['dry-run', 'n'], type: 'bool'} ],
666 argv: 'node foo.js --dry-run',
667 /* JSSTYLED */
668 expect: { dry_run: true, _args: [] }
669 },
670 {
671 options: [ {name: 'foo-bar-', type: 'bool'} ],
672 argv: 'node foo.js --foo-bar-',
673 /* JSSTYLED */
674 expect: { foo_bar_: true, _args: [] }
675 },
676
677 // issue #1: 'env' not taking precendence over 'default'
678 {
679 options: [ {
680 names: ['file', 'f'],
681 env: 'FOO_FILE',
682 'default': 'default.file',
683 type: 'string'
684 } ],
685 argv: 'node foo.js',
686 expect: { file: 'default.file', _args: [] }
687 },
688 {
689 options: [ {
690 names: ['file', 'f'],
691 env: 'FOO_FILE',
692 'default': 'default.file',
693 type: 'string'
694 } ],
695 env: {FOO_FILE: 'env.file'},
696 argv: 'node foo.js',
697 expect: { file: 'env.file', _args: [] }
698 },
699 {
700 options: [ {
701 names: ['file', 'f'],
702 env: 'FOO_FILE',
703 'default': 'default.file',
704 type: 'string'
705 } ],
706 argv: 'node foo.js -f argv.file',
707 env: {FOO_FILE: 'env.file'},
708 expect: { file: 'argv.file', _args: [] }
709 },
710
711 {
712 options: [ {
713 names: ['verbose', 'v'],
714 env: 'FOO_VERBOSE',
715 'default': false,
716 type: 'bool'
717 } ],
718 argv: 'node foo.js',
719 expect: { verbose: false, _args: [] }
720 },
721 {
722 options: [ {
723 names: ['verbose', 'v'],
724 env: 'FOO_VERBOSE',
725 'default': false,
726 type: 'bool'
727 } ],
728 argv: 'node foo.js',
729 env: {FOO_VERBOSE: '1'},
730 expect: { verbose: true, _args: [] }
731 },
732 {
733 options: [ {
734 names: ['verbose', 'v'],
735 env: 'FOO_VERBOSE',
736 'default': false,
737 type: 'bool'
738 } ],
739 argv: 'node foo.js',
740 env: {FOO_VERBOSE: '0'},
741 expect: { verbose: false, _args: [] }
742 },
743 {
744 options: [ {
745 names: ['verbose', 'v'],
746 env: 'FOO_VERBOSE',
747 'default': false,
748 type: 'bool'
749 } ],
750 argv: 'node foo.js -v',
751 env: {FOO_VERBOSE: '0'},
752 expect: { verbose: true, _args: [] }
753 },
754
755 // unstrict
756 {
757 options: [ {name: 'help', type: 'bool'} ],
758 argv: 'node tool.js a --help -b --cheese',
759 allowUnknown: true,
760 expect: {
761 help: true,
762 _args: ['a', '-b', '--cheese']
763 }
764 },
765 {
766 options: [ {name: 'help', type: 'bool'}, {name: 'c', type: 'bool'} ],
767 argv: 'node tool.js a -bcd --cheese --help',
768 allowUnknown: true,
769 expect: {
770 help: true,
771 _args: ['a', '-bcd', '--cheese']
772 }
773 },
774
775 // date
776 {
777 options: [ {names: ['start', 's'], type: 'date'} ],
778 argv: 'node foo.js -s',
779 /* JSSTYLED */
780 expect: /do not have enough args for "-s" option/
781 },
782 {
783 options: [ {names: ['start', 's'], type: 'date'} ],
784 argv: 'node foo.js -s notadate',
785 /* JSSTYLED */
786 expect: /arg for "-s" is not a valid date format: "notadate"/
787 },
788 {
789 options: [ {names: ['start', 's'], type: 'date'} ],
790 argv: 'node foo.js -s 0',
791 expect: { start: new Date(0), _args: [] }
792 },
793 {
794 options: [ {names: ['start', 's'], type: 'date'} ],
795 argv: 'node foo.js -s 1',
796 expect: { start: new Date(1000), _args: [] }
797 },
798 {
799 options: [ {names: ['start', 's'], type: 'date'} ],
800 argv: 'node foo.js -s 1396065084',
801 expect: { start: new Date(1396065084000), _args: [] }
802 },
803 {
804 options: [ {names: ['start', 's'], type: 'date'} ],
805 argv: 'node foo.js -s 2014-04-01',
806 expect: { start: new Date('2014-04-01'), _args: [] }
807 },
808 {
809 options: [ {names: ['start', 's'], type: 'date'} ],
810 argv: 'node foo.js -s 2014-04-01T',
811 /* JSSTYLED */
812 expect: /arg for "-s" is not a valid date format: "2014-04-01T"/
813 },
814 {
815 options: [ {names: ['start', 's'], type: 'date'} ],
816 argv: 'node foo.js -s 2014-04-01T12:01:02',
817 expect: { start: new Date('2014-04-01T12:01:02Z'), _args: [] }
818 },
819 {
820 options: [ {names: ['start', 's'], type: 'date'} ],
821 argv: 'node foo.js -s 2014-04-01T12:01:02Z',
822 expect: { start: new Date('2014-04-01T12:01:02Z'), _args: [] }
823 },
824 {
825 options: [ {names: ['start', 's'], type: 'date'} ],
826 argv: 'node foo.js -s 2014-04-01T12:01:02.7',
827 expect: { start: new Date('2014-04-01T12:01:02.7Z'), _args: [] }
828 },
829 {
830 options: [ {names: ['start', 's'], type: 'date'} ],
831 argv: 'node foo.js -s 2014-04-01T12:01:02.456Z',
832 expect: { start: new Date('2014-04-01T12:01:02.456Z'), _args: [] }
833 },
834 {
835 options: [ {names: ['start', 's'], type: 'date'} ],
836 argv: 'node foo.js -s 2014-04-01t12:01:02.456z',
837 expect: { start: new Date('2014-04-01T12:01:02.456Z'), _args: [] }
838 },
839 {
840 options: [ {names: ['times', 't'], type: 'arrayOfDate'} ],
841 argv: 'node foo.js --times 1 -t 2 -t 2014-04-01',
842 expect: {
843 times: [
844 new Date(1000),
845 new Date(2000),
846 new Date('2014-04-01T00:00:00Z')
847 ],
848 _args: [] }
849 },
850
851 {
852 optionTypes: [
853 {
854 name: 'yesno',
855 takesArg: true,
856 helpArg: '<yes/no>',
857 parseArg: parseYesNo
858 }
859 ],
860 options: [ {names: ['answer', 'a'], type: 'yesno'} ],
861 argv: 'node foo.js -a yes',
862 expect: {
863 answer: true,
864 _args: []
865 }
866 },
867 {
868 optionTypes: [
869 {
870 name: 'yesno',
871 takesArg: true,
872 helpArg: '<yes/no>',
873 parseArg: parseYesNo
874 }
875 ],
876 options: [ {names: ['answer', 'a'], type: 'yesno'} ],
877 argv: 'node foo.js -a no',
878 expect: {
879 answer: false,
880 _args: []
881 }
882 },
883
884 // helpWrap option
885 {
886 options: [
887 {
888 names: ['opt', 'o'],
889 type: 'string',
890 env: ['ENVVARIABLE'],
891 help: 'long help with\n newlines' +
892 '\n spaces\n and such\nwill not render correctly'
893 },
894 {
895 names: ['array', 'a'],
896 type: 'string',
897 helpWrap: false,
898 env: ['OTHERVARIABLE'],
899 help: 'long help with\n newlines' +
900 '\n spaces\n and such\nwill render correctly'
901 },
902 {
903 names: ['foo'],
904 type: 'string',
905 helpWrap: false,
906 env: ['FOOVAR']
907 }
908 ],
909 argv: 'node helpWrapTool.js --help',
910 helpOptions: { includeEnv: true },
911 /* BEGIN JSSTYLED */
912 expectHelp: [
913 /long help with newlines spaces and such will not render/,
914 /\. Environment: ENVVARIABLE=ARG/,
915 // Without wrapping:
916 /long help with$/m,
917 /^ +newlines$/m,
918 /^ +Environment: OTHERVARIABLE=ARG/m,
919 // Ensure FOOVAR env is on *first* line and not after a blank.
920 /^ +--foo=ARG +Environment: FOOVAR=ARG$/m
921 ]
922 /* END JSSTYLED */
923 },
924 {
925 options: [
926 {
927 names: ['array', 'a'],
928 type: 'string',
929 env: ['OTHERVARIABLE'],
930 help: 'long help with\n newlines' +
931 '\n spaces\n and such\nwill render correctly'
932 }
933 ],
934 argv: 'node helpWrapTool2.js --help',
935 helpOptions: { includeEnv: true, helpWrap: false },
936 /* BEGIN JSSTYLED */
937 expectHelp: [
938 /long help with$/m,
939 /^ +newlines$/m,
940 /^ +Environment: OTHERVARIABLE=ARG/m,
941 ]
942 /* END JSSTYLED */
943 },
944];
945
946cases.forEach(function (c, num) {
947 var expect = c.expect;
948 delete c.expect;
949 var expectHelps = c.expectHelp;
950 if (!Array.isArray(expectHelps)) {
951 expectHelps = expectHelps ? [expectHelps] : [];
952 for (var i = 0; i < expectHelps.length; i++) {
953 if (typeof (expectHelps[i]) === 'string') {
954 expectHelps[i] = new RegExp(expectHelps[i]);
955 }
956 }
957 }
958 delete c.expectHelp;
959 var helpOptions = c.helpOptions;
960 delete c.helpOptions;
961 var argv = c.argv;
962 delete c.argv;
963 if (typeof (argv) === 'string') {
964 argv = argv.split(/\s+/);
965 }
966 var env = c.env;
967 delete c.env;
968 var envStr = '';
969 if (env) {
970 Object.keys(env).forEach(function (e) {
971 envStr += format('%s=%s ', e, env[e]);
972 });
973 }
974 var optionTypes = c.optionTypes;
975 delete c.optionTypes;
976 if (optionTypes) {
977 // WARNING: These are not removed for subsequent tests. That *could*
978 // theoretically cause conflicts.
979 optionTypes.forEach(function (ot) {
980 dashdash.addOptionType(ot);
981 });
982 }
983 var testName = format('case %d: %s%s', num, envStr, argv.join(' '));
984 if (TEST_FILTER && !~testName.indexOf(TEST_FILTER)) {
985 return;
986 }
987 test(testName, function (t) {
988 debug('--', num)
989 debug('c: %j', c)
990 var parser = new dashdash.Parser(c);
991 var opts;
992 if (expect instanceof RegExp) {
993 var error = null;
994 try {
995 opts = parser.parse({argv: argv, env: env});
996 } catch (e) {
997 error = e;
998 t.ok(expect.test(e.message), format(
999 'error message did not match %s: "%s"',
1000 expect, e.message));
1001 }
1002 t.ok(error, 'expected an error');
1003 } else if (expect) {
1004 opts = parser.parse({argv: argv, env: env});
1005 if (!expect._order) {
1006 delete opts._order; // don't test it, if not in case data
1007 }
1008 debug('opts: %j', opts)
1009 t.deepEqual(opts, expect);
1010 }
1011 if (expectHelps.length) {
1012 var help = parser.help(helpOptions);
1013 expectHelps.forEach(function (eH) {
1014 t.ok(eH.test(help), format(
1015 'help did not match %s: "%s"', eH, help));
1016 });
1017 }
1018 t.end();
1019 });
1020});