usage.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. var should = require('chai').should(),
  2. Hash = require('hashish'),
  3. yargs = require('../');
  4. describe('usage', function () {
  5. describe('demand options', function () {
  6. describe('using .demand()', function () {
  7. it ('should show an error along with the missing arguments on demand fail', function () {
  8. var r = checkUsage(function () {
  9. return yargs('-x 10 -z 20'.split(' '))
  10. .usage('Usage: $0 -x NUM -y NUM')
  11. .demand(['x','y'])
  12. .argv;
  13. });
  14. r.result.should.have.property('x', 10);
  15. r.result.should.have.property('z', 20);
  16. r.result.should.have.property('_').with.length(0);
  17. r.errors.join('\n').split(/\n+/).should.deep.equal([
  18. 'Usage: ./usage -x NUM -y NUM',
  19. 'Options:',
  20. ' -x [required]',
  21. ' -y [required]',
  22. 'Missing required arguments: y'
  23. ]);
  24. r.logs.should.have.length(0);
  25. r.exit.should.be.ok;
  26. });
  27. describe('using .require()', function() {
  28. it ('should show an error along with the missing arguments on demand fail', function () {
  29. var r = checkUsage(function () {
  30. return yargs('-x 10 -z 20'.split(' '))
  31. .usage('Usage: $0 -x NUM -y NUM')
  32. .require(['x','y'])
  33. .argv;
  34. });
  35. r.result.should.have.property('x', 10);
  36. r.result.should.have.property('z', 20);
  37. r.result.should.have.property('_').with.length(0);
  38. r.errors.join('\n').split(/\n+/).should.deep.equal([
  39. 'Usage: ./usage -x NUM -y NUM',
  40. 'Options:',
  41. ' -x [required]',
  42. ' -y [required]',
  43. 'Missing required arguments: y'
  44. ]);
  45. r.logs.should.have.length(0);
  46. r.exit.should.be.ok;
  47. });
  48. });
  49. });
  50. it('should show an error along with a custom message on demand fail', function () {
  51. var r = checkUsage(function () {
  52. return yargs('-z 20'.split(' '))
  53. .usage('Usage: $0 -x NUM -y NUM')
  54. .demand(['x','y'], 'x and y are both required to multiply all the things')
  55. .argv;
  56. });
  57. r.result.should.have.property('z', 20);
  58. r.result.should.have.property('_').with.length(0);
  59. r.errors.join('\n').split(/\n+/).should.deep.equal([
  60. 'Usage: ./usage -x NUM -y NUM',
  61. 'Options:',
  62. ' -x [required]',
  63. ' -y [required]',
  64. 'Missing required arguments: x, y',
  65. 'x and y are both required to multiply all the things'
  66. ]);
  67. r.logs.should.have.length(0);
  68. r.exit.should.be.ok;
  69. });
  70. it('should return valid values when demand passes', function () {
  71. var r = checkUsage(function () {
  72. return yargs('-x 10 -y 20'.split(' '))
  73. .usage('Usage: $0 -x NUM -y NUM')
  74. .demand(['x','y'])
  75. .argv;
  76. });
  77. r.should.have.property('result');
  78. r.result.should.have.property('x', 10);
  79. r.result.should.have.property('y', 20)
  80. r.result.should.have.property('_').with.length(0);
  81. r.should.have.property('errors').with.length(0);
  82. r.should.have.property('logs').with.length(0);
  83. r.should.have.property('exit', false);
  84. });
  85. });
  86. it('should return valid values when check passes', function () {
  87. var r = checkUsage(function () {
  88. return yargs('-x 10 -y 20'.split(' '))
  89. .usage('Usage: $0 -x NUM -y NUM')
  90. .check(function (argv) {
  91. if (!('x' in argv)) throw 'You forgot about -x';
  92. if (!('y' in argv)) throw 'You forgot about -y';
  93. })
  94. .argv;
  95. });
  96. r.should.have.property('result');
  97. r.result.should.have.property('x', 10);
  98. r.result.should.have.property('y', 20);
  99. r.result.should.have.property('_').with.length(0);
  100. r.should.have.property('errors').with.length(0);
  101. r.should.have.property('logs').with.length(0);
  102. r.should.have.property('exit', false);
  103. });
  104. it('should display missing arguments when check fails with a thrown exception', function () {
  105. var r = checkUsage(function () {
  106. return yargs('-x 10 -z 20'.split(' '))
  107. .usage('Usage: $0 -x NUM -y NUM')
  108. .check(function (argv) {
  109. if (!('x' in argv)) throw 'You forgot about -x';
  110. if (!('y' in argv)) throw 'You forgot about -y';
  111. })
  112. .argv;
  113. });
  114. r.should.have.property('result');
  115. r.result.should.have.property('x', 10);
  116. r.result.should.have.property('z', 20);
  117. r.result.should.have.property('_').with.length(0);
  118. r.errors.join('\n').split(/\n+/).should.deep.equal([
  119. 'Usage: ./usage -x NUM -y NUM',
  120. 'You forgot about -y'
  121. ]);
  122. r.should.have.property('logs').with.length(0);
  123. r.should.have.property('exit').and.be.ok;
  124. });
  125. it('should display missing arguments when check fails with a return value', function () {
  126. var r = checkUsage(function () {
  127. return yargs('-x 10 -z 20'.split(' '))
  128. .usage('Usage: $0 -x NUM -y NUM')
  129. .check(function (argv) {
  130. if (!('x' in argv)) return 'You forgot about -x';
  131. if (!('y' in argv)) return 'You forgot about -y';
  132. })
  133. .argv;
  134. });
  135. r.should.have.property('result');
  136. r.result.should.have.property('x', 10);
  137. r.result.should.have.property('z', 20);
  138. r.result.should.have.property('_').with.length(0);
  139. r.should.have.property('logs').with.length(0);
  140. r.should.have.property('exit').and.be.ok;
  141. r.should.have.property('errors');
  142. r.errors.join('\n').split(/\n+/).should.deep.equal([
  143. 'Usage: ./usage -x NUM -y NUM',
  144. 'You forgot about -y'
  145. ]);
  146. });
  147. exports.checkFailReturn = function () {
  148. var r = checkUsage(function () {
  149. return yargs('-x 10 -z 20'.split(' '))
  150. .usage('Usage: $0 -x NUM -y NUM')
  151. .check(function (argv) {
  152. if (!('x' in argv)) return 'You forgot about -x';
  153. if (!('y' in argv)) return 'You forgot about -y';
  154. })
  155. .argv;
  156. });
  157. r.should.have.property('result');
  158. r.result.should.have.property('x', 10);
  159. r.result.should.have.property('z', 20);
  160. r.result.should.have.property('_').with.length(0);
  161. r.should.have.property('logs').with.length(0);
  162. r.should.have.property('exit').and.be.ok;
  163. r.should.have.property('errors');
  164. r.errors.join('\n').split(/\n+/).should.deep.equal([
  165. 'Usage: ./usage -x NUM -y NUM',
  166. 'You forgot about -y'
  167. ]);
  168. };
  169. it('should return a valid result when check condition passes', function () {
  170. function checker (argv) {
  171. return 'x' in argv && 'y' in argv;
  172. }
  173. var r = checkUsage(function () {
  174. return yargs('-x 10 -y 20'.split(' '))
  175. .usage('Usage: $0 -x NUM -y NUM')
  176. .check(checker)
  177. .argv;
  178. });
  179. r.should.have.property('result');
  180. r.result.should.have.property('x', 10);
  181. r.result.should.have.property('y', 20);
  182. r.result.should.have.property('_').with.length(0);
  183. r.should.have.property('errors').with.length(0);
  184. r.should.have.property('logs').with.length(0);
  185. r.should.have.property('exit', false);
  186. });
  187. it('should display a failed message when check condition fails', function () {
  188. function checker (argv) {
  189. return 'x' in argv && 'y' in argv;
  190. }
  191. var r = checkUsage(function () {
  192. return yargs('-x 10 -z 20'.split(' '))
  193. .usage('Usage: $0 -x NUM -y NUM')
  194. .check(checker)
  195. .argv;
  196. });
  197. r.should.have.property('result');
  198. r.result.should.have.property('x', 10);
  199. r.result.should.have.property('z', 20);
  200. r.result.should.have.property('_').with.length(0);
  201. r.should.have.property('logs').with.length(0);
  202. r.should.have.property('exit').and.be.ok;
  203. r.should.have.property('errors');
  204. r.errors.join('\n').split(/\n+/).join('\n').should.equal(
  205. 'Usage: ./usage -x NUM -y NUM\n'
  206. + 'Argument check failed: ' + checker.toString()
  207. );
  208. });
  209. it('should return a valid result when demanding a count of non-hyphenated values', function () {
  210. var r = checkUsage(function () {
  211. return yargs('1 2 3 --moo'.split(' '))
  212. .usage('Usage: $0 [x] [y] [z] {OPTIONS}')
  213. .demand(3)
  214. .argv;
  215. });
  216. r.should.have.property('result');
  217. r.should.have.property('errors').with.length(0);
  218. r.should.have.property('logs').with.length(0);
  219. r.should.have.property('exit', false);
  220. r.result.should.have.property('_').and.deep.equal([1,2,3]);
  221. r.result.should.have.property('moo', true);
  222. });
  223. it('should return a failure message when not enough non-hyphenated arguments are found after a demand count', function () {
  224. var r = checkUsage(function () {
  225. return yargs('1 2 --moo'.split(' '))
  226. .usage('Usage: $0 [x] [y] [z] {OPTIONS}')
  227. .demand(3)
  228. .argv;
  229. });
  230. r.should.have.property('result');
  231. r.should.have.property('logs').with.length(0);
  232. r.should.have.property('exit').and.be.ok;
  233. r.result.should.have.property('_').and.deep.equal([1,2]);
  234. r.result.should.have.property('moo', true);
  235. r.should.have.property('errors');
  236. r.errors.join('\n').split(/\n+/).should.deep.equal([
  237. 'Usage: ./usage [x] [y] [z] {OPTIONS}',
  238. 'Not enough non-option arguments: got 2, need at least 3'
  239. ]);
  240. });
  241. it('should return a custom failure message when not enough non-hyphenated arguments are found after a demand count', function () {
  242. var r = checkUsage(function () {
  243. return yargs('src --moo'.split(' '))
  244. .usage('Usage: $0 [x] [y] [z] {OPTIONS} <src> <dest> [extra_files...]')
  245. .demand(2, 'src and dest files are both required')
  246. .argv;
  247. });
  248. r.should.have.property('result');
  249. r.should.have.property('logs').with.length(0);
  250. r.should.have.property('exit').and.be.ok;
  251. r.result.should.have.property('_').and.deep.equal(['src']);
  252. r.result.should.have.property('moo', true);
  253. r.should.have.property('errors');
  254. r.errors.join('\n').split(/\n+/).should.deep.equal([
  255. 'Usage: ./usage [x] [y] [z] {OPTIONS} <src> <dest> [extra_files...]',
  256. 'src and dest files are both required'
  257. ]);
  258. });
  259. it('should return a valid result when setting defaults for singles', function () {
  260. var r = checkUsage(function () {
  261. return yargs('--foo 50 --baz 70 --powsy'.split(' '))
  262. .default('foo', 5)
  263. .default('bar', 6)
  264. .default('baz', 7)
  265. .argv
  266. ;
  267. });
  268. r.should.have.property('result');
  269. r.result.should.have.property('foo', 50);
  270. r.result.should.have.property('bar', 6);
  271. r.result.should.have.property('baz', 70);
  272. r.result.should.have.property('powsy', true);
  273. r.result.should.have.property('_').with.length(0);
  274. });
  275. it('should return a valid result when default is set for an alias', function () {
  276. var r = checkUsage(function () {
  277. return yargs('')
  278. .alias('f', 'foo')
  279. .default('f', 5)
  280. .argv
  281. ;
  282. });
  283. r.should.have.property('result');
  284. r.result.should.have.property('f', 5);
  285. r.result.should.have.property('foo', 5);
  286. r.result.should.have.property('_').with.length(0);
  287. });
  288. it('should print a single line when failing and default is set for an alias', function() {
  289. var r = checkUsage(function() {
  290. return yargs('')
  291. .alias('f', 'foo')
  292. .default('f', 5)
  293. .demand(1)
  294. .argv
  295. ;
  296. });
  297. r.errors.join('\n').split(/\n+/).should.deep.equal([
  298. 'Options:',
  299. ' -f, --foo [default: 5]',
  300. 'Not enough non-option arguments: got 0, need at least 1',
  301. ]);
  302. });
  303. it('should allow you to set default values for a hash of options', function () {
  304. var r = checkUsage(function () {
  305. return yargs('--foo 50 --baz 70'.split(' '))
  306. .default({ foo : 10, bar : 20, quux : 30 })
  307. .argv
  308. ;
  309. });
  310. r.should.have.property('result');
  311. r.result.should.have.property('_').with.length(0);
  312. r.result.should.have.property('foo', 50);
  313. r.result.should.have.property('baz', 70);
  314. r.result.should.have.property('bar', 20);
  315. r.result.should.have.property('quux', 30);
  316. });
  317. describe('required arguments', function () {
  318. describe('with options object', function () {
  319. it('should show a failure message if a required option is missing', function () {
  320. var r = checkUsage(function () {
  321. var opts = {
  322. foo: { description: 'foo option', alias: 'f', requiresArg: true },
  323. bar: { description: 'bar option', alias: 'b', requiresArg: true }
  324. };
  325. return yargs('-f --bar 20'.split(' '))
  326. .usage('Usage: $0 [options]', opts)
  327. .argv;
  328. });
  329. r.should.have.property('result');
  330. r.result.should.have.property('_').with.length(0);
  331. r.should.have.property('errors');
  332. r.should.have.property('logs').with.length(0);
  333. r.should.have.property('exit').and.be.ok;
  334. r.errors.join('\n').split(/\n+/).should.deep.equal([
  335. 'Usage: ./usage [options]',
  336. 'Options:',
  337. ' --foo, -f foo option',
  338. ' --bar, -b bar option',
  339. 'Missing argument value: foo',
  340. ]);
  341. });
  342. it('should show a failure message if more than one required option is missing', function () {
  343. var r = checkUsage(function () {
  344. var opts = {
  345. foo: { description: 'foo option', alias: 'f', requiresArg: true },
  346. bar: { description: 'bar option', alias: 'b', requiresArg: true }
  347. };
  348. return yargs('-f --bar'.split(' '))
  349. .usage('Usage: $0 [options]', opts)
  350. .argv;
  351. });
  352. r.should.have.property('result');
  353. r.result.should.have.property('_').with.length(0);
  354. r.should.have.property('errors');
  355. r.should.have.property('logs').with.length(0);
  356. r.should.have.property('exit').and.be.ok;
  357. r.errors.join('\n').split(/\n+/).should.deep.equal([
  358. 'Usage: ./usage [options]',
  359. 'Options:',
  360. ' --foo, -f foo option',
  361. ' --bar, -b bar option',
  362. 'Missing argument values: foo, bar',
  363. ]);
  364. });
  365. });
  366. describe('with requiresArg method', function () {
  367. it('should show a failure message if a required option is missing', function () {
  368. var r = checkUsage(function () {
  369. var opts = {
  370. foo: { description: 'foo option', alias: 'f' },
  371. bar: { description: 'bar option', alias: 'b' }
  372. };
  373. return yargs('-f --bar 20'.split(' '))
  374. .usage('Usage: $0 [options]', opts)
  375. .requiresArg(['foo', 'bar'])
  376. .argv;
  377. });
  378. r.should.have.property('result');
  379. r.result.should.have.property('_').with.length(0);
  380. r.should.have.property('errors');
  381. r.should.have.property('logs').with.length(0);
  382. r.should.have.property('exit').and.be.ok;
  383. r.errors.join('\n').split(/\n+/).should.deep.equal([
  384. 'Usage: ./usage [options]',
  385. 'Options:',
  386. ' --foo, -f foo option',
  387. ' --bar, -b bar option',
  388. 'Missing argument value: foo',
  389. ]);
  390. });
  391. });
  392. });
  393. context("with strict() option set", function () {
  394. it('should fail given an option argument that is not demanded', function () {
  395. var r = checkUsage(function () {
  396. opts = {
  397. foo: { demand: 'foo option', alias: 'f' },
  398. bar: { demand: 'bar option', alias: 'b' }
  399. };
  400. return yargs('-f 10 --bar 20 --baz 30'.split(' '))
  401. .usage('Usage: $0 [options]', opts)
  402. .strict()
  403. .argv;
  404. });
  405. r.should.have.property('result');
  406. r.result.should.have.property('_').with.length(0);
  407. r.result.should.have.property('f', 10);
  408. r.result.should.have.property('foo', 10);
  409. r.result.should.have.property('b', 20);
  410. r.result.should.have.property('bar', 20);
  411. r.result.should.have.property('baz', 30);
  412. r.should.have.property('errors');
  413. r.errors.join('\n').split(/\n+/).should.deep.equal([
  414. 'Usage: ./usage [options]',
  415. 'Options:',
  416. ' --foo, -f [required]',
  417. ' --bar, -b [required]',
  418. 'Unknown argument: baz',
  419. ]);
  420. r.should.have.property('logs').with.length(0);
  421. r.should.have.property('exit').and.be.ok;
  422. });
  423. it('should fail given an option argument without a corresponding description', function () {
  424. var r = checkUsage(function () {
  425. opts = {
  426. foo: { description: 'foo option', alias: 'f' },
  427. bar: { description: 'bar option', alias: 'b' }
  428. };
  429. return yargs('-f 10 --bar 20 --baz 30'.split(' '))
  430. .usage('Usage: $0 [options]', opts)
  431. .strict()
  432. .argv;
  433. });
  434. r.should.have.property('result');
  435. r.result.should.have.property('_').with.length(0);
  436. r.result.should.have.property('f', 10);
  437. r.result.should.have.property('foo', 10);
  438. r.result.should.have.property('b', 20);
  439. r.result.should.have.property('bar', 20);
  440. r.result.should.have.property('baz', 30);
  441. r.should.have.property('errors');
  442. r.errors.join('\n').split(/\n+/).should.deep.equal([
  443. 'Usage: ./usage [options]',
  444. 'Options:',
  445. ' --foo, -f foo option',
  446. ' --bar, -b bar option',
  447. 'Unknown argument: baz',
  448. ]);
  449. r.should.have.property('logs').with.length(0);
  450. r.should.have.property('exit').and.be.ok;
  451. });
  452. it('should fail given multiple option arguments without corresponding descriptions', function () {
  453. var r = checkUsage(function () {
  454. opts = {
  455. foo: { description: 'foo option', alias: 'f' },
  456. bar: { description: 'bar option', alias: 'b' }
  457. };
  458. return yargs('-f 10 --bar 20 --baz 30 -q 40'.split(' '))
  459. .usage('Usage: $0 [options]', opts)
  460. .strict()
  461. .argv;
  462. });
  463. r.should.have.property('result');
  464. r.result.should.have.property('_').with.length(0);
  465. r.result.should.have.property('f', 10);
  466. r.result.should.have.property('foo', 10);
  467. r.result.should.have.property('b', 20);
  468. r.result.should.have.property('bar', 20);
  469. r.result.should.have.property('baz', 30);
  470. r.result.should.have.property('q', 40);
  471. r.should.have.property('errors');
  472. r.errors.join('\n').split(/\n+/).should.deep.equal([
  473. 'Usage: ./usage [options]',
  474. 'Options:',
  475. ' --foo, -f foo option',
  476. ' --bar, -b bar option',
  477. 'Unknown arguments: baz, q',
  478. ]);
  479. r.should.have.property('logs').with.length(0);
  480. r.should.have.property('exit').and.be.ok;
  481. });
  482. it('should pass given option arguments with corresponding descriptions', function () {
  483. var r = checkUsage(function () {
  484. opts = {
  485. foo: { description: 'foo option' },
  486. bar: { description: 'bar option' }
  487. };
  488. return yargs('--foo 10 --bar 20'.split(' '))
  489. .usage('Usage: $0 [options]', opts)
  490. .strict()
  491. .argv;
  492. });
  493. r.should.have.property('result');
  494. r.result.should.have.property('foo', 10);
  495. r.result.should.have.property('bar', 20)
  496. r.result.should.have.property('_').with.length(0);
  497. r.should.have.property('errors').with.length(0);
  498. r.should.have.property('logs').with.length(0);
  499. r.should.have.property('exit', false);
  500. });
  501. });
  502. it('should display example on fail', function () {
  503. var r = checkUsage(function () {
  504. return yargs('')
  505. .example("$0 something", "description")
  506. .example("$0 something else", "other description")
  507. .demand(['y'])
  508. .argv;
  509. });
  510. r.should.have.property('result');
  511. r.result.should.have.property('_').with.length(0);
  512. r.should.have.property('errors');
  513. r.should.have.property('logs').with.length(0);
  514. r.should.have.property('exit').and.be.ok;
  515. r.errors.join('\n').split(/\n+/).should.deep.equal([
  516. 'Examples:',
  517. ' ./usage something description',
  518. ' ./usage something else other description',
  519. 'Options:',
  520. ' -y [required]',
  521. 'Missing required arguments: y'
  522. ]);
  523. });
  524. describe('demand option with boolean flag', function () {
  525. describe('with demand option', function () {
  526. it('should report missing required arguments', function () {
  527. var r = checkUsage(function () {
  528. return yargs('-y 10 -z 20'.split(' '))
  529. .usage('Usage: $0 -x NUM [-y NUM]')
  530. .options({
  531. 'x': { description: 'an option', demand: true },
  532. 'y': { description: 'another option', demand: false }
  533. })
  534. .argv;
  535. });
  536. r.result.should.have.property('y', 10);
  537. r.result.should.have.property('z', 20);
  538. r.result.should.have.property('_').with.length(0);
  539. r.errors.join('\n').split(/\n/).should.deep.equal([
  540. 'Usage: ./usage -x NUM [-y NUM]',
  541. '',
  542. 'Options:',
  543. ' -x an option [required]',
  544. ' -y another option',
  545. '',
  546. 'Missing required arguments: x'
  547. ]);
  548. r.logs.should.have.length(0);
  549. r.exit.should.be.ok;
  550. });
  551. });
  552. describe('with required option', function () {
  553. it('should report missing required arguments', function () {
  554. var r = checkUsage(function () {
  555. return yargs('-y 10 -z 20'.split(' '))
  556. .usage('Usage: $0 -x NUM [-y NUM]')
  557. .options({
  558. 'x': { description: 'an option', required: true },
  559. 'y': { description: 'another option', required: false }
  560. })
  561. .argv;
  562. });
  563. r.result.should.have.property('y', 10);
  564. r.result.should.have.property('z', 20);
  565. r.result.should.have.property('_').with.length(0);
  566. r.errors.join('\n').split(/\n/).should.deep.equal([
  567. 'Usage: ./usage -x NUM [-y NUM]',
  568. '',
  569. 'Options:',
  570. ' -x an option [required]',
  571. ' -y another option',
  572. '',
  573. 'Missing required arguments: x'
  574. ]);
  575. r.logs.should.have.length(0);
  576. r.exit.should.be.ok;
  577. });
  578. });
  579. it('should not report missing required arguments when given an alias', function () {
  580. var r = checkUsage(function () {
  581. return yargs('-w 10'.split(' '))
  582. .usage('Usage: $0 --width NUM [--height NUM]')
  583. .options({
  584. 'width': { description: 'Width', alias: 'w', demand: true },
  585. 'height': { description: 'Height', alias: 'h', demand: false }
  586. })
  587. .argv;
  588. });
  589. r.result.should.have.property('w', 10);
  590. r.result.should.have.property('_').with.length(0);
  591. r.should.have.property('errors').with.length(0);
  592. r.logs.should.have.length(0);
  593. });
  594. });
  595. describe('help option', function () {
  596. it('should display usage', function () {
  597. var r = checkUsage(function () {
  598. return yargs(['--help'])
  599. .demand(['y'])
  600. .help('help')
  601. .argv;
  602. });
  603. r.should.have.property('result');
  604. r.result.should.have.property('_').with.length(0);
  605. r.should.have.property('errors');
  606. r.should.have.property('logs').with.length(1);
  607. r.should.have.property('exit').and.be.ok;
  608. r.logs.join('\n').split(/\n+/).should.deep.equal([
  609. 'Options:',
  610. ' --help Show help',
  611. ' -y [required]',
  612. ''
  613. ]);
  614. });
  615. it('should not show both dashed and camelCase aliases', function () {
  616. var r = checkUsage(function () {
  617. return yargs(['--help'])
  618. .usage('Usage: $0 options')
  619. .help('help')
  620. .describe('some-opt', 'Some option')
  621. .default('some-opt', 2)
  622. .argv;
  623. });
  624. r.should.have.property('result');
  625. r.result.should.have.property('_').with.length(0);
  626. r.should.have.property('exit').and.be.ok;
  627. r.should.have.property('errors').with.length(0);
  628. r.should.have.property('logs');
  629. r.logs.join('\n').split(/\n+/).should.deep.equal([
  630. 'Usage: ./usage options',
  631. 'Options:',
  632. ' --help Show help ',
  633. ' --some-opt Some option [default: 2]',
  634. ''
  635. ]);
  636. });
  637. });
  638. describe('version option', function () {
  639. it('should display version', function () {
  640. var r = checkUsage(function () {
  641. return yargs(['--version'])
  642. .version('1.0.1', 'version', 'Show version number')
  643. .argv;
  644. });
  645. r.should.have.property('result');
  646. r.result.should.have.property('_').with.length(0);
  647. r.should.have.property('errors');
  648. r.should.have.property('logs').with.length(1);
  649. r.should.have.property('exit').and.be.ok;
  650. r.logs.join('\n').split(/\n+/).should.deep.equal([
  651. '1.0.1'
  652. ]);
  653. });
  654. });
  655. describe('showHelpOnFail', function () {
  656. it('should display user supplied message', function () {
  657. var opts = {
  658. foo: { desc: 'foo option', alias: 'f' },
  659. bar: { desc: 'bar option', alias: 'b' }
  660. };
  661. var r = checkUsage(function () {
  662. return yargs(['--foo'])
  663. .usage('Usage: $0 [options]')
  664. .options(opts)
  665. .demand(['foo', 'bar'])
  666. .showHelpOnFail(false, "Specify --help for available options")
  667. .argv;
  668. });
  669. r.should.have.property('result');
  670. r.result.should.have.property('_').with.length(0);
  671. r.should.have.property('errors');
  672. r.should.have.property('logs').with.length(0);
  673. r.should.have.property('exit').and.be.ok;
  674. r.errors.join('\n').split(/\n/).should.deep.equal([
  675. 'Missing required arguments: bar',
  676. '',
  677. 'Specify --help for available options'
  678. ]);
  679. });
  680. });
  681. it('should succeed when rebase', function () {
  682. yargs.rebase('/home/chevex', '/home/chevex/foo/bar/baz').should.equal('./foo/bar/baz');
  683. yargs.rebase('/home/chevex/foo/bar/baz', '/home/chevex').should.equal('../../..');
  684. yargs.rebase('/home/chevex/foo', '/home/chevex/pow/zoom.txt').should.equal('../pow/zoom.txt');
  685. });
  686. function checkUsage (f) {
  687. var exit = false;
  688. process._exit = process.exit;
  689. process._env = process.env;
  690. process._argv = process.argv;
  691. process.stdout._write = process.stdout.write;
  692. process.exit = function () { exit = true };
  693. process.env = Hash.merge(process.env, { _ : 'node' });
  694. process.argv = [ './usage' ];
  695. process.stdout.write = function (msg) { logs.push(msg) };
  696. var errors = [];
  697. var logs = [];
  698. console._error = console.error;
  699. console.error = function (msg) { errors.push(msg) };
  700. console._log = console.log;
  701. console.log = function (msg) { logs.push(msg) };
  702. var result = f();
  703. process.exit = process._exit;
  704. process.env = process._env;
  705. process.argv = process._argv;
  706. process.stdout.write = process.stdout._write;
  707. console.error = console._error;
  708. console.log = console._log;
  709. return {
  710. errors : errors,
  711. logs : logs,
  712. exit : exit,
  713. result : result
  714. };
  715. };
  716. });