mocha 5.0.3 → 5.1.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,89 @@
1
+ # 5.1.1 / 2018-04-18
2
+
3
+ ## :bug: Fixes
4
+
5
+ - [#3325]: Revert change which broke `--watch` ([@boneskull])
6
+
7
+ [#3325]: https://github.com/mochajs/mocha/issues/3325
8
+
9
+ # 5.1.0 / 2018-04-12
10
+
11
+ ## :tada: Enhancements
12
+
13
+ - [#3210]: Add `--exclude` option ([@metalex9])
14
+
15
+ ## :bug: Fixes
16
+
17
+ - [#3318]: Fix failures in circular objects in JSON reporter ([@jeversmann], [@boneskull])
18
+
19
+ ## :book: Documentation
20
+
21
+ - [#3323]: Publish actual [API documentation](https://mochajs.org/api/)! ([@dfberry], [@Munter])
22
+ - [#3299]: Improve docs around exclusive tests ([@nicgirault])
23
+
24
+ ## :nut_and_bolt: Other
25
+
26
+ - [#3302], [#3308], [#3310], [#3315], [#3316]: Build matrix improvements ([more info](https://boneskull.com/mocha-and-travis-ci-build-stages/)) ([@outsideris], [@boneskull])
27
+ - [#3272]: Refactor reporter tests ([@jMuzsik])
28
+
29
+ [#3210]: https://github.com/mochajs/mocha/pull/3210
30
+ [#3318]: https://github.com/mochajs/mocha/pull/3318
31
+ [#3323]: https://github.com/mochajs/mocha/pull/3323
32
+ [#3299]: https://github.com/mochajs/mocha/pull/3299
33
+ [#3302]: https://github.com/mochajs/mocha/pull/3302
34
+ [#3308]: https://github.com/mochajs/mocha/pull/3308
35
+ [#3310]: https://github.com/mochajs/mocha/pull/3310
36
+ [#3315]: https://github.com/mochajs/mocha/pull/3315
37
+ [#3316]: https://github.com/mochajs/mocha/pull/3316
38
+ [#3272]: https://github.com/mochajs/mocha/pull/3272
39
+ [@metalex9]: https://github.com/metalex9
40
+ [@jeversmann]: https://github.com/jeversmann
41
+ [@dfberry]: https://github.com/dfberry
42
+ [@nicgirault]: https://github.com/nicgirault
43
+ [@jMuzsik]: https://github.com/jMuzsik
44
+
45
+ # 5.0.5 / 2018-03-22
46
+
47
+ Welcome [@outsideris] to the team!
48
+
49
+ ## :bug: Fixes
50
+
51
+ - [#3096]: Fix `--bail` failing to bail within hooks ([@outsideris])
52
+ - [#3184]: Don't skip too many suites (using `describe.skip()`) ([@outsideris])
53
+
54
+ ## :book: Documentation
55
+
56
+ - [#3133]: Improve docs regarding "pending" behavior ([@ematicipo])
57
+ - [#3276], [#3274]: Fix broken stuff in `CHANGELOG.md` ([@tagoro9], [@honzajavorek])
58
+
59
+ ## :nut_and_bolt: Other
60
+
61
+ - [#3208]: Improve test coverage for AMD users ([@outsideris])
62
+ - [#3267]: Remove vestiges of PhantomJS from CI ([@anishkny])
63
+ - [#2952]: Fix a debug message ([@boneskull])
64
+
65
+ [#3096]: https://github.com/mochajs/mocha/issues/3096
66
+ [#3184]: https://github.com/mochajs/mocha/issues/3184
67
+ [#3133]: https://github.com/mochajs/mocha/issues/3133
68
+ [#3276]: https://github.com/mochajs/mocha/pull/3276
69
+ [#3274]: https://github.com/mochajs/mocha/pull/3274
70
+ [#3208]: https://github.com/mochajs/mocha/issues/3208
71
+ [#2952]: https://github.com/mochajs/mocha/issues/2952
72
+ [#3267]: https://github.com/mochajs/mocha/pull/3267
73
+
74
+ [@ematicipo]: https://github.com/ematicipo
75
+ [@tagoro9]: https://github.com/tagoro9
76
+ [@honzajavorek]: https://github.com/honajavorek
77
+ [@anishkny]: https://github.com/anishkny
78
+
79
+ # 5.0.4 / 2018-03-07
80
+
81
+ ## :bug: Fixes
82
+
83
+ - [#3265]: Fixes regression in "watch" functionality introduced in v5.0.2 ([@outsideris])
84
+
85
+ [#3265]: https://github.com/mochajs/mocha/issues/3265
86
+
1
87
  # 5.0.3 / 2018-03-06
2
88
 
3
89
  This patch features a fix to address a potential "low severity" [ReDoS vulnerability](https://snyk.io/vuln/npm:diff:20180305) in the [diff](https://npm.im/diff) package (a dependency of Mocha).
@@ -44,7 +130,7 @@ This release fixes a class of tests which report as *false positives*. **Certai
44
130
  **Maintainers of external reporters**: *If* a test of this class is encountered, the `Runner` instance will emit the `end` event *twice*; you *may* need to change your reporter to use `runner.once('end')` intead of `runner.on('end')`.
45
131
  - [#3093]: Fix stack trace reformatting problem ([@outsideris])
46
132
 
47
- ## :nut_and_bolt Other
133
+ ## :nut_and_bolt: Other
48
134
 
49
135
  - [#3248]: Update `browser-stdout` to v1.3.1 ([@honzajavorek])
50
136
 
@@ -79,10 +165,10 @@ Special thanks to [Wallaby.js](https://wallabyjs.com) for their continued suppor
79
165
  [#3119]: https://github.com/mochajs/mocha/issues/3119
80
166
  [#3132]: https://github.com/mochajs/mocha/issues/3132
81
167
  [#3098]: https://github.com/mochajs/mocha/issues/3098
82
- [#3212]: https://github.com/mochajs/mocha/pulls/3212
83
- [#3205]: https://github.com/mochajs/mocha/pulls/3205
84
- [#3224]: https://github.com/mochajs/mocha/pulls/3224
85
- [#3230]: https://github.com/mochajs/mocha/pulls/3230
168
+ [#3212]: https://github.com/mochajs/mocha/pull/3212
169
+ [#3205]: https://github.com/mochajs/mocha/pull/3205
170
+ [#3224]: https://github.com/mochajs/mocha/pull/3224
171
+ [#3230]: https://github.com/mochajs/mocha/pull/3230
86
172
  [@silviom]: https://github.com/silviom
87
173
  [@outsideris]: https://github.com/outsideris
88
174
  [@ArtemGovorov]: https://github.com/ArtemGovorov
@@ -342,9 +428,9 @@ For more info, please [read this article](https://boneskull.com/mocha-v4-nears-r
342
428
  - Various CI-and-test-related fixes and improvements ([@boneskull], [@dasilvacontin], [@PopradiArpad], [@Munter], [@ScottFreeCode])
343
429
  - "Officially" support Node.js 8 ([@elergy])
344
430
 
345
- [#2860]: https://github.com/mochajs/mocha/pulls/2860
346
- [#2696]: https://github.com/mochajs/mocha/pulls/2696
347
- [#2813]: https://github.com/mochajs/mocha/pulls/2813
431
+ [#2860]: https://github.com/mochajs/mocha/pull/2860
432
+ [#2696]: https://github.com/mochajs/mocha/pull/2696
433
+ [#2813]: https://github.com/mochajs/mocha/pull/2813
348
434
  [@charlierudolph]: https://github.com/charlierudolph
349
435
  [@PopradiArpad]: https://github.com/PopradiArpad
350
436
  [@kungapal]: https://github.com/kungapal
@@ -366,7 +452,7 @@ For more info, please [read this article](https://boneskull.com/mocha-v4-nears-r
366
452
  [@makepanic]: https://github.com/makepanic
367
453
  [@Munter]: https://github.com/Munter
368
454
 
369
- [#2778]: https://github.com/mochajs/mocha/pulls/2778
455
+ [#2778]: https://github.com/mochajs/mocha/pull/2778
370
456
  [#2802]: https://github.com/mochajs/mocha/issues/2802
371
457
  [#2820]: https://github.com/mochajs/mocha/pull/2820
372
458
 
package/bin/_mocha CHANGED
@@ -10,6 +10,7 @@
10
10
  const program = require('commander');
11
11
  const path = require('path');
12
12
  const fs = require('fs');
13
+ const minimatch = require('minimatch');
13
14
  const resolve = path.resolve;
14
15
  const exists = fs.existsSync;
15
16
  const Mocha = require('../');
@@ -205,7 +206,8 @@ program
205
206
  .option('--allow-uncaught', 'enable uncaught errors to propagate')
206
207
  .option('--forbid-only', 'causes test marked with only to fail the suite')
207
208
  .option('--forbid-pending', 'causes pending tests and test marked with skip to fail the suite')
208
- .option('--file <file>', 'include a file to be ran during the suite', collect, []);
209
+ .option('--file <file>', 'include a file to be ran during the suite', collect, [])
210
+ .option('--exclude <file>', 'a file or glob pattern to ignore', collect, []);
209
211
 
210
212
  program._name = 'mocha';
211
213
 
@@ -494,6 +496,13 @@ args.forEach(arg => {
494
496
  throw err;
495
497
  }
496
498
 
499
+ if (typeof newFiles !== 'undefined') {
500
+ if (typeof newFiles === 'string') {
501
+ newFiles = [newFiles];
502
+ }
503
+ newFiles = newFiles.filter(fileName => program.exclude.every(pattern => !minimatch(fileName, pattern)));
504
+ }
505
+
497
506
  files = files.concat(newFiles);
498
507
  });
499
508
 
package/lib/context.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module Context
4
+ */
3
5
  /**
4
6
  * Expose `Context`.
5
7
  */
@@ -18,7 +20,7 @@ function Context () {}
18
20
  *
19
21
  * @api private
20
22
  * @param {Runnable} runnable
21
- * @return {Context}
23
+ * @return {Context} context
22
24
  */
23
25
  Context.prototype.runnable = function (runnable) {
24
26
  if (!arguments.length) {
package/lib/hook.js CHANGED
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module Hook
4
+ *
5
+ */
3
6
  /**
4
7
  * Module dependencies.
5
8
  */
@@ -14,8 +17,12 @@ var inherits = require('./utils').inherits;
14
17
  module.exports = Hook;
15
18
 
16
19
  /**
17
- * Initialize a new `Hook` with the given `title` and callback `fn`.
20
+ * Initialize a new `Hook` with the given `title` and callback `fn`. Derived from
21
+ * `Runnable`.
18
22
  *
23
+ * @memberof Mocha
24
+ * @public
25
+ * @class
19
26
  * @param {String} title
20
27
  * @param {Function} fn
21
28
  * @api private
@@ -33,6 +40,8 @@ inherits(Hook, Runnable);
33
40
  /**
34
41
  * Get or set the test `err`.
35
42
  *
43
+ * @memberof Mocha.Hook
44
+ * @public
36
45
  * @param {Error} err
37
46
  * @return {Error}
38
47
  * @api public
@@ -113,6 +113,8 @@ module.exports = function (suites, context, mocha) {
113
113
  suites.shift();
114
114
  } else if (typeof opts.fn === 'undefined' && !suite.pending) {
115
115
  throw new Error('Suite "' + suite.fullTitle() + '" was defined but no callback was supplied. Supply a callback or explicitly skip the suite.');
116
+ } else if (!opts.fn && suite.pending) {
117
+ suites.shift();
116
118
  }
117
119
 
118
120
  return suite;
package/lib/mocha.js CHANGED
@@ -5,7 +5,10 @@
5
5
  * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
6
6
  * MIT Licensed
7
7
  */
8
-
8
+ /**
9
+ * @namespace Mocha
10
+ * @module Mocha
11
+ */
9
12
  /**
10
13
  * Module dependencies.
11
14
  */
@@ -34,11 +37,25 @@ if (!process.browser) {
34
37
  * Expose internals.
35
38
  */
36
39
 
40
+ /**
41
+ * @public
42
+ * @class utils
43
+ * @memberof Mocha
44
+ */
37
45
  exports.utils = utils;
38
46
  exports.interfaces = require('./interfaces');
47
+ /**
48
+ *
49
+ * @memberof Mocha
50
+ * @public
51
+ */
39
52
  exports.reporters = reporters;
40
53
  exports.Runnable = require('./runnable');
41
54
  exports.Context = require('./context');
55
+ /**
56
+ *
57
+ * @memberof Mocha
58
+ */
42
59
  exports.Runner = require('./runner');
43
60
  exports.Suite = require('./suite');
44
61
  exports.Hook = require('./hook');
@@ -71,6 +88,8 @@ function image (name) {
71
88
  * - `fullTrace` display the full stack-trace on failing
72
89
  * - `grep` string or regexp to filter tests with
73
90
  *
91
+ * @public
92
+ * @class Mocha
74
93
  * @param {Object} options
75
94
  * @api public
76
95
  */
@@ -106,6 +125,7 @@ function Mocha (options) {
106
125
  /**
107
126
  * Enable or disable bailing on the first failure.
108
127
  *
128
+ * @public
109
129
  * @api public
110
130
  * @param {boolean} [bail]
111
131
  */
@@ -120,6 +140,7 @@ Mocha.prototype.bail = function (bail) {
120
140
  /**
121
141
  * Add test `file`.
122
142
  *
143
+ * @public
123
144
  * @api public
124
145
  * @param {string} file
125
146
  */
@@ -131,6 +152,7 @@ Mocha.prototype.addFile = function (file) {
131
152
  /**
132
153
  * Set reporter to `reporter`, defaults to "spec".
133
154
  *
155
+ * @public
134
156
  * @param {String|Function} reporter name or constructor
135
157
  * @param {Object} reporterOptions optional options
136
158
  * @api public
@@ -181,7 +203,7 @@ Mocha.prototype.reporter = function (reporter, reporterOptions) {
181
203
 
182
204
  /**
183
205
  * Set test UI `name`, defaults to "bdd".
184
- *
206
+ * @public
185
207
  * @api public
186
208
  * @param {string} bdd
187
209
  */
@@ -260,6 +282,7 @@ Mocha.prototype._growl = function (runner, reporter) {
260
282
  /**
261
283
  * Escape string and add it to grep as a regexp.
262
284
  *
285
+ * @public
263
286
  * @api public
264
287
  * @param str
265
288
  * @returns {Mocha}
@@ -271,6 +294,7 @@ Mocha.prototype.fgrep = function (str) {
271
294
  /**
272
295
  * Add regexp to grep, if `re` is a string it is escaped.
273
296
  *
297
+ * @public
274
298
  * @param {RegExp|String} re
275
299
  * @return {Mocha}
276
300
  * @api public
@@ -290,6 +314,7 @@ Mocha.prototype.grep = function (re) {
290
314
  /**
291
315
  * Invert `.grep()` matches.
292
316
  *
317
+ * @public
293
318
  * @return {Mocha}
294
319
  * @api public
295
320
  */
@@ -301,6 +326,7 @@ Mocha.prototype.invert = function () {
301
326
  /**
302
327
  * Ignore global leaks.
303
328
  *
329
+ * @public
304
330
  * @param {Boolean} ignore
305
331
  * @return {Mocha}
306
332
  * @api public
@@ -317,6 +343,7 @@ Mocha.prototype.ignoreLeaks = function (ignore) {
317
343
  *
318
344
  * @return {Mocha}
319
345
  * @api public
346
+ * @public
320
347
  */
321
348
  Mocha.prototype.checkLeaks = function () {
322
349
  this.options.ignoreLeaks = false;
@@ -328,6 +355,7 @@ Mocha.prototype.checkLeaks = function () {
328
355
  *
329
356
  * @return {Mocha}
330
357
  * @api public
358
+ * @public
331
359
  */
332
360
  Mocha.prototype.fullTrace = function () {
333
361
  this.options.fullStackTrace = true;
@@ -339,6 +367,7 @@ Mocha.prototype.fullTrace = function () {
339
367
  *
340
368
  * @return {Mocha}
341
369
  * @api public
370
+ * @public
342
371
  */
343
372
  Mocha.prototype.growl = function () {
344
373
  this.options.growl = true;
@@ -351,6 +380,7 @@ Mocha.prototype.growl = function () {
351
380
  * @param {Array|String} globals
352
381
  * @return {Mocha}
353
382
  * @api public
383
+ * @public
354
384
  * @param {Array|string} globals
355
385
  * @return {Mocha}
356
386
  */
@@ -365,6 +395,7 @@ Mocha.prototype.globals = function (globals) {
365
395
  * @param {Boolean} colors
366
396
  * @return {Mocha}
367
397
  * @api public
398
+ * @public
368
399
  * @param {boolean} colors
369
400
  * @return {Mocha}
370
401
  */
@@ -381,6 +412,7 @@ Mocha.prototype.useColors = function (colors) {
381
412
  * @param {Boolean} inlineDiffs
382
413
  * @return {Mocha}
383
414
  * @api public
415
+ * @public
384
416
  * @param {boolean} inlineDiffs
385
417
  * @return {Mocha}
386
418
  */
@@ -395,6 +427,7 @@ Mocha.prototype.useInlineDiffs = function (inlineDiffs) {
395
427
  * @param {Boolean} hideDiff
396
428
  * @return {Mocha}
397
429
  * @api public
430
+ * @public
398
431
  * @param {boolean} hideDiff
399
432
  * @return {Mocha}
400
433
  */
@@ -409,6 +442,7 @@ Mocha.prototype.hideDiff = function (hideDiff) {
409
442
  * @param {Number} timeout
410
443
  * @return {Mocha}
411
444
  * @api public
445
+ * @public
412
446
  * @param {number} timeout
413
447
  * @return {Mocha}
414
448
  */
@@ -423,6 +457,7 @@ Mocha.prototype.timeout = function (timeout) {
423
457
  * @param {Number} retry times
424
458
  * @return {Mocha}
425
459
  * @api public
460
+ * @public
426
461
  */
427
462
  Mocha.prototype.retries = function (n) {
428
463
  this.suite.retries(n);
@@ -435,6 +470,7 @@ Mocha.prototype.retries = function (n) {
435
470
  * @param {Number} slow
436
471
  * @return {Mocha}
437
472
  * @api public
473
+ * @public
438
474
  * @param {number} slow
439
475
  * @return {Mocha}
440
476
  */
@@ -449,6 +485,7 @@ Mocha.prototype.slow = function (slow) {
449
485
  * @param {Boolean} enabled
450
486
  * @return {Mocha}
451
487
  * @api public
488
+ * @public
452
489
  * @param {boolean} enabled
453
490
  * @return {Mocha}
454
491
  */
@@ -462,6 +499,7 @@ Mocha.prototype.enableTimeouts = function (enabled) {
462
499
  *
463
500
  * @return {Mocha}
464
501
  * @api public
502
+ * @public
465
503
  */
466
504
  Mocha.prototype.asyncOnly = function () {
467
505
  this.options.asyncOnly = true;
@@ -472,6 +510,7 @@ Mocha.prototype.asyncOnly = function () {
472
510
  * Disable syntax highlighting (in browser).
473
511
  *
474
512
  * @api public
513
+ * @public
475
514
  */
476
515
  Mocha.prototype.noHighlighting = function () {
477
516
  this.options.noHighlighting = true;
@@ -483,6 +522,7 @@ Mocha.prototype.noHighlighting = function () {
483
522
  *
484
523
  * @return {Mocha}
485
524
  * @api public
525
+ * @public
486
526
  */
487
527
  Mocha.prototype.allowUncaught = function () {
488
528
  this.options.allowUncaught = true;
@@ -528,6 +568,7 @@ Mocha.prototype.forbidPending = function () {
528
568
  * cache first in whichever manner best suits your needs.
529
569
  *
530
570
  * @api public
571
+ * @public
531
572
  * @param {Function} fn
532
573
  * @return {Runner}
533
574
  */
package/lib/ms.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module milliseconds
4
+ */
3
5
  /**
4
6
  * Helpers.
5
7
  */
@@ -13,6 +15,8 @@ var y = d * 365.25;
13
15
  /**
14
16
  * Parse or format the given `val`.
15
17
  *
18
+ * @memberof Mocha
19
+ * @public
16
20
  * @api public
17
21
  * @param {string|number} val
18
22
  * @return {string|number}
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module Base
4
+ */
3
5
  /**
4
6
  * Module dependencies.
5
7
  */
@@ -185,6 +187,9 @@ var generateDiff = exports.generateDiff = function (actual, expected) {
185
187
  /**
186
188
  * Output the given `failures` as a list.
187
189
  *
190
+ * @public
191
+ * @memberof Mocha.reporters.Base
192
+ * @variation 1
188
193
  * @param {Array} failures
189
194
  * @api public
190
195
  */
@@ -261,6 +266,9 @@ exports.list = function (failures) {
261
266
  * stats such as test duration, number
262
267
  * of tests passed / failed etc.
263
268
  *
269
+ * @memberof Mocha.reporters
270
+ * @public
271
+ * @class
264
272
  * @param {Runner} runner
265
273
  * @api public
266
274
  */
@@ -328,6 +336,8 @@ function Base (runner) {
328
336
  * Output common epilogue used by many of
329
337
  * the bundled reporters.
330
338
  *
339
+ * @memberof Mocha.reporters.Base
340
+ * @public
331
341
  * @api public
332
342
  */
333
343
  Base.prototype.epilogue = function () {
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module Doc
4
+ */
3
5
  /**
4
6
  * Module dependencies.
5
7
  */
@@ -16,6 +18,10 @@ exports = module.exports = Doc;
16
18
  /**
17
19
  * Initialize a new `Doc` reporter.
18
20
  *
21
+ * @class
22
+ * @memberof Mocha.reporters
23
+ * @extends {Base}
24
+ * @public
19
25
  * @param {Runner} runner
20
26
  * @api public
21
27
  */
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module Dot
4
+ */
3
5
  /**
4
6
  * Module dependencies.
5
7
  */
@@ -17,6 +19,10 @@ exports = module.exports = Dot;
17
19
  /**
18
20
  * Initialize a new `Dot` matrix test reporter.
19
21
  *
22
+ * @class
23
+ * @memberof Mocha.reporters
24
+ * @extends Mocha.reporters.Base
25
+ * @public
20
26
  * @api public
21
27
  * @param {Runner} runner
22
28
  */
@@ -1,7 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  /* eslint-env browser */
4
-
4
+ /**
5
+ * @module HTML
6
+ */
5
7
  /**
6
8
  * Module dependencies.
7
9
  */
@@ -46,6 +48,10 @@ var playIcon = '&#x2023;';
46
48
  /**
47
49
  * Initialize a new `HTML` reporter.
48
50
  *
51
+ * @public
52
+ * @class
53
+ * @memberof Mocha.reporters
54
+ * @extends Mocha.reporters.Base
49
55
  * @api public
50
56
  * @param {Runner} runner
51
57
  */
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module JSONStream
4
+ */
3
5
  /**
4
6
  * Module dependencies.
5
7
  */
@@ -13,8 +15,13 @@ var Base = require('./base');
13
15
  exports = module.exports = List;
14
16
 
15
17
  /**
16
- * Initialize a new `List` test reporter.
18
+ * Initialize a new `JSONStream` test reporter.
17
19
  *
20
+ * @public
21
+ * @name JSONStream
22
+ * @class JSONStream
23
+ * @memberof Mocha.reporters
24
+ * @extends Mocha.reporters.Base
18
25
  * @api public
19
26
  * @param {Runner} runner
20
27
  */
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
-
2
+ /**
3
+ * @module JSON
4
+ */
3
5
  /**
4
6
  * Module dependencies.
5
7
  */
@@ -15,6 +17,10 @@ exports = module.exports = JSONReporter;
15
17
  /**
16
18
  * Initialize a new `JSON` reporter.
17
19
  *
20
+ * @public
21
+ * @class JSON
22
+ * @memberof Mocha.reporters
23
+ * @extends Mocha.reporters.Base
18
24
  * @api public
19
25
  * @param {Runner} runner
20
26
  */
@@ -67,17 +73,44 @@ function JSONReporter (runner) {
67
73
  * @return {Object}
68
74
  */
69
75
  function clean (test) {
76
+ var err = test.err || {};
77
+ if (err instanceof Error) {
78
+ err = errorJSON(err);
79
+ }
80
+
70
81
  return {
71
82
  title: test.title,
72
83
  fullTitle: test.fullTitle(),
73
84
  duration: test.duration,
74
85
  currentRetry: test.currentRetry(),
75
- err: errorJSON(test.err || {})
86
+ err: cleanCycles(err)
76
87
  };
77
88
  }
78
89
 
79
90
  /**
80
- * Transform `error` into a JSON object.
91
+ * Replaces any circular references inside `obj` with '[object Object]'
92
+ *
93
+ * @api private
94
+ * @param {Object} obj
95
+ * @return {Object}
96
+ */
97
+ function cleanCycles (obj) {
98
+ var cache = [];
99
+ return JSON.parse(JSON.stringify(obj, function (key, value) {
100
+ if (typeof value === 'object' && value !== null) {
101
+ if (cache.indexOf(value) !== -1) {
102
+ // Instead of going in a circle, we'll print [object Object]
103
+ return '' + value;
104
+ }
105
+ cache.push(value);
106
+ }
107
+
108
+ return value;
109
+ }));
110
+ }
111
+
112
+ /**
113
+ * Transform an Error object into a JSON object.
81
114
  *
82
115
  * @api private
83
116
  * @param {Error} err