| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647 | 
							- #!/usr/bin/env node
 
- 'use strict';
 
- /* eslint no-unused-vars: off */
 
- /**
 
-  * Module dependencies.
 
-  */
 
- const program = require('commander');
 
- const path = require('path');
 
- const fs = require('fs');
 
- const minimatch = require('minimatch');
 
- const resolve = path.resolve;
 
- const exists = fs.existsSync;
 
- const Mocha = require('../');
 
- const utils = Mocha.utils;
 
- const interfaceNames = Object.keys(Mocha.interfaces);
 
- const join = path.join;
 
- const cwd = process.cwd();
 
- const getOptions = require('./options');
 
- const mocha = new Mocha();
 
- /**
 
-  * Save timer references to avoid Sinon interfering (see GH-237).
 
-  */
 
- const Date = global.Date;
 
- const setTimeout = global.setTimeout;
 
- const setInterval = global.setInterval;
 
- const clearTimeout = global.clearTimeout;
 
- const clearInterval = global.clearInterval;
 
- /**
 
-  * Exits Mocha when tests + code under test has finished execution (default)
 
-  * @param {number} code - Exit code; typically # of failures
 
-  */
 
- const exitLater = code => {
 
-   process.on('exit', () => {
 
-     process.exit(Math.min(code, 255));
 
-   });
 
- };
 
- /**
 
-  * Exits Mocha when Mocha itself has finished execution, regardless of
 
-  * what the tests or code under test is doing.
 
-  * @param {number} code - Exit code; typically # of failures
 
-  */
 
- const exit = code => {
 
-   const clampedCode = Math.min(code, 255);
 
-   let draining = 0;
 
-   // Eagerly set the process's exit code in case stream.write doesn't
 
-   // execute its callback before the process terminates.
 
-   process.exitCode = clampedCode;
 
-   // flush output for Node.js Windows pipe bug
 
-   // https://github.com/joyent/node/issues/6247 is just one bug example
 
-   // https://github.com/visionmedia/mocha/issues/333 has a good discussion
 
-   const done = () => {
 
-     if (!draining--) {
 
-       process.exit(clampedCode);
 
-     }
 
-   };
 
-   const streams = [process.stdout, process.stderr];
 
-   streams.forEach(stream => {
 
-     // submit empty write request and wait for completion
 
-     draining += 1;
 
-     stream.write('', done);
 
-   });
 
-   done();
 
- };
 
- /**
 
-  * Parse list.
 
-  */
 
- const list = str => str.split(/ *, */);
 
- /**
 
-  * Parse multiple flag.
 
-  */
 
- const collect = (val, memo) => memo.concat(val);
 
- /**
 
-  * Hide the cursor.
 
-  */
 
- const hideCursor = () => {
 
-   process.stdout.write('\u001b[?25l');
 
- };
 
- /**
 
-  * Show the cursor.
 
-  */
 
- const showCursor = () => {
 
-   process.stdout.write('\u001b[?25h');
 
- };
 
- /**
 
-  * Stop play()ing.
 
-  */
 
- const stop = () => {
 
-   process.stdout.write('\u001b[2K');
 
-   clearInterval(play.timer);
 
- };
 
- /**
 
-  * Play the given array of strings.
 
-  */
 
- const play = (arr, interval) => {
 
-   const len = arr.length;
 
-   interval = interval || 100;
 
-   let i = 0;
 
-   play.timer = setInterval(() => {
 
-     const str = arr[i++ % len];
 
-     process.stdout.write(`\u001b[0G${str}`);
 
-   }, interval);
 
- };
 
- /**
 
-  * Files.
 
-  */
 
- let files = [];
 
- /**
 
-  * Globals.
 
-  */
 
- let globals = [];
 
- /**
 
-  * Requires.
 
-  */
 
- const requires = [];
 
- /**
 
-  * Images.
 
-  */
 
- const images = {
 
-   fail: path.join(__dirname, '..', 'assets', 'growl', 'error.png'),
 
-   pass: path.join(__dirname, '..', 'assets', 'growl', 'ok.png')
 
- };
 
- // options
 
- program
 
-   .version(
 
-     JSON.parse(
 
-       fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')
 
-     ).version
 
-   )
 
-   .usage('[debug] [options] [files]')
 
-   .option(
 
-     '-A, --async-only',
 
-     'force all tests to take a callback (async) or return a promise'
 
-   )
 
-   .option('-c, --colors', 'force enabling of colors')
 
-   .option('-C, --no-colors', 'force disabling of colors')
 
-   .option('-G, --growl', 'enable growl notification support')
 
-   .option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
 
-   .option('-R, --reporter <name>', 'specify the reporter to use', 'spec')
 
-   .option('-S, --sort', 'sort test files')
 
-   .option('-b, --bail', 'bail after first test failure')
 
