mocha 5.1.0 → 6.0.0-1

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