cli.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. 'use strict';
  2. /**
  3. * Contains CLI entry point and public API for programmatic usage in Node.js.
  4. * - Option parsing is handled by {@link https://npm.im/yargs yargs}.
  5. * - If executed via `node`, this module will run {@linkcode module:lib/cli.main main()}.
  6. * @public
  7. * @module lib/cli
  8. */
  9. const debug = require('debug')('mocha:cli:cli');
  10. const symbols = require('log-symbols');
  11. const yargs = require('yargs');
  12. const path = require('node:path');
  13. const {
  14. loadRc,
  15. loadPkgRc,
  16. loadOptions,
  17. YARGS_PARSER_CONFIG
  18. } = require('./options');
  19. const lookupFiles = require('./lookup-files');
  20. const commands = require('./commands');
  21. const pc = require('picocolors');
  22. const {repository, homepage, version, discord} = require('../../package.json');
  23. const {cwd} = require('../utils');
  24. /**
  25. * - Accepts an `Array` of arguments
  26. * - Modifies {@link https://nodejs.org/api/modules.html#modules_module_paths Node.js' search path} for easy loading of consumer modules
  27. * - Sets {@linkcode https://nodejs.org/api/errors.html#errors_error_stacktracelimit Error.stackTraceLimit} to `Infinity`
  28. * @public
  29. * @summary Mocha's main command-line entry-point.
  30. * @param {string[]} argv - Array of arguments to parse, or by default the lovely `process.argv.slice(2)`
  31. * @param {object} [mochaArgs] - Object of already parsed Mocha arguments (by bin/mocha)
  32. */
  33. exports.main = (argv = process.argv.slice(2), mochaArgs) => {
  34. debug('entered main with raw args', argv);
  35. // ensure we can require() from current working directory
  36. if (typeof module.paths !== 'undefined') {
  37. module.paths.push(cwd(), path.resolve('node_modules'));
  38. }
  39. try {
  40. Error.stackTraceLimit = Infinity; // configurable via --stack-trace-limit?
  41. } catch (err) {
  42. debug('unable to set Error.stackTraceLimit = Infinity', err);
  43. }
  44. var args = mochaArgs || loadOptions(argv);
  45. yargs()
  46. .scriptName('mocha')
  47. .command(commands.run)
  48. .command(commands.init)
  49. .updateStrings({
  50. 'Positionals:': 'Positional Arguments',
  51. 'Options:': 'Other Options',
  52. 'Commands:': 'Commands'
  53. })
  54. .fail((msg, err, yargs) => {
  55. debug('caught error sometime before command handler: %O', err);
  56. yargs.showHelp();
  57. console.error(`\n${symbols.error} ${pc.red('ERROR:')} ${msg}`);
  58. process.exit(1);
  59. })
  60. .help('help', 'Show usage information & exit')
  61. .alias('help', 'h')
  62. .version('version', 'Show version number & exit', version)
  63. .alias('version', 'V')
  64. .wrap(process.stdout.columns ? Math.min(process.stdout.columns, 80) : 80)
  65. .epilog(
  66. `${pc.reset("Mocha Resources")}
  67. Chat: ${pc.magenta(discord)}
  68. GitHub: ${pc.blue(repository.url)}
  69. Docs: ${pc.yellow(homepage)}
  70. `
  71. )
  72. .parserConfiguration(YARGS_PARSER_CONFIG)
  73. .config(args)
  74. .parse(args._);
  75. };
  76. exports.lookupFiles = lookupFiles;
  77. exports.loadOptions = loadOptions;
  78. exports.loadPkgRc = loadPkgRc;
  79. exports.loadRc = loadRc;
  80. // allow direct execution
  81. if (require.main === module) {
  82. exports.main();
  83. }