-   .option('-d, --debug', "enable node's debugger, synonym for node --debug")
 
-   .option('-g, --grep <pattern>', 'only run tests matching <pattern>')
 
-   .option('-f, --fgrep <string>', 'only run tests containing <string>')
 
-   .option('-gc, --expose-gc', 'expose gc extension')
 
-   .option('-i, --invert', 'inverts --grep and --fgrep matches')
 
-   .option('-r, --require <name>', 'require the given module')
 
-   .option('-s, --slow <ms>', '"slow" test threshold in milliseconds [75]')
 
-   .option('-t, --timeout <ms>', 'set test-case timeout in milliseconds [2000]')
 
-   .option(
 
-     '-u, --ui <name>',
 
-     `specify user-interface (${interfaceNames.join('|')})`,
 
-     'bdd'
 
-   )
 
-   .option('-w, --watch', 'watch files for changes')
 
-   .option('--check-leaks', 'check for global variable leaks')
 
-   .option('--full-trace', 'display the full stack trace')
 
-   .option(
 
-     '--compilers <ext>:<module>,...',
 
-     'use the given module(s) to compile files',
 
-     list,
 
-     []
 
-   )
 
-   .option('--debug-brk', "enable node's debugger breaking on the first line")
 
-   .option(
 
-     '--globals <names>',
 
-     'allow the given comma-delimited global [names]',
 
-     list,
 
-     []
 
-   )
 
-   .option('--es_staging', 'enable all staged features')
 
-   .option(
 
-     '--harmony<_classes,_generators,...>',
 
-     'all node --harmony* flags are available'
 
-   )
 
-   .option(
 
-     '--preserve-symlinks',
 
-     'Instructs the module loader to preserve symbolic links when resolving and caching modules'
 
-   )
 
-   .option('--icu-data-dir', 'include ICU data')
 
-   .option(
 
-     '--inline-diffs',
 
-     'display actual/expected differences inline within each string'
 
-   )
 
-   .option('--no-diff', 'do not show a diff on failure')
 
-   .option('--inspect', 'activate devtools in chrome')
 
-   .option(
 
-     '--inspect-brk',
 
-     'activate devtools in chrome and break on the first line'
 
-   )
 
-   .option('--interfaces', 'display available interfaces')
 
-   .option('--no-deprecation', 'silence deprecation warnings')
 
-   .option(
 
-     '--exit',
 
-     'force shutdown of the event loop after test run: mocha will call process.exit'
 
-   )
 
-   .option('--no-timeouts', 'disables timeouts, given implicitly with --debug')
 
-   .option('--no-warnings', 'silence all node process warnings')
 
-   .option('--opts <path>', 'specify opts path', 'test/mocha.opts')
 
-   .option('--perf-basic-prof', 'enable perf linux profiler (basic support)')
 
-   .option('--napi-modules', 'enable experimental NAPI modules')
 
-   .option('--prof', 'log statistical profiling information')
 
-   .option('--log-timer-events', 'Time events including external callbacks')
 
-   .option('--recursive', 'include sub directories')
 
-   .option('--reporters', 'display available reporters')
 
-   .option(
 
-     '--retries <times>',
 
-     'set numbers of time to retry a failed test case'
 
-   )
 
-   .option(
 
-     '--throw-deprecation',
 
-     'throw an exception anytime a deprecated function is used'
 
-   )
 
-   .option('--trace', 'trace function calls')
 
-   .option('--trace-deprecation', 'show stack traces on deprecations')
 
-   .option('--trace-warnings', 'show stack traces on node process warnings')
 
-   .option('--use_strict', 'enforce strict mode')
 
-   .option(
 
-     '--watch-extensions <ext>,...',
 
-     'additional extensions to monitor with --watch',
 
-     list,
 
-     ['js']
 
-   )
 
-   .option('--delay', 'wait for async suite definition')
 
-   .option('--allow-uncaught', 'enable uncaught errors to propagate')
 
-   .option('--forbid-only', 'causes test marked with only to fail the suite')
 
-   .option(
 
-     '--forbid-pending',
 
-     'causes pending tests and test marked with skip to fail the suite'
 
-   )
 
-   .option(
 
-     '--file <file>',
 
-     'include a file to be ran during the suite',
 
-     collect,
 
-     []
 
-   )
 
-   .option('--exclude <file>', 'a file or glob pattern to ignore', collect, []);
 
- program._name = 'mocha';
 
- // init command
 
- program
 
-   .command('init <path>')
 
-   .description('initialize a client-side mocha setup at <path>')
 
