mocha 5.1.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +686 -984
  2. package/README.md +2 -1
  3. package/{images → assets/growl}/error.png +0 -0
  4. package/{images → assets/growl}/ok.png +0 -0
  5. package/bin/_mocha +4 -595
  6. package/bin/mocha +121 -61
  7. package/bin/options.js +6 -39
  8. package/browser-entry.js +21 -17
  9. package/lib/browser/growl.js +165 -2
  10. package/lib/browser/progress.js +11 -11
  11. package/lib/{template.html → browser/template.html} +0 -0
  12. package/lib/browser/tty.js +2 -2
  13. package/lib/cli/cli.js +68 -0
  14. package/lib/cli/commands.js +13 -0
  15. package/lib/cli/config.js +79 -0
  16. package/lib/cli/index.js +9 -0
  17. package/lib/cli/init.js +37 -0
  18. package/lib/cli/node-flags.js +69 -0
  19. package/lib/cli/one-and-dones.js +70 -0
  20. package/lib/cli/options.js +330 -0
  21. package/lib/cli/run-helpers.js +337 -0
  22. package/lib/cli/run-option-metadata.js +76 -0
  23. package/lib/cli/run.js +297 -0
  24. package/lib/context.js +14 -14
  25. package/lib/errors.js +141 -0
  26. package/lib/growl.js +136 -0
  27. package/lib/hook.js +5 -16
  28. package/lib/interfaces/bdd.js +16 -13
  29. package/lib/interfaces/common.js +62 -18
  30. package/lib/interfaces/exports.js +5 -8
  31. package/lib/interfaces/qunit.js +10 -10
  32. package/lib/interfaces/tdd.js +12 -11
  33. package/lib/mocha.js +477 -256
  34. package/lib/mocharc.json +10 -0
  35. package/lib/pending.js +1 -5
  36. package/lib/reporters/base.js +95 -117
  37. package/lib/reporters/doc.js +23 -9
  38. package/lib/reporters/dot.js +19 -13
  39. package/lib/reporters/html.js +82 -47
  40. package/lib/reporters/json-stream.js +43 -23
  41. package/lib/reporters/json.js +32 -23
  42. package/lib/reporters/landing.js +16 -9
  43. package/lib/reporters/list.js +19 -11
  44. package/lib/reporters/markdown.js +18 -12
  45. package/lib/reporters/min.js +8 -4
  46. package/lib/reporters/nyan.js +42 -35
  47. package/lib/reporters/progress.js +12 -7
  48. package/lib/reporters/spec.js +23 -12
  49. package/lib/reporters/tap.js +250 -32
  50. package/lib/reporters/xunit.js +61 -35
  51. package/lib/runnable.js +152 -95
  52. package/lib/runner.js +296 -248
  53. package/lib/stats-collector.js +83 -0
  54. package/lib/suite.js +294 -75
  55. package/lib/test.js +16 -15
  56. package/lib/utils.js +419 -146
  57. package/mocha.js +4589 -2228
  58. package/package.json +137 -38
  59. package/lib/ms.js +0 -94
  60. package/lib/reporters/base.js.orig +0 -498
  61. package/lib/reporters/json.js.orig +0 -128
package/lib/mocha.js CHANGED
@@ -5,22 +5,22 @@
5
5
  * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
6
6
  * MIT Licensed
7
7
  */
8
- /**
9
- * @namespace Mocha
10
- * @module Mocha
11
- */
12
- /**
13
- * Module dependencies.
14
- */
15
8
 
16
9
  var escapeRe = require('escape-string-regexp');
17
10
  var path = require('path');
18
- var reporters = require('./reporters');
11
+ var builtinReporters = require('./reporters');
12
+ var growl = require('./growl');
19
13
  var utils = require('./utils');
20
-
21
- /**
22
- * Expose `Mocha`.
23
- */
14
+ var mocharc = require('./mocharc.json');
15
+ var errors = require('./errors');
16
+ var Suite = require('./suite');
17
+ var createStatsCollector = require('./stats-collector');
18
+ var createInvalidReporterError = errors.createInvalidReporterError;
19
+ var createInvalidInterfaceError = errors.createInvalidInterfaceError;
20
+ var EVENT_FILE_PRE_REQUIRE = Suite.constants.EVENT_FILE_PRE_REQUIRE;
21
+ var EVENT_FILE_POST_REQUIRE = Suite.constants.EVENT_FILE_POST_REQUIRE;
22
+ var EVENT_FILE_REQUIRE = Suite.constants.EVENT_FILE_REQUIRE;
23
+ var sQuote = utils.sQuote;
24
24
 
25
25
  exports = module.exports = Mocha;
26
26
 