-   .action(path => {
 
-     const mkdir = require('mkdirp');
 
-     mkdir.sync(path);
 
-     const css = fs.readFileSync(join(__dirname, '..', 'mocha.css'));
 
-     const js = fs.readFileSync(join(__dirname, '..', 'mocha.js'));
 
-     const tmpl = fs.readFileSync(join(__dirname, '..', 'lib/template.html'));
 
-     fs.writeFileSync(join(path, 'mocha.css'), css);
 
-     fs.writeFileSync(join(path, 'mocha.js'), js);
 
-     fs.writeFileSync(join(path, 'tests.js'), '');
 
-     fs.writeFileSync(join(path, 'index.html'), tmpl);
 
-     process.exit(0);
 
-   });
 
- // --globals
 
- program.on('option:globals', val => {
 
-   globals = globals.concat(list(val));
 
- });
 
- // --reporters
 
- program.on('option:reporters', () => {
 
-   console.log();
 
-   console.log('    dot - dot matrix');
 
-   console.log('    doc - html documentation');
 
-   console.log('    spec - hierarchical spec list');
 
-   console.log('    json - single json object');
 
-   console.log('    progress - progress bar');
 
-   console.log('    list - spec-style listing');
 
-   console.log('    tap - test-anything-protocol');
 
-   console.log('    landing - unicode landing strip');
 
-   console.log('    xunit - xunit reporter');
 
-   console.log('    min - minimal reporter (great with --watch)');
 
-   console.log('    json-stream - newline delimited json events');
 
-   console.log('    markdown - markdown documentation (github flavour)');
 
-   console.log('    nyan - nyan cat!');
 
-   console.log();
 
-   process.exit();
 
- });
 
- // --interfaces
 
- program.on('option:interfaces', () => {
 
-   console.log('');
 
-   interfaceNames.forEach(interfaceName => {
 
-     console.log(`    ${interfaceName}`);
 
-   });
 
-   console.log('');
 
-   process.exit();
 
- });
 
- // -r, --require
 
- module.paths.push(cwd, join(cwd, 'node_modules'));
 
- program.on('option:require', mod => {
 
-   const abs = exists(mod) || exists(`${mod}.js`);
 
-   if (abs) {
 
-     mod = resolve(mod);
 
-   }
 
-   requires.push(mod);
 
- });
 
- // If not already done, load mocha.opts
 
- if (!process.env.LOADED_MOCHA_OPTS) {
 
-   getOptions();
 
- }
 
- // parse args
 
- program.parse(process.argv);
 
- // infinite stack traces
 
- Error.stackTraceLimit = Infinity; // TODO: config
 
- // reporter options
 
- const reporterOptions = {};
 
- if (program.reporterOptions !== undefined) {
 
-   program.reporterOptions.split(',').forEach(opt => {
 
-     const L = opt.split('=');
 
-     if (L.length > 2 || L.length === 0) {
 
-       throw new Error(`invalid reporter option '${opt}'`);
 
-     } else if (L.length === 2) {
 
-       reporterOptions[L[0]] = L[1];
 
-     } else {
 
-       reporterOptions[L[0]] = true;
 
-     }
 
-   });
 
- }
 
- // reporter
 
- mocha.reporter(program.reporter, reporterOptions);
 
- // --no-colors
 
- if (!program.colors) {
 
-   mocha.useColors(false);
 
- }
 
- // --colors
 
- if (~process.argv.indexOf('--colors') || ~process.argv.indexOf('-c')) {
 
-   mocha.useColors(true);
 
- }
 
- // --inline-diffs
 
- if (program.inlineDiffs) {
 
-   mocha.useInlineDiffs(true);
 
- }
 
- // --no-diff
 
- if (process.argv.indexOf('--no-diff') !== -1) {
 
-   mocha.hideDiff(true);
 
- }
 
- // --slow <ms>
 
- if (program.slow) {
 
-   mocha.suite.slow(program.slow);
 
- }
 
- // --no-timeouts
 
- if (!program.timeouts) {
 
-   mocha.enableTimeouts(false);
 
- }
 
- // --timeout
 
- if (program.timeout) {
 
-   mocha.suite.timeout(program.timeout);
 
- }
 
- // --bail
 
- mocha.suite.bail(program.bail);
 
- // --grep
 
- if (program.grep) {
 
-   mocha.grep(program.grep);
 
- }
 
- // --fgrep
 
- if (program.fgrep) {
 
-   mocha.fgrep(program.fgrep);
 
- }
 
- // --invert
 
- if (program.invert) {
 
-   mocha.invert();
 
- }
 
- // --check-leaks
 
- if (program.checkLeaks) {
 
-   mocha.checkLeaks();
 
- }
 
- // --stack-trace
 
- if (program.fullTrace) {
 
-   mocha.fullTrace();
 
- }
 
- // --growl
 
- if (program.growl) {
 
-   mocha.growl();
 
- }
 
- // --async-only
 
- if (program.asyncOnly) {
 
-   mocha.asyncOnly();
 
- }
 
- // --delay
 
- if (program.delay) {
 
-   mocha.delay();
 
- }
 
- // --allow-uncaught
 
- if (program.allowUncaught) {
 
-   mocha.allowUncaught();
 
- }
 
- // --globals
 
- mocha.globals(globals);
 
- // --retries
 
- if (program.retries) {
 
-   mocha.suite.retries(program.retries);
 
- }
 
- // --forbid-only
 
- if (program.forbidOnly) mocha.forbidOnly();
 
- // --forbid-pending
 
- if (program.forbidPending) mocha.forbidPending();
 
- // custom compiler support
 
- if (program.compilers.length > 0) {
 
-   require('util').deprecate(() => {},
 
-   '"--compilers" will be removed in a future version of Mocha; see https://git.io/vdcSr for more info')();
 
- }
 
- const extensions = ['js'];
 
- program.compilers.forEach(c => {
 
-   const idx = c.indexOf(':');
 
-   const ext = c.slice(0, idx);
 
-   let mod = c.slice(idx + 1);
 
-   if (mod[0] === '.') {
 
-     mod = join(process.cwd(), mod);
 
-   }
 
-   require(mod);
 
-   extensions.push(ext);
 
-   program.watchExtensions.push(ext);
 
- });
 
- // requires
 
- requires.forEach(mod => {
 
-   require(mod);
 
- });
 
- // interface
 
- mocha.ui(program.ui);
 
- // args
 
- const args = program.args;
 
- // default files to test/*.{js,coffee}
 
- if (!args.length) {
 
-   args.push('test');
 
- }
 
- args.forEach(arg => {
 
-   let newFiles;
 
-   try {
 
-     newFiles = utils.lookupFiles(arg, extensions, program.recursive);
 
-   } catch (err) {
 
-     if (err.message.indexOf('cannot resolve path') === 0) {
 
-       console.error(
 
-         `Warning: Could not find any test files matching pattern: ${arg}`
 
-       );
 
-       return;
 
-     }
 
-     throw err;
 
-   }
 
-   if (typeof newFiles !== 'undefined') {
 
-     if (typeof newFiles === 'string') {
 
-       newFiles = [newFiles];
 
-     }
 
-     newFiles = newFiles.filter(fileName =>
 
-       program.exclude.every(pattern => !minimatch(fileName, pattern))
 
-     );
 
-   }
 
-   files = files.concat(newFiles);
 
- });
 
- if (!files.length) {
 
-   console.error('No test files found');
 
-   process.exit(1);
 
- }
 
- // resolve
 
- let fileArgs = program.file.map(path => resolve(path));
 
- files = files.map(path => resolve(path));
 
- if (program.sort) {
 
-   files.sort();
 
- }
 
- // add files given through --file to be ran first
 
- files = fileArgs.concat(files);
 
- // --watch
 
- let runner;
 
- let loadAndRun;
 
- let purge;
 
- let rerun;
 
- if (program.watch) {
 
-   console.log();
 
-   hideCursor();
 
-   process.on('SIGINT', () => {
 
-     showCursor();
 
-     console.log('\n');
 
-     process.exit(130);
 
-   });
 
-   const watchFiles = utils.files(cwd, ['js'].concat(program.watchExtensions));
 
-   let runAgain = false;
 
-   loadAndRun = () => {
 
-     try {
 
-       mocha.files = files;
 
-       runAgain = false;
 
-       runner = mocha.run(() => {
 
-         runner = null;
 
-         if (runAgain) {
 
-           rerun();
 
-         }
 
-       });
 
-     } catch (e) {
 
-       console.log(e.stack);
 
-     }
 
-   };
 
-   purge = () => {
 
-     watchFiles.forEach(file => {
 
-       delete require.cache[file];
 
-     });
 
-   };
 
-   loadAndRun();
 
-   rerun = () => {
 
-     purge();
 
-     stop();
 
-     if (!program.grep) {
 
-       mocha.grep(null);
 
-     }
 
-     mocha.suite = mocha.suite.clone();
 
-     mocha.suite.ctx = new Mocha.Context();
 
-     mocha.ui(program.ui);
 
-     loadAndRun();
 
-   };
 
-   utils.watch(watchFiles, () => {
 
-     runAgain = true;
 
-     if (runner) {
 
-       runner.abort();
 
-     } else {
 
-       rerun();
 
-     }
 
-   });
 
- } else {
 
-   // load
 
-   mocha.files = files;
 
-   runner = mocha.run(program.exit ? exit : exitLater);
 
- }
 
- process.on('SIGINT', () => {
 
-   runner.abort();
 
-   // This is a hack:
 
-   // Instead of `process.exit(130)`, set runner.failures to 130 (exit code for SIGINT)
 
-   // The amount of failures will be emitted as error code later
 
-   runner.failures = 130;
 
- });
 
 
  |