@@ -45,11 +45,10 @@ if (!process.browser) {
45
45
  exports.utils = utils;
46
46
  exports.interfaces = require('./interfaces');
47
47
  /**
48
- *
49
- * @memberof Mocha
50
48
  * @public
49
+ * @memberof Mocha
51
50
  */
52
- exports.reporters = reporters;
51
+ exports.reporters = builtinReporters;
53
52
  exports.Runnable = require('./runnable');
54
53
  exports.Context = require('./context');
55
54
  /**
@@ -57,79 +56,112 @@ exports.Context = require('./context');
57
56
  * @memberof Mocha
58
57
  */
59
58
  exports.Runner = require('./runner');
60
- exports.Suite = require('./suite');
59
+ exports.Suite = Suite;
61
60
  exports.Hook = require('./hook');
62
61
  exports.Test = require('./test');
63
62
 
64
63
  /**
65
- * Return image `name` path.
66
- *
67
- * @api private
68
- * @param {string} name
69
- * @return {string}
70
- */
71
- function image (name) {
72
- return path.join(__dirname, '../images', name + '.png');
73
- }
74
-
75
- /**
76
- * Set up mocha with `options`.
77
- *
78
- * Options:
79
- *
80
- * - `ui` name "bdd", "tdd", "exports" etc
81
- * - `reporter` reporter instance, defaults to `mocha.reporters.spec`
82
- * - `globals` array of accepted globals
83
- * - `timeout` timeout in milliseconds
84
- * - `retries` number of times to retry failed tests
85
- * - `bail` bail on the first test failure
86
- * - `slow` milliseconds to wait before considering a test slow
87
- * - `ignoreLeaks` ignore global leaks
88
- * - `fullTrace` display the full stack-trace on failing
89
- * - `grep` string or regexp to filter tests with
64
+ * Constructs a new Mocha instance with `options`.
90
65
  *
91
66
  * @public
92
67
  * @class Mocha
93
- * @param {Object} options
94
- * @api public
95
- */
96
- function Mocha (options) {
97
- options = options || {};
68
+ * @param {Object} [options] - Settings object.
69
+ * @param {boolean} [options.allowUncaught] - Propagate uncaught errors?
70
+ * @param {boolean} [options.asyncOnly] - Force `done` callback or promise?
71
+ * @param {boolean} [options.bail] - Bail after first test failure?
72
+ * @param {boolean} [options.checkLeaks] - If true, check leaks.
73
+ * @param {boolean} [options.delay] - Delay root suite execution?
74
+ * @param {boolean} [options.enableTimeouts] - Enable timeouts?
75
+ * @param {string} [options.fgrep] - Test filter given string.
76
+ * @param {boolean} [options.forbidOnly] - Tests marked `only` fail the suite?
77
+ * @param {boolean} [options.forbidPending] - Pending tests fail the suite?
78
+ * @param {boolean} [options.fullStackTrace] - Full stacktrace upon failure?
79
+ * @param {string[]} [options.global] - Variables expected in global scope.
80
+ * @param {RegExp|string} [options.grep] - Test filter given regular expression.
81
+ * @param {boolean} [options.growl] - Enable desktop notifications?
82
+ * @param {boolean} [options.hideDiff] - Suppress diffs from failures?
83
+ * @param {boolean} [options.ignoreLeaks] - Ignore global leaks?
84
+ * @param {boolean} [options.invert] - Invert test filter matches?
85
+ * @param {boolean} [options.noHighlighting] - Disable syntax highlighting?
86
+ * @param {string} [options.reporter] - Reporter name.
87
+ * @param {Object} [options.reporterOption] - Reporter settings object.
88
+ * @param {number} [options.retries] - Number of times to retry failed tests.
89
+ * @param {number} [options.slow] - Slow threshold value.
90
+ * @param {number|string} [options.timeout] - Timeout threshold value.
91
+ * @param {string} [options.ui] - Interface name.
92
+ * @param {boolean} [options.color] - Color TTY output from reporter?
93
+ * @param {boolean} [options.useInlineDiffs] - Use inline diffs?
94
+ */
95
+ function Mocha(options) {
96
+ options = utils.assign({}, mocharc, options || {});
98
97
  this.files = [];
99
98
  this.options = options;
100
- if (options.grep) {
101
- this.grep(new RegExp(options.grep));
102
- }
103
- if (options.fgrep) {
104
- this.fgrep(options.fgrep);
99
+ // root suite
100
+ this.suite = new exports.Suite('', new exports.Context(), true);
101
+
102
+ if ('useColors' in options) {
103
+ utils.deprecate(
104
+ 'useColors is DEPRECATED and will be removed from a future version of Mocha. Instead, use the "color" option'
105
+ );
106
+ options.color = 'color' in options ? options.color : options.useColors;
105
107
  }
106
- this.suite = new exports.Suite('', new exports.Context());
107
- this.ui(options.ui);
108
- this.bail(options.bail);
109
- this.reporter(options.reporter, options.reporterOptions);
110
- if (typeof options.timeout !== 'undefined' && options.timeout !== null) {
111
- this.timeout(options.timeout);
108
+
109
+ this.grep(options.grep)
110
+ .fgrep(options.fgrep)
111
+ .ui(options.ui)
112
+ .bail(options.bail)
113
+ .reporter(options.reporter, options.reporterOptions)
114
+ .useColors(options.color)
115
+ .slow(options.slow)
116
+ .useInlineDiffs(options.inlineDiffs)
117
+ .globals(options.globals);
118
+
119
+ if ('enableTimeouts' in options) {
120
+ utils.deprecate(
121
+ 'enableTimeouts is DEPRECATED and will be removed from a future version of Mocha. Instead, use "timeout: false" to disable timeouts.'
122
+ );
112
123
  }
113
- if (typeof options.retries !== 'undefined' && options.retries !== null) {
124
+ this.timeout(
125
+ options.enableTimeouts === false || options.timeout === false
126
+ ? 0
127
+ : options.timeout
128
+ );
129
+
130
+ if ('retries' in options) {
114
131
  this.retries(options.retries);
115
132
  }
116
- this.useColors(options.useColors);
117
- if (options.enableTimeouts !== null) {
118
- this.enableTimeouts(options.enableTimeouts);
119
- }
120
- if (options.slow) {
121
- this.slow(options.slow);
133
+
134
+ if ('diff' in options) {
135
+ this.hideDiff(!options.diff);
122
136
  }
137
+
138
+ [
139
+ 'allowUncaught',
140
+ 'asyncOnly',
141
+ 'checkLeaks',
142
+ 'delay',
143
+ 'forbidOnly',
144
+ 'forbidPending',
145
+ 'fullTrace',
146
+ 'growl',
147
+ 'invert'
148
+ ].forEach(function(opt) {
149
+ if (options[opt]) {
150
+ this[opt]();
151
+ }
152
+ }, this);
123
153
  }
124
154
 
125
155
  /**
126
- * Enable or disable bailing on the first failure.
156
+ * Enables or disables bailing on the first failure.
127
157
  *
128
158
  * @public
129
- * @api public
130
- * @param {boolean} [bail]
159
+ * @see {@link https://mochajs.org/#-b---bail|CLI option}
160
+ * @param {boolean} [bail=true] - Whether to bail on first error.
161
+ * @returns {Mocha} this
162
+ * @chainable
131
163
  */
132
- Mocha.prototype.bail = function (bail) {
164
+ Mocha.prototype.bail = function(bail) {
133
165
  if (!arguments.length) {
134
166
  bail = true;
135
167
  }
@@ -138,62 +170,83 @@ Mocha.prototype.bail = function (bail) {
138
170
  };
139
171
 
140
172
  /**
141
- * Add test `file`.
173
+ * @summary
174
+ * Adds `file` to be loaded for execution.
175
+ *
176
+ * @description
177
+ * Useful for generic setup code that must be included within test suite.
142
178
  *
143
179
  * @public
144
- * @api public
145
- * @param {string} file
180
+ * @see {@link https://mochajs.org/#--file-file|CLI option}
181
+ * @param {string} file - Pathname of file to be loaded.
182
+ * @returns {Mocha} this
183
+ * @chainable
146
184
  */
147
- Mocha.prototype.addFile = function (file) {
185
+ Mocha.prototype.addFile = function(file) {
148
186
  this.files.push(file);
149
187
  return this;
150
188
  };
151
189
 
152
190
  /**
153
- * Set reporter to `reporter`, defaults to "spec".
191
+ * Sets reporter to `reporter`, defaults to "spec".
154
192
  *
155
193
  * @public
156
- * @param {String|Function} reporter name or constructor
157
- * @param {Object} reporterOptions optional options
158
- * @api public
159
- * @param {string|Function} reporter name or constructor
160
- * @param {Object} reporterOptions optional options
194
+ * @see {@link https://mochajs.org/#-r---reporter-name|CLI option}
195
+ * @see {@link https://mochajs.org/#reporters|Reporters}
196
+ * @param {String|Function} reporter - Reporter name or constructor.
197
+ * @param {Object} [reporterOptions] - Options used to configure the reporter.
198
+ * @returns {Mocha} this
199
+ * @chainable
200
+ * @throws {Error} if requested reporter cannot be loaded
201
+ * @example
202
+ *
203
+ * // Use XUnit reporter and direct its output to file
204
+ * mocha.reporter('xunit', { output: '/path/to/testspec.xunit.xml' });
161
205
  */
162
- Mocha.prototype.reporter = function (reporter, reporterOptions) {
206
+ Mocha.prototype.reporter = function(reporter, reporterOptions) {
163
207
  if (typeof reporter === 'function') {
164
208
  this._reporter = reporter;
165
209
  } else {
166
210
  reporter = reporter || 'spec';
167
211
  var _reporter;
168
212
  // Try to load a built-in reporter.
169
- if (reporters[reporter]) {
170
- _reporter = reporters[reporter];
213
+ if (builtinReporters[reporter]) {
214
+ _reporter = builtinReporters[reporter];
171
215
  }
172
216
  // Try to load reporters from process.cwd() and node_modules
173
217
  if (!_reporter) {
174
218
  try {
175
219
  _reporter = require(reporter);
176
220
  } catch (err) {
177
- if (err.message.indexOf('Cannot find module') !== -1) {
221
+ if (
222
+ err.code !== 'MODULE_NOT_FOUND' ||
223
+ err.message.indexOf('Cannot find module') !== -1
224
+ ) {
178
225
  // Try to load reporters from a path (absolute or relative)
179
226
  try {
180
227
  _reporter = require(path.resolve(process.cwd(), reporter));
181
228
  } catch (_err) {
182
- err.message.indexOf('Cannot find module') !== -1 ? console.warn('"' + reporter + '" reporter not found')
183
- : console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack);
229
+ _err.code !== 'MODULE_NOT_FOUND' ||
230
+ _err.message.indexOf('Cannot find module') !== -1
231
+ ? console.warn(sQuote(reporter) + ' reporter not found')
232
+ : console.warn(
233
+ sQuote(reporter) +
234
+ ' reporter blew up with error:\n' +
235
+ err.stack
236
+ );
184
237
  }
185
238
  } else {
186
- console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack);
239
+ console.warn(
240
+ sQuote(reporter) + ' reporter blew up with error:\n' + err.stack
241
+ );
187
242
  }
188
243
  }
189
244
  }
190
- if (!_reporter && reporter === 'teamcity') {
191
- console.warn('The Teamcity reporter was moved to a package named ' +
192
- 'mocha-teamcity-reporter ' +
193
- '(https://npmjs.org/package/mocha-teamcity-reporter).');
194
- }
195
245
  if (!_reporter) {
196
- throw new Error('invalid reporter "' + reporter + '"');
246
+ throw createInvalidReporterError(
247
+ 'invalid reporter ' + sQuote(reporter),
248
+ reporter
249
+ );
197
250
  }
198
251
  this._reporter = _reporter;
199
252
  }
@@ -202,31 +255,39 @@ Mocha.prototype.reporter = function (reporter, reporterOptions) {
202
255
  };
203
256
 
204
257
  /**
205
- * Set test UI `name`, defaults to "bdd".
258
+ * Sets test UI `name`, defaults to "bdd".
259
+ *
206
260
  * @public
207
- * @api public
208
- * @param {string} bdd
209
- */
210
- Mocha.prototype.ui = function (name) {
261
+ * @see {@link https://mochajs.org/#-u---ui-name|CLI option}
262
+ * @see {@link https://mochajs.org/#interfaces|Interface DSLs}
263
+ * @param {string} [name=bdd] - Interface name.
264
+ * @returns {Mocha} this
265
+ * @chainable
266
+ * @throws {Error} if requested interface cannot be loaded
267
+ */
268
+ Mocha.prototype.ui = function(name) {
211
269
  name = name || 'bdd';
212
270
  this._ui = exports.interfaces[name];
213
271
  if (!this._ui) {
214
272
  try {
215
273
  this._ui = require(name);
216
274
  } catch (err) {
217
- throw new Error('invalid interface "' + name + '"');
275
+ throw createInvalidInterfaceError(
276
+ 'invalid interface ' + sQuote(name),
277
+ name
278
+ );
218
279
  }
219
280
  }
220
281
  this._ui = this._ui(this.suite);
221
282
 
222
- this.suite.on('pre-require', function (context) {
283
+ this.suite.on(EVENT_FILE_PRE_REQUIRE, function(context) {
223
284
  exports.afterEach = context.afterEach || context.teardown;
224
285
  exports.after = context.after || context.suiteTeardown;
225
286
  exports.beforeEach = context.beforeEach || context.setup;
226
287
  exports.before = context.before || context.suiteSetup;
227
288
  exports.describe = context.describe || context.suite;
228
289
  exports.it = context.it || context.test;
229
- exports.xit = context.xit || context.test.skip;
290
+ exports.xit = context.xit || (context.test && context.test.skip);
230
291
  exports.setup = context.setup || context.beforeEach;
231
292
  exports.suiteSetup = context.suiteSetup || context.before;
232
293
  exports.suiteTeardown = context.suiteTeardown || context.after;
@@ -240,68 +301,118 @@ Mocha.prototype.ui = function (name) {
240
301
  };
241
302
 
242
303
  /**
243
- * Load registered files.
304
+ * Loads `files` prior to execution.
244
305
  *
245
- * @api private
306
+ * @description
307
+ * The implementation relies on Node's `require` to execute
308
+ * the test interface functions and will be subject to its cache.
309
+ *
310
+ * @private
311
+ * @see {@link Mocha#addFile}
312
+ * @see {@link Mocha#run}
313
+ * @see {@link Mocha#unloadFiles}
314
+ * @param {Function} [fn] - Callback invoked upon completion.
246
315
  */
247
- Mocha.prototype.loadFiles = function (fn) {
316
+ Mocha.prototype.loadFiles = function(fn) {
248
317
  var self = this;
249
318
  var suite = this.suite;
250
- this.files.forEach(function (file) {
319
+ this.files.forEach(function(file) {
251
320
  file = path.resolve(file);
252
- suite.emit('pre-require', global, file, self);
253
- suite.emit('require', require(file), file, self);
254
- suite.emit('post-require', global, file, self);
321
+ suite.emit(EVENT_FILE_PRE_REQUIRE, global, file, self);
322
+ suite.emit(EVENT_FILE_REQUIRE, require(file), file, self);
323
+ suite.emit(EVENT_FILE_POST_REQUIRE, global, file, self);
255
324
  });
256
325
  fn && fn();
257
326
  };
258
327
 
259
328
  /**
260
- * Enable growl support.
329
+ * Removes a previously loaded file from Node's `require` cache.
261
330
  *
262
- * @api private
331
+ * @private
332
+ * @static
333
+ * @see {@link Mocha#unloadFiles}
334
+ * @param {string} file - Pathname of file to be unloaded.
263
335
  */
264
- Mocha.prototype._growl = function (runner, reporter) {
265
- var notify = require('growl');
336
+ Mocha.unloadFile = function(file) {
337
+ delete require.cache[require.resolve(file)];
338
+ };
266
339
 
267
- runner.on('end', function () {
268
- var stats = reporter.stats;
269
- if (stats.failures) {
270
- var msg = stats.failures + ' of ' + runner.total + ' tests failed';
271
- notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
272
- } else {
273
- notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
274
- name: 'mocha',
275
- title: 'Passed',
276
- image: image('ok')
277
- });
278
- }
279
- });
340
+ /**
341
+ * Unloads `files` from Node's `require` cache.
342
+ *
343
+ * @description
344
+ * This allows files to be "freshly" reloaded, providing the ability
345
+ * to reuse a Mocha instance programmatically.
346
+ *
347
+ * <strong>Intended for consumers &mdash; not used internally</strong>
348
+ *
349
+ * @public
350
+ * @see {@link Mocha.unloadFile}
351
+ * @see {@link Mocha#loadFiles}
352
+ * @see {@link Mocha#run}
353
+ * @returns {Mocha} this
354
+ * @chainable
355
+ */
356
+ Mocha.prototype.unloadFiles = function() {
357
+ this.files.forEach(Mocha.unloadFile);
358
+ return this;
280
359
  };
281
360
 
282
361
  /**
283
- * Escape string and add it to grep as a regexp.
362
+ * Sets `grep` filter after escaping RegExp special characters.
284
363
  *
285
364
  * @public
286
- * @api public
287
- * @param str
288
- * @returns {Mocha}
365
+ * @see {@link Mocha#grep}
366
+ * @param {string} str - Value to be converted to a regexp.
367
+ * @returns {Mocha} this
368
+ * @chainable
369
+ * @example
370
+ *
371
+ * // Select tests whose full title begins with `"foo"` followed by a period
372
+ * mocha.fgrep('foo.');
289
373
  */
290
- Mocha.prototype.fgrep = function (str) {
374
+ Mocha.prototype.fgrep = function(str) {
375
+ if (!str) {
376
+ return this;
377
+ }
291
378
  return this.grep(new RegExp(escapeRe(str)));
292
379
  };
293
380
 
294
381
  /**
295
- * Add regexp to grep, if `re` is a string it is escaped.
382
+ * @summary
383
+ * Sets `grep` filter used to select specific tests for execution.
384
+ *
385
+ * @description
386
+ * If `re` is a regexp-like string, it will be converted to regexp.
387
+ * The regexp is tested against the full title of each test (i.e., the
388
+ * name of the test preceded by titles of each its ancestral suites).
389
+ * As such, using an <em>exact-match</em> fixed pattern against the
390
+ * test name itself will not yield any matches.
391
+ * <br>
392
+ * <strong>Previous filter value will be overwritten on each call!</strong>
296
393
  *
297
394
  * @public
298
- * @param {RegExp|String} re
299
- * @return {Mocha}
300
- * @api public
301
- * @param {RegExp|string} re
302
- * @return {Mocha}
395
+ * @see {@link https://mochajs.org/#-g---grep-pattern|CLI option}
396
+ * @see {@link Mocha#fgrep}
397
+ * @see {@link Mocha#invert}
398
+ * @param {RegExp|String} re - Regular expression used to select tests.
399
+ * @return {Mocha} this
400
+ * @chainable
401
+ * @example
402
+ *
403
+ * // Select tests whose full title contains `"match"`, ignoring case
404
+ * mocha.grep(/match/i);
405
+ * @example
406
+ *
407
+ * // Same as above but with regexp-like string argument
408
+ * mocha.grep('/match/i');
409
+ * @example
410
+ *
411
+ * // ## Anti-example
412
+ * // Given embedded test `it('only-this-test')`...
413
+ * mocha.grep('/^only-this-test$/'); // NO! Use `.only()` to do this!
303
414
  */
304
- Mocha.prototype.grep = function (re) {
415
+ Mocha.prototype.grep = function(re) {
305
416
  if (utils.isString(re)) {
306
417
  // extract args if it's regex-like, i.e: [string, pattern, flag]
307
418
  var arg = re.match(/^\/(.*)\/(g|i|)$|.*/);
@@ -311,95 +422,142 @@ Mocha.prototype.grep = function (re) {
311
422
  }
312
423
  return this;
313
424
  };
425
+
314
426
  /**
315
- * Invert `.grep()` matches.
427
+ * Inverts `grep` matches.
316
428
  *
317
429
  * @public
318
- * @return {Mocha}
319
- * @api public
430
+ * @see {@link Mocha#grep}
431
+ * @return {Mocha} this
432
+ * @chainable
433
+ * @example
434
+ *
435
+ * // Select tests whose full title does *not* contain `"match"`, ignoring case
436
+ * mocha.grep(/match/i).invert();
320
437
  */
321
- Mocha.prototype.invert = function () {
438
+ Mocha.prototype.invert = function() {
322
439
  this.options.invert = true;
323
440
  return this;
324
441
  };
325
442
 
326
443
  /**
327
- * Ignore global leaks.
444
+ * Enables or disables ignoring global leaks.
328
445
  *
329
446
  * @public
330
- * @param {Boolean} ignore
331
- * @return {Mocha}
332
- * @api public
333
- * @param {boolean} ignore
334
- * @return {Mocha}
335
- */
336
- Mocha.prototype.ignoreLeaks = function (ignore) {
337
- this.options.ignoreLeaks = Boolean(ignore);
447
+ * @see {@link Mocha#checkLeaks}
448
+ * @param {boolean} ignoreLeaks - Whether to ignore global leaks.
449
+ * @return {Mocha} this
450
+ * @chainable
451
+ * @example
452
+ *
453
+ * // Ignore global leaks
454
+ * mocha.ignoreLeaks(true);
455
+ */
456
+ Mocha.prototype.ignoreLeaks = function(ignoreLeaks) {
457
+ this.options.ignoreLeaks = Boolean(ignoreLeaks);
338
458
  return this;
339
459
  };
340
460
 
341
461
  /**
342
- * Enable global leak checking.
462
+ * Enables checking for global variables leaked while running tests.
343
463
  *
344
- * @return {Mocha}
345
- * @api public
346
464
  * @public
465
+ * @see {@link https://mochajs.org/#--check-leaks|CLI option}
466
+ * @see {@link Mocha#ignoreLeaks}
467
+ * @return {Mocha} this
468
+ * @chainable
347
469
  */
348
- Mocha.prototype.checkLeaks = function () {
470
+ Mocha.prototype.checkLeaks = function() {
349
471
  this.options.ignoreLeaks = false;
350
472
  return this;
351
473
  };
352
474
 
353
475
  /**
354
- * Display long stack-trace on failing
476
+ * Displays full stack trace upon test failure.
355
477
  *
356
- * @return {Mocha}
357
- * @api public
358
478
  * @public
479
+ * @return {Mocha} this
480
+ * @chainable
359
481
  */
360
- Mocha.prototype.fullTrace = function () {
482
+ Mocha.prototype.fullTrace = function() {
361
483
  this.options.fullStackTrace = true;
362
484
  return this;
363
485
  };
364
486
 
365
487
  /**
366
- * Enable growl support.
488
+ * Enables desktop notification support if prerequisite software installed.
367
489
  *
368
- * @return {Mocha}
369
- * @api public
370
490
  * @public
371
- */
372
- Mocha.prototype.growl = function () {
373
- this.options.growl = true;
491
+ * @see {@link Mocha#isGrowlCapable}
492
+ * @see {@link Mocha#_growl}
493
+ * @return {Mocha} this
494
+ * @chainable
495
+ */
496
+ Mocha.prototype.growl = function() {
497
+ this.options.growl = this.isGrowlCapable();
498
+ if (!this.options.growl) {
499
+ var detail = process.browser
500
+ ? 'notification support not available in this browser...'
501
+ : 'notification support prerequisites not installed...';
502
+ console.error(detail + ' cannot enable!');
503
+ }
374
504
  return this;
375
505
  };
376
506
 
377
507
  /**
378
- * Ignore `globals` array or string.
508
+ * @summary
509
+ * Determines if Growl support seems likely.
510
+ *
511
+ * @description
512
+ * <strong>Not available when run in browser.</strong>
513
+ *
514
+ * @private
515
+ * @see {@link Growl#isCapable}
516
+ * @see {@link Mocha#growl}
517
+ * @return {boolean} whether Growl support can be expected
518
+ */
519
+ Mocha.prototype.isGrowlCapable = growl.isCapable;
520
+
521
+ /**
522
+ * Implements desktop notifications using a pseudo-reporter.
523
+ *
524
+ * @private
525
+ * @see {@link Mocha#growl}
526
+ * @see {@link Growl#notify}
527
+ * @param {Runner} runner - Runner instance.
528
+ */
529
+ Mocha.prototype._growl = growl.notify;
530
+
531
+ /**
532
+ * Specifies whitelist of variable names to be expected in global scope.
379
533
  *
380
- * @param {Array|String} globals
381
- * @return {Mocha}
382
- * @api public
383
534
  * @public
384
- * @param {Array|string} globals
385
- * @return {Mocha}
535
+ * @see {@link https://mochajs.org/#--globals-names|CLI option}
536
+ * @see {@link Mocha#checkLeaks}
537
+ * @param {String[]|String} globals - Accepted global variable name(s).
538
+ * @return {Mocha} this
539
+ * @chainable
540
+ * @example
541
+ *
542
+ * // Specify variables to be expected in global scope
543
+ * mocha.globals(['jQuery', 'MyLib']);
386
544
  */
387
- Mocha.prototype.globals = function (globals) {
388
- this.options.globals = (this.options.globals || []).concat(globals);
545
+ Mocha.prototype.globals = function(globals) {
546
+ this.options.globals = (this.options.globals || [])
547
+ .concat(globals)
548
+ .filter(Boolean);
389
549
  return this;
390
550
  };
391
551
 
392
552
  /**
393
- * Emit color output.
553
+ * Enables or disables TTY color output by screen-oriented reporters.
394
554
  *
395
- * @param {Boolean} colors
396
- * @return {Mocha}
397
- * @api public
398
555
  * @public
399
- * @param {boolean} colors
400
- * @return {Mocha}
556
+ * @param {boolean} colors - Whether to enable color output.
557
+ * @return {Mocha} this
558
+ * @chainable
401
559
  */
402
- Mocha.prototype.useColors = function (colors) {
560
+ Mocha.prototype.useColors = function(colors) {
403
561
  if (colors !== undefined) {
404
562
  this.options.useColors = colors;
405
563
  }
@@ -407,172 +565,233 @@ Mocha.prototype.useColors = function (colors) {
407
565
  };
408
566
 
409
567
  /**
410
- * Use inline diffs rather than +/-.
568
+ * Determines if reporter should use inline diffs (rather than +/-)
569
+ * in test failure output.
411
570
  *
412
- * @param {Boolean} inlineDiffs
413
- * @return {Mocha}
414
- * @api public
415
571
  * @public
416
- * @param {boolean} inlineDiffs
417
- * @return {Mocha}
572
+ * @param {boolean} inlineDiffs - Whether to use inline diffs.
573
+ * @return {Mocha} this
574
+ * @chainable
418
575
  */
419
- Mocha.prototype.useInlineDiffs = function (inlineDiffs) {
576
+ Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
420
577
  this.options.useInlineDiffs = inlineDiffs !== undefined && inlineDiffs;
421
578
  return this;
422
579
  };
423
580
 
424
581
  /**
425
- * Do not show diffs at all.
582
+ * Determines if reporter should include diffs in test failure output.
426
583
  *
427
- * @param {Boolean} hideDiff
428
- * @return {Mocha}
429
- * @api public
430
584
  * @public
431
- * @param {boolean} hideDiff
432
- * @return {Mocha}
585
+ * @param {boolean} hideDiff - Whether to hide diffs.
586
+ * @return {Mocha} this
587
+ * @chainable
433
588
  */
434
- Mocha.prototype.hideDiff = function (hideDiff) {
589
+ Mocha.prototype.hideDiff = function(hideDiff) {
435
590
  this.options.hideDiff = hideDiff !== undefined && hideDiff;
436
591
  return this;
437
592
  };
438
593
 
439
594
  /**
440
- * Set the timeout in milliseconds.
595
+ * @summary
596
+ * Sets timeout threshold value.
597
+ *
598
+ * @description
599
+ * A string argument can use shorthand (such as "2s") and will be converted.
600
+ * If the value is `0`, timeouts will be disabled.
441
601
  *
442
- * @param {Number} timeout
443
- * @return {Mocha}
444
- * @api public
445
602
  * @public
446
- * @param {number} timeout
447
- * @return {Mocha}
603
+ * @see {@link https://mochajs.org/#-t---timeout-ms|CLI option}
604
+ * @see {@link https://mochajs.org/#--no-timeouts|CLI option}
605
+ * @see {@link https://mochajs.org/#timeouts|Timeouts}
606
+ * @see {@link Mocha#enableTimeouts}
607
+ * @param {number|string} msecs - Timeout threshold value.
608
+ * @return {Mocha} this
609
+ * @chainable
610
+ * @example
611
+ *
612
+ * // Sets timeout to one second
613
+ * mocha.timeout(1000);
614
+ * @example
615
+ *
616
+ * // Same as above but using string argument
617
+ * mocha.timeout('1s');
448
618
  */
449
- Mocha.prototype.timeout = function (timeout) {
450
- this.suite.timeout(timeout);
619
+ Mocha.prototype.timeout = function(msecs) {
620
+ this.suite.timeout(msecs);
451
621
  return this;
452
622
  };
453
623
 
454
624
  /**
455
- * Set the number of times to retry failed tests.
625
+ * Sets the number of times to retry failed tests.
456
626
  *
457
- * @param {Number} retry times
458
- * @return {Mocha}
459
- * @api public
460
627
  * @public
628
+ * @see {@link https://mochajs.org/#retry-tests|Retry Tests}
629
+ * @param {number} retry - Number of times to retry failed tests.
630
+ * @return {Mocha} this
631
+ * @chainable
632
+ * @example
633
+ *
634
+ * // Allow any failed test to retry one more time
635
+ * mocha.retries(1);
461
636
  */
462
- Mocha.prototype.retries = function (n) {
637
+ Mocha.prototype.retries = function(n) {
463
638
  this.suite.retries(n);
464
639
  return this;
465
640
  };
466
641
 
467
642
  /**
468
- * Set slowness threshold in milliseconds.
643
+ * Sets slowness threshold value.
469
644
  *
470
- * @param {Number} slow
471
- * @return {Mocha}
472
- * @api public
473
645
  * @public
474
- * @param {number} slow
475
- * @return {Mocha}
646
+ * @see {@link https://mochajs.org/#-s---slow-ms|CLI option}
647
+ * @param {number} msecs - Slowness threshold value.
648
+ * @return {Mocha} this
649
+ * @chainable
650
+ * @example
651
+ *
652
+ * // Sets "slow" threshold to half a second
653
+ * mocha.slow(500);
654
+ * @example
655
+ *
656
+ * // Same as above but using string argument
657
+ * mocha.slow('0.5s');
476
658
  */
477
- Mocha.prototype.slow = function (slow) {
478
- this.suite.slow(slow);
659
+ Mocha.prototype.slow = function(msecs) {
660
+ this.suite.slow(msecs);
479
661
  return this;
480
662
  };
481
663
 
482
664
  /**
483
- * Enable timeouts.
665
+ * Enables or disables timeouts.
484
666
  *
485
- * @param {Boolean} enabled
486
- * @return {Mocha}
487
- * @api public
488
667
  * @public
489
- * @param {boolean} enabled
490
- * @return {Mocha}
491
- */
492
- Mocha.prototype.enableTimeouts = function (enabled) {
493
- this.suite.enableTimeouts(arguments.length && enabled !== undefined ? enabled : true);
668
+ * @see {@link https://mochajs.org/#-t---timeout-ms|CLI option}
669
+ * @see {@link https://mochajs.org/#--no-timeouts|CLI option}
670
+ * @param {boolean} enableTimeouts - Whether to enable timeouts.
671
+ * @return {Mocha} this
672
+ * @chainable
673
+ */
674
+ Mocha.prototype.enableTimeouts = function(enableTimeouts) {
675
+ this.suite.enableTimeouts(
676
+ arguments.length && enableTimeouts !== undefined ? enableTimeouts : true
677
+ );
494
678
  return this;
495
679
  };
496
680
 
497
681
  /**
498
- * Makes all tests async (accepting a callback)
682
+ * Forces all tests to either accept a `done` callback or return a promise.
499
683
  *
500
- * @return {Mocha}
501
- * @api public
502
684
  * @public
685
+ * @return {Mocha} this
686
+ * @chainable
503
687
  */
504
- Mocha.prototype.asyncOnly = function () {
688
+ Mocha.prototype.asyncOnly = function() {
505
689
  this.options.asyncOnly = true;
506
690
  return this;
507
691
  };
508
692
 
509
693
  /**
510
- * Disable syntax highlighting (in browser).
694
+ * Disables syntax highlighting (in browser).
511
695
  *
512
- * @api public
513
696
  * @public
697
+ * @return {Mocha} this
698
+ * @chainable
514
699
  */
515
- Mocha.prototype.noHighlighting = function () {
700
+ Mocha.prototype.noHighlighting = function() {
516
701
  this.options.noHighlighting = true;
517
702
  return this;
518
703
  };
519
704
 
520
705
  /**
521
- * Enable uncaught errors to propagate (in browser).
706
+ * Enables uncaught errors to propagate (in browser).
522
707
  *
523
- * @return {Mocha}
524
- * @api public
525
708
  * @public
709
+ * @return {Mocha} this
710
+ * @chainable
526
711
  */
527
- Mocha.prototype.allowUncaught = function () {
712
+ Mocha.prototype.allowUncaught = function() {
528
713
  this.options.allowUncaught = true;
529
714
  return this;
530
715
  };
531
716
 
532
717
  /**
533
- * Delay root suite execution.
534
- * @returns {Mocha}
718
+ * @summary
719
+ * Delays root suite execution.
720
+ *
721
+ * @description
722
+ * Used to perform asynch operations before any suites are run.
723
+ *
724
+ * @public
725
+ * @see {@link https://mochajs.org/#delayed-root-suite|delayed root suite}
726
+ * @returns {Mocha} this
727
+ * @chainable
535
728
  */
536
- Mocha.prototype.delay = function delay () {
729
+ Mocha.prototype.delay = function delay() {
537
730
  this.options.delay = true;
538
731
  return this;
539
732
  };
540
733
 
541
734
  /**
542
- * Tests marked only fail the suite
543
- * @returns {Mocha}
735
+ * Causes tests marked `only` to fail the suite.
736
+ *
737
+ * @public
738
+ * @returns {Mocha} this
739
+ * @chainable
544
740
  */
545
- Mocha.prototype.forbidOnly = function () {
741
+ Mocha.prototype.forbidOnly = function() {
546
742
  this.options.forbidOnly = true;
547
743
  return this;
548
744
  };
549
745
 
550
746
  /**
551
- * Pending tests and tests marked skip fail the suite
552
- * @returns {Mocha}
747
+ * Causes pending tests and tests marked `skip` to fail the suite.
748
+ *
749
+ * @public
750
+ * @returns {Mocha} this
751
+ * @chainable
553
752
  */
554
- Mocha.prototype.forbidPending = function () {
753
+ Mocha.prototype.forbidPending = function() {
555
754
  this.options.forbidPending = true;
556
755
  return this;
557
756
  };
558
757
 
559
758
  /**
560
- * Run tests and invoke `fn()` when complete.
759
+ * Mocha version as specified by "package.json".
760
+ *
761
+ * @name Mocha#version
762
+ * @type string
763
+ * @readonly
764
+ */
765
+ Object.defineProperty(Mocha.prototype, 'version', {
766
+ value: require('../package.json').version,
767
+ configurable: false,
768
+ enumerable: true,
769
+ writable: false
770
+ });
771
+
772
+ /**
773
+ * Callback to be invoked when test execution is complete.
774
+ *
775
+ * @callback DoneCB
776
+ * @param {number} failures - Number of failures that occurred.
777
+ */
778
+
779
+ /**
780
+ * Runs root suite and invokes `fn()` when complete.
561
781
  *
562
- * Note that `loadFiles` relies on Node's `require` to execute
563
- * the test interface functions and will be subject to the
564
- * cache - if the files are already in the `require` cache,
565
- * they will effectively be skipped. Therefore, to run tests
566
- * multiple times or to run tests in files that are already
567
- * in the `require` cache, make sure to clear them from the
568
- * cache first in whichever manner best suits your needs.
782
+ * @description
783
+ * To run tests multiple times (or to run tests in files that are
784
+ * already in the `require` cache), make sure to clear them from
785
+ * the cache first!
569
786
  *
570
- * @api public
571
787
  * @public
572
- * @param {Function} fn
573
- * @return {Runner}
788
+ * @see {@link Mocha#loadFiles}
789
+ * @see {@link Mocha#unloadFiles}
790
+ * @see {@link Runner#run}
791
+ * @param {DoneCB} [fn] - Callback invoked when test execution completed.
792
+ * @return {Runner} runner instance
574
793
  */
575
- Mocha.prototype.run = function (fn) {
794
+ Mocha.prototype.run = function(fn) {
576
795
  if (this.files.length) {
577
796
  this.loadFiles();
578
797
  }
@@ -580,6 +799,7 @@ Mocha.prototype.run = function (fn) {
580
799
  var options = this.options;
581
800
  options.files = this.files;
582
801
  var runner = new exports.Runner(suite, options.delay);
802
+ createStatsCollector(runner);
583
803
  var reporter = new this._reporter(runner, options);
584
804
  runner.ignoreLeaks = options.ignoreLeaks !== false;
585
805
  runner.fullStackTrace = options.fullStackTrace;
@@ -594,7 +814,7 @@ Mocha.prototype.run = function (fn) {
594
814
  runner.globals(options.globals);
595
815
  }
596
816
  if (options.growl) {
597
- this._growl(runner, reporter);
817
+ this._growl(runner);
598
818
  }
599
819
  if (options.useColors !== undefined) {
600
820
  exports.reporters.Base.useColors = options.useColors;
@@ -602,11 +822,12 @@ Mocha.prototype.run = function (fn) {
602
822
  exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
603
823
  exports.reporters.Base.hideDiff = options.hideDiff;
604
824
 
605
- function done (failures) {
825
+ function done(failures) {
826
+ fn = fn || utils.noop;
606
827
  if (reporter.done) {
607
828
  reporter.done(failures, fn);
608
829
  } else {
609
- fn && fn(failures);
830
+ fn(failures);
610
831
  }
611
832
  }
612
833