mocha 6.0.0-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.
package/mocha.js CHANGED
@@ -207,6 +207,7 @@ module.exports = global;
207
207
  */
208
208
  var Date = global.Date;
209
209
  var setTimeout = global.setTimeout;
210
+ var EVENT_RUN_END = require('../runner').constants.EVENT_RUN_END;
210
211
 
211
212
  /**
212
213
  * Checks if browser notification support exists.
@@ -250,7 +251,7 @@ exports.notify = function(runner) {
250
251
  .catch(notPermitted);
251
252
  };
252
253
 
253
- runner.once('end', sendNotification);
254
+ runner.once(EVENT_RUN_END, sendNotification);
254
255
  };
255
256
 
256
257
  /**
@@ -326,7 +327,7 @@ function display(runner) {
326
327
  var title;
327
328
 
328
329
  if (stats.failures) {
329
- _message = stats.failures + ' of ' + runner.total + ' tests failed';
330
+ _message = stats.failures + ' of ' + stats.tests + ' tests failed';
330
331
  message = symbol.cross + ' ' + _message;
331
332
  title = 'Failed';
332
333
  } else {
@@ -364,7 +365,7 @@ function notPermitted(err) {
364
365
  }
365
366
 
366
367
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
367
- },{"../../package":89,"_process":68}],3:[function(require,module,exports){
368
+ },{"../../package":89,"../runner":34,"_process":68}],3:[function(require,module,exports){
368
369
  'use strict';
369
370
 
370
371
  /**
@@ -615,7 +616,7 @@ Context.prototype.retries = function(n) {
615
616
  */
616
617
 
617
618
  /**
618
- * Creates an error object used when no files to be tested could be found using specified pattern.
619
+ * Creates an error object to be thrown when no files to be tested could be found using specified pattern.
619
620
  *
620
621
  * @public
621
622
  * @param {string} message - Error message to be displayed.
@@ -630,7 +631,7 @@ function createNoFilesMatchPatternError(message, pattern) {
630
631
  }
631
632
 
632
633
  /**
633
- * Creates an error object used when the reporter specified in the options was not found.
634
+ * Creates an error object to be thrown when the reporter specified in the options was not found.
634
635
  *
635
636
  * @public
636
637
  * @param {string} message - Error message to be displayed.
@@ -645,7 +646,7 @@ function createInvalidReporterError(message, reporter) {
645
646
  }
646
647
 
647
648
  /**
648
- * Creates an error object used when the interface specified in the options was not found.
649
+ * Creates an error object to be thrown when the interface specified in the options was not found.
649
650
  *
650
651
  * @public
651
652
  * @param {string} message - Error message to be displayed.
@@ -660,20 +661,20 @@ function createInvalidInterfaceError(message, ui) {
660
661
  }
661
662
 
662
663
  /**
663
- * Creates an error object used when the type of output specified was not supported.
664
+ * Creates an error object to be thrown when a behavior, option, or parameter is unsupported.
664
665
  *
665
666
  * @public
666
667
  * @param {string} message - Error message to be displayed.
667
668
  * @returns {Error} instance detailing the error condition
668
669
  */
669
- function createNotSupportedError(message) {
670
+ function createUnsupportedError(message) {
670
671
  var err = new Error(message);
671
- err.code = 'ERR_MOCHA_NOT_SUPPORTED';
672
+ err.code = 'ERR_MOCHA_UNSUPPORTED';
672
673
  return err;
673
674
  }
674
675
 
675
676
  /**
676
- * Creates an error object used when an argument is missing.
677
+ * Creates an error object to be thrown when an argument is missing.
677
678
  *
678
679
  * @public
679
680
  * @param {string} message - Error message to be displayed.
@@ -686,7 +687,7 @@ function createMissingArgumentError(message, argument, expected) {
686
687
  }
687
688
 
688
689
  /**
689
- * Creates an error object used when an argument did not use the supported type
690
+ * Creates an error object to be thrown when an argument did not use the supported type
690
691
  *
691
692
  * @public
692
693
  * @param {string} message - Error message to be displayed.
@@ -704,7 +705,7 @@ function createInvalidArgumentTypeError(message, argument, expected) {
704
705
  }
705
706
 
706
707
  /**
707
- * Creates an error object used when an argument did not use the supported value
708
+ * Creates an error object to be thrown when an argument did not use the supported value
708
709
  *
709
710
  * @public
710
711
  * @param {string} message - Error message to be displayed.
@@ -723,27 +724,29 @@ function createInvalidArgumentValueError(message, argument, value, reason) {
723
724
  }
724
725
 
725
726
  /**
726
- * Creates an error object used when an error was thrown but no details were specified.
727
+ * Creates an error object to be thrown when an exception was caught, but the `Error` is falsy or undefined.
727
728
  *
728
729
  * @public
729
730
  * @param {string} message - Error message to be displayed.
730
731
  * @returns {Error} instance detailing the error condition
731
732
  */
732
- function createUndefinedError(message) {
733
+ function createInvalidExceptionError(message, value) {
733
734
  var err = new Error(message);
734
- err.code = 'ERR_MOCHA_UNDEFINED_ERROR';
735
+ err.code = 'ERR_MOCHA_INVALID_EXCEPTION';
736
+ err.valueType = typeof value;
737
+ err.value = value;
735
738
  return err;
736
739
  }
737
740
 
738
741
  module.exports = {
739
742
  createInvalidArgumentTypeError: createInvalidArgumentTypeError,
740
743
  createInvalidArgumentValueError: createInvalidArgumentValueError,
744
+ createInvalidExceptionError: createInvalidExceptionError,
741
745
  createInvalidInterfaceError: createInvalidInterfaceError,
742
746
  createInvalidReporterError: createInvalidReporterError,
743
747
  createMissingArgumentError: createMissingArgumentError,
744
748
  createNoFilesMatchPatternError: createNoFilesMatchPatternError,
745
- createNotSupportedError: createNotSupportedError,
746
- createUndefinedError: createUndefinedError
749
+ createUnsupportedError: createUnsupportedError
747
750
  };
748
751
 
749
752
  },{}],7:[function(require,module,exports){
@@ -798,6 +801,8 @@ Hook.prototype.error = function(err) {
798
801
  'use strict';
799
802
 
800
803
  var Test = require('../test');
804
+ var EVENT_FILE_PRE_REQUIRE = require('../suite').constants
805
+ .EVENT_FILE_PRE_REQUIRE;
801
806
 
802
807
  /**
803
808
  * BDD-style interface:
@@ -819,7 +824,7 @@ var Test = require('../test');
819
824
  module.exports = function bddInterface(suite) {
820
825
  var suites = [suite];
821
826
 
822
- suite.on('pre-require', function(context, file, mocha) {
827
+ suite.on(EVENT_FILE_PRE_REQUIRE, function(context, file, mocha) {
823
828
  var common = require('./common')(suites, context, mocha);
824
829
 
825
830
  context.before = common.before;
@@ -912,7 +917,7 @@ module.exports = function bddInterface(suite) {
912
917
 
913
918
  module.exports.description = 'BDD or RSpec style [default]';
914
919
 
915
- },{"../test":37,"./common":9}],9:[function(require,module,exports){
920
+ },{"../suite":36,"../test":37,"./common":9}],9:[function(require,module,exports){
916
921
  'use strict';
917
922
 
918
923
  var Suite = require('../suite');
@@ -1045,7 +1050,7 @@ module.exports = function(suites, context, mocha) {
1045
1050
  throw new Error('`.only` forbidden');
1046
1051
  }
1047
1052
 
1048
- suite.parent._onlySuites = suite.parent._onlySuites.concat(suite);
1053
+ suite.parent.appendOnlySuite(suite);
1049
1054
  }
1050
1055
  if (suite.pending) {
1051
1056
  if (mocha.options.forbidPending && shouldBeTested(suite)) {
@@ -1056,10 +1061,11 @@ module.exports = function(suites, context, mocha) {
1056
1061
  var result = opts.fn.call(suite);
1057
1062
  if (typeof result !== 'undefined') {
1058
1063
  utils.deprecate(
1059
- 'Deprecation Warning: Suites do not support a return value;' +
1060
- opts.title +
1061
- ' returned :' +
1062
- result
1064
+ 'Suites ignore return values. Suite "' +
1065
+ suite.fullTitle() +
1066
+ '" in ' +
1067
+ suite.file +
1068
+ ' returned a value; this may be a bug in your test code'
1063
1069
  );
1064
1070
  }
1065
1071
  suites.shift();
@@ -1089,7 +1095,7 @@ module.exports = function(suites, context, mocha) {
1089
1095
  * @returns {*}
1090
1096
  */
1091
1097
  only: function(mocha, test) {
1092
- test.parent._onlyTests = test.parent._onlyTests.concat(test);
1098
+ test.parent.appendOnlyTest(test);
1093
1099
  return test;
1094
1100
  },
1095
1101
 
@@ -1139,7 +1145,7 @@ var Test = require('../test');
1139
1145
  module.exports = function(suite) {
1140
1146
  var suites = [suite];
1141
1147
 
1142
- suite.on('require', visit);
1148
+ suite.on(Suite.constants.EVENT_FILE_REQUIRE, visit);
1143
1149
 
1144
1150
  function visit(obj, file) {
1145
1151
  var suite;
@@ -1188,6 +1194,8 @@ exports.exports = require('./exports');
1188
1194
  'use strict';
1189
1195
 
1190
1196
  var Test = require('../test');
1197
+ var EVENT_FILE_PRE_REQUIRE = require('../suite').constants
1198
+ .EVENT_FILE_PRE_REQUIRE;
1191
1199
 
1192
1200
  /**
1193
1201
  * QUnit-style interface:
@@ -1217,7 +1225,7 @@ var Test = require('../test');
1217
1225
  module.exports = function qUnitInterface(suite) {
1218
1226
  var suites = [suite];
1219
1227
 
1220
- suite.on('pre-require', function(context, file, mocha) {
1228
+ suite.on(EVENT_FILE_PRE_REQUIRE, function(context, file, mocha) {
1221
1229
  var common = require('./common')(suites, context, mocha);
1222
1230
 
1223
1231
  context.before = common.before;
@@ -1283,10 +1291,12 @@ module.exports = function qUnitInterface(suite) {
1283
1291
 
1284
1292
  module.exports.description = 'QUnit style';
1285
1293
 
1286
- },{"../test":37,"./common":9}],13:[function(require,module,exports){
1294
+ },{"../suite":36,"../test":37,"./common":9}],13:[function(require,module,exports){
1287
1295
  'use strict';
1288
1296
 
1289
1297
  var Test = require('../test');
1298
+ var EVENT_FILE_PRE_REQUIRE = require('../suite').constants
1299
+ .EVENT_FILE_PRE_REQUIRE;
1290
1300
 
1291
1301
  /**
1292
1302
  * TDD-style interface:
@@ -1316,7 +1326,7 @@ var Test = require('../test');
1316
1326
  module.exports = function(suite) {
1317
1327
  var suites = [suite];
1318
1328
 
1319
- suite.on('pre-require', function(context, file, mocha) {
1329
+ suite.on(EVENT_FILE_PRE_REQUIRE, function(context, file, mocha) {
1320
1330
  var common = require('./common')(suites, context, mocha);
1321
1331
 
1322
1332
  context.setup = common.beforeEach;
@@ -1390,7 +1400,7 @@ module.exports = function(suite) {
1390
1400
  module.exports.description =
1391
1401
  'traditional "suite"/"test" instead of BDD\'s "describe"/"it"';
1392
1402
 
1393
- },{"../test":37,"./common":9}],14:[function(require,module,exports){
1403
+ },{"../suite":36,"../test":37,"./common":9}],14:[function(require,module,exports){
1394
1404
  (function (process,global){
1395
1405
  'use strict';
1396
1406
 
@@ -1406,10 +1416,15 @@ var builtinReporters = require('./reporters');
1406
1416
  var growl = require('./growl');
1407
1417
  var utils = require('./utils');
1408
1418
  var mocharc = require('./mocharc.json');
1409
- var assign = require('object.assign').getPolyfill();
1410
1419
  var errors = require('./errors');
1420
+ var Suite = require('./suite');
1421
+ var createStatsCollector = require('./stats-collector');
1411
1422
  var createInvalidReporterError = errors.createInvalidReporterError;
1412
1423
  var createInvalidInterfaceError = errors.createInvalidInterfaceError;
1424
+ var EVENT_FILE_PRE_REQUIRE = Suite.constants.EVENT_FILE_PRE_REQUIRE;
1425
+ var EVENT_FILE_POST_REQUIRE = Suite.constants.EVENT_FILE_POST_REQUIRE;
1426
+ var EVENT_FILE_REQUIRE = Suite.constants.EVENT_FILE_REQUIRE;
1427
+ var sQuote = utils.sQuote;
1413
1428
 
1414
1429
  exports = module.exports = Mocha;
1415
1430
 
@@ -1445,7 +1460,7 @@ exports.Context = require('./context');
1445
1460
  * @memberof Mocha
1446
1461
  */
1447
1462
  exports.Runner = require('./runner');
1448
- exports.Suite = require('./suite');
1463
+ exports.Suite = Suite;
1449
1464
  exports.Hook = require('./hook');
1450
1465
  exports.Test = require('./test');
1451
1466
 
@@ -1482,11 +1497,11 @@ exports.Test = require('./test');
1482
1497
  * @param {boolean} [options.useInlineDiffs] - Use inline diffs?
1483
1498
  */
1484
1499
  function Mocha(options) {
1485
- options = assign({}, mocharc, options || {});
1500
+ options = utils.assign({}, mocharc, options || {});
1486
1501
  this.files = [];
1487
1502
  this.options = options;
1488
1503
  // root suite
1489
- this.suite = new exports.Suite('', new exports.Context());
1504
+ this.suite = new exports.Suite('', new exports.Context(), true);
1490
1505
 
1491
1506
  if ('useColors' in options) {
1492
1507
  utils.deprecate(
@@ -1617,31 +1632,23 @@ Mocha.prototype.reporter = function(reporter, reporterOptions) {
1617
1632
  } catch (_err) {
1618
1633
  _err.code !== 'MODULE_NOT_FOUND' ||
1619
1634
  _err.message.indexOf('Cannot find module') !== -1
1620
- ? console.warn('"' + reporter + '" reporter not found')
1635
+ ? console.warn(sQuote(reporter) + ' reporter not found')
1621
1636
  : console.warn(
1622
- '"' +
1623
- reporter +
1624
- '" reporter blew up with error:\n' +
1637
+ sQuote(reporter) +
1638
+ ' reporter blew up with error:\n' +
1625
1639
  err.stack
1626
1640
  );
1627
1641
  }
1628
1642
  } else {
1629
1643
  console.warn(
1630
- '"' + reporter + '" reporter blew up with error:\n' + err.stack
1644
+ sQuote(reporter) + ' reporter blew up with error:\n' + err.stack
1631
1645
  );
1632
1646
  }
1633
1647
  }
1634
1648
  }
1635
- if (!_reporter && reporter === 'teamcity') {
1636
- console.warn(
1637
- 'The Teamcity reporter was moved to a package named ' +
1638
- 'mocha-teamcity-reporter ' +
1639
- '(https://npmjs.org/package/mocha-teamcity-reporter).'
1640
- );
1641
- }
1642
1649
  if (!_reporter) {
1643
1650
  throw createInvalidReporterError(
1644
- 'invalid reporter "' + reporter + '"',
1651
+ 'invalid reporter ' + sQuote(reporter),
1645
1652
  reporter
1646
1653
  );
1647
1654
  }
@@ -1670,14 +1677,14 @@ Mocha.prototype.ui = function(name) {
1670
1677
  this._ui = require(name);
1671
1678
  } catch (err) {
1672
1679
  throw createInvalidInterfaceError(
1673
- 'invalid interface "' + name + '"',
1680
+ 'invalid interface ' + sQuote(name),
1674
1681
  name
1675
1682
  );
1676
1683
  }
1677
1684
  }
1678
1685
  this._ui = this._ui(this.suite);
1679
1686
 
1680
- this.suite.on('pre-require', function(context) {
1687
+ this.suite.on(EVENT_FILE_PRE_REQUIRE, function(context) {
1681
1688
  exports.afterEach = context.afterEach || context.teardown;
1682
1689
  exports.after = context.after || context.suiteTeardown;
1683
1690
  exports.beforeEach = context.beforeEach || context.setup;
@@ -1698,7 +1705,6 @@ Mocha.prototype.ui = function(name) {
1698
1705
  };
1699
1706
 
1700
1707
  /**
1701
- * @summary
1702
1708
  * Loads `files` prior to execution.
1703
1709
  *
1704
1710
  * @description
@@ -1707,6 +1713,8 @@ Mocha.prototype.ui = function(name) {
1707
1713
  *
1708
1714
  * @private
1709
1715
  * @see {@link Mocha#addFile}
1716
+ * @see {@link Mocha#run}
1717
+ * @see {@link Mocha#unloadFiles}
1710
1718
  * @param {Function} [fn] - Callback invoked upon completion.
1711
1719
  */
1712
1720
  Mocha.prototype.loadFiles = function(fn) {
@@ -1714,13 +1722,46 @@ Mocha.prototype.loadFiles = function(fn) {
1714
1722
  var suite = this.suite;
1715
1723
  this.files.forEach(function(file) {
1716
1724
  file = path.resolve(file);
1717
- suite.emit('pre-require', global, file, self);
1718
- suite.emit('require', require(file), file, self);
1719
- suite.emit('post-require', global, file, self);
1725
+ suite.emit(EVENT_FILE_PRE_REQUIRE, global, file, self);
1726
+ suite.emit(EVENT_FILE_REQUIRE, require(file), file, self);
1727
+ suite.emit(EVENT_FILE_POST_REQUIRE, global, file, self);
1720
1728
  });
1721
1729
  fn && fn();
1722
1730
  };
1723
1731
 
1732
+ /**
1733
+ * Removes a previously loaded file from Node's `require` cache.
1734
+ *
1735
+ * @private
1736
+ * @static
1737
+ * @see {@link Mocha#unloadFiles}
1738
+ * @param {string} file - Pathname of file to be unloaded.
1739
+ */
1740
+ Mocha.unloadFile = function(file) {
1741
+ delete require.cache[require.resolve(file)];
1742
+ };
1743
+
1744
+ /**
1745
+ * Unloads `files` from Node's `require` cache.
1746
+ *
1747
+ * @description
1748
+ * This allows files to be "freshly" reloaded, providing the ability
1749
+ * to reuse a Mocha instance programmatically.
1750
+ *
1751
+ * <strong>Intended for consumers &mdash; not used internally</strong>
1752
+ *
1753
+ * @public
1754
+ * @see {@link Mocha.unloadFile}
1755
+ * @see {@link Mocha#loadFiles}
1756
+ * @see {@link Mocha#run}
1757
+ * @returns {Mocha} this
1758
+ * @chainable
1759
+ */
1760
+ Mocha.prototype.unloadFiles = function() {
1761
+ this.files.forEach(Mocha.unloadFile);
1762
+ return this;
1763
+ };
1764
+
1724
1765
  /**
1725
1766
  * Sets `grep` filter after escaping RegExp special characters.
1726
1767
  *
@@ -1906,7 +1947,9 @@ Mocha.prototype._growl = growl.notify;
1906
1947
  * mocha.globals(['jQuery', 'MyLib']);
1907
1948
  */
1908
1949
  Mocha.prototype.globals = function(globals) {
1909
- this.options.globals = (this.options.globals || []).concat(globals);
1950
+ this.options.globals = (this.options.globals || [])
1951
+ .concat(globals)
1952
+ .filter(Boolean);
1910
1953
  return this;
1911
1954
  };
1912
1955
 
@@ -2138,8 +2181,7 @@ Object.defineProperty(Mocha.prototype, 'version', {
2138
2181
  */
2139
2182
 
2140
2183
  /**
2141
- * @summary
2142
- * Runs tests and invokes `fn()` when complete.
2184
+ * Runs root suite and invokes `fn()` when complete.
2143
2185
  *
2144
2186
  * @description
2145
2187
  * To run tests multiple times (or to run tests in files that are
@@ -2148,6 +2190,7 @@ Object.defineProperty(Mocha.prototype, 'version', {
2148
2190
  *
2149
2191
  * @public
2150
2192
  * @see {@link Mocha#loadFiles}
2193
+ * @see {@link Mocha#unloadFiles}
2151
2194
  * @see {@link Runner#run}
2152
2195
  * @param {DoneCB} [fn] - Callback invoked when test execution completed.
2153
2196
  * @return {Runner} runner instance
@@ -2160,6 +2203,7 @@ Mocha.prototype.run = function(fn) {
2160
2203
  var options = this.options;
2161
2204
  options.files = this.files;
2162
2205
  var runner = new exports.Runner(suite, options.delay);
2206
+ createStatsCollector(runner);
2163
2207
  var reporter = new this._reporter(runner, options);
2164
2208
  runner.ignoreLeaks = options.ignoreLeaks !== false;
2165
2209
  runner.fullStackTrace = options.fullStackTrace;
@@ -2183,7 +2227,7 @@ Mocha.prototype.run = function(fn) {
2183
2227
  exports.reporters.Base.hideDiff = options.hideDiff;
2184
2228
 
2185
2229
  function done(failures) {
2186
- fn = fn || function fn() {};
2230
+ fn = fn || utils.noop;
2187
2231
  if (reporter.done) {
2188
2232
  reporter.done(failures, fn);
2189
2233
  } else {
@@ -2195,7 +2239,7 @@ Mocha.prototype.run = function(fn) {
2195
2239
  };
2196
2240
 
2197
2241
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
2198
- },{"../package.json":89,"./context":5,"./errors":6,"./growl":2,"./hook":7,"./interfaces":11,"./mocharc.json":15,"./reporters":21,"./runnable":33,"./runner":34,"./suite":36,"./test":37,"./utils":38,"_process":68,"escape-string-regexp":49,"object.assign":64,"path":42}],15:[function(require,module,exports){
2242
+ },{"../package.json":89,"./context":5,"./errors":6,"./growl":2,"./hook":7,"./interfaces":11,"./mocharc.json":15,"./reporters":21,"./runnable":33,"./runner":34,"./stats-collector":35,"./suite":36,"./test":37,"./utils":38,"_process":68,"escape-string-regexp":49,"path":42}],15:[function(require,module,exports){
2199
2243
  module.exports={
2200
2244
  "diff": true,
2201
2245
  "extension": ["js"],
@@ -2236,6 +2280,9 @@ var diff = require('diff');
2236
2280
  var milliseconds = require('ms');
2237
2281
  var utils = require('../utils');
2238
2282
  var supportsColor = process.browser ? null : require('supports-color');
2283
+ var constants = require('../runner').constants;
2284
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
2285
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
2239
2286
 
2240
2287
  /**
2241
2288
  * Expose `Base`.
@@ -2499,7 +2546,7 @@ function Base(runner) {
2499
2546
  this.stats = runner.stats; // assigned so Reporters keep a closer reference
2500
2547
  this.runner = runner;
2501
2548
 
2502
- runner.on('pass', function(test) {
2549
+ runner.on(EVENT_TEST_PASS, function(test) {
2503
2550
  if (test.duration > test.slow()) {
2504
2551
  test.speed = 'slow';
2505
2552
  } else if (test.duration > test.slow() / 2) {
@@ -2509,7 +2556,7 @@ function Base(runner) {
2509
2556
  }
2510
2557
  });
2511
2558
 
2512
- runner.on('fail', function(test, err) {
2559
+ runner.on(EVENT_TEST_FAIL, function(test, err) {
2513
2560
  if (showDiff(err)) {
2514
2561
  stringifyDiffObjs(err);
2515
2562
  }
@@ -2712,7 +2759,7 @@ function sameType(a, b) {
2712
2759
  Base.abstract = true;
2713
2760
 
2714
2761
  }).call(this,require('_process'))
2715
- },{"../utils":38,"_process":68,"diff":48,"ms":60,"supports-color":42,"tty":4}],18:[function(require,module,exports){
2762
+ },{"../runner":34,"../utils":38,"_process":68,"diff":48,"ms":60,"supports-color":42,"tty":4}],18:[function(require,module,exports){
2716
2763
  'use strict';
2717
2764
  /**
2718
2765
  * @module Doc
@@ -2723,6 +2770,11 @@ Base.abstract = true;
2723
2770
 
2724
2771
  var Base = require('./base');
2725
2772
  var utils = require('../utils');
2773
+ var constants = require('../runner').constants;
2774
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
2775
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
2776
+ var EVENT_SUITE_BEGIN = constants.EVENT_SUITE_BEGIN;
2777
+ var EVENT_SUITE_END = constants.EVENT_SUITE_END;
2726
2778
 
2727
2779
  /**
2728
2780
  * Expose `Doc`.
@@ -2748,7 +2800,7 @@ function Doc(runner) {
2748
2800
  return Array(indents).join(' ');
2749
2801
  }
2750
2802
 
2751
- runner.on('suite', function(suite) {
2803
+ runner.on(EVENT_SUITE_BEGIN, function(suite) {
2752
2804
  if (suite.root) {
2753
2805
  return;
2754
2806
  }
@@ -2759,7 +2811,7 @@ function Doc(runner) {
2759
2811
  console.log('%s<dl>', indent());
2760
2812
  });
2761
2813
 
2762
- runner.on('suite end', function(suite) {
2814
+ runner.on(EVENT_SUITE_END, function(suite) {
2763
2815
  if (suite.root) {
2764
2816
  return;
2765
2817
  }
@@ -2769,13 +2821,13 @@ function Doc(runner) {
2769
2821
  --indents;
2770
2822
  });
2771
2823
 
2772
- runner.on('pass', function(test) {
2824
+ runner.on(EVENT_TEST_PASS, function(test) {
2773
2825
  console.log('%s <dt>%s</dt>', indent(), utils.escape(test.title));
2774
2826
  var code = utils.escape(utils.clean(test.body));
2775
2827
  console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
2776
2828
  });
2777
2829
 
2778
- runner.on('fail', function(test, err) {
2830
+ runner.on(EVENT_TEST_FAIL, function(test, err) {
2779
2831
  console.log(
2780
2832
  '%s <dt class="error">%s</dt>',
2781
2833
  indent(),
@@ -2793,7 +2845,7 @@ function Doc(runner) {
2793
2845
 
2794
2846
  Doc.description = 'HTML documentation';
2795
2847
 
2796
- },{"../utils":38,"./base":17}],19:[function(require,module,exports){
2848
+ },{"../runner":34,"../utils":38,"./base":17}],19:[function(require,module,exports){
2797
2849
  (function (process){
2798
2850
  'use strict';
2799
2851
  /**
@@ -2805,6 +2857,12 @@ Doc.description = 'HTML documentation';
2805
2857
 
2806
2858
  var Base = require('./base');
2807
2859
  var inherits = require('../utils').inherits;
2860
+ var constants = require('../runner').constants;
2861
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
2862
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
2863
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
2864
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
2865
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
2808
2866
 
2809
2867
  /**
2810
2868
  * Expose `Dot`.
@@ -2828,18 +2886,18 @@ function Dot(runner) {
2828
2886
  var width = (Base.window.width * 0.75) | 0;
2829
2887
  var n = -1;
2830
2888
 
2831
- runner.on('start', function() {
2889
+ runner.on(EVENT_RUN_BEGIN, function() {
2832
2890
  process.stdout.write('\n');
2833
2891
  });
2834
2892
 
2835
- runner.on('pending', function() {
2893
+ runner.on(EVENT_TEST_PENDING, function() {
2836
2894
  if (++n % width === 0) {
2837
2895
  process.stdout.write('\n ');
2838
2896
  }
2839
2897
  process.stdout.write(Base.color('pending', Base.symbols.comma));
2840
2898
  });
2841
2899
 
2842
- runner.on('pass', function(test) {
2900
+ runner.on(EVENT_TEST_PASS, function(test) {
2843
2901
  if (++n % width === 0) {
2844
2902
  process.stdout.write('\n ');
2845
2903
  }
@@ -2850,14 +2908,14 @@ function Dot(runner) {
2850
2908
  }
2851
2909
  });
2852
2910
 
2853
- runner.on('fail', function() {
2911
+ runner.on(EVENT_TEST_FAIL, function() {
2854
2912
  if (++n % width === 0) {
2855
2913
  process.stdout.write('\n ');
2856
2914
  }
2857
2915
  process.stdout.write(Base.color('fail', Base.symbols.bang));
2858
2916
  });
2859
2917
 
2860
- runner.once('end', function() {
2918
+ runner.once(EVENT_RUN_END, function() {
2861
2919
  console.log();
2862
2920
  self.epilogue();
2863
2921
  });
@@ -2871,7 +2929,7 @@ inherits(Dot, Base);
2871
2929
  Dot.description = 'dot matrix representation';
2872
2930
 
2873
2931
  }).call(this,require('_process'))
2874
- },{"../utils":38,"./base":17,"_process":68}],20:[function(require,module,exports){
2932
+ },{"../runner":34,"../utils":38,"./base":17,"_process":68}],20:[function(require,module,exports){
2875
2933
  (function (global){
2876
2934
  'use strict';
2877
2935
 
@@ -2887,6 +2945,12 @@ var Base = require('./base');
2887
2945
  var utils = require('../utils');
2888
2946
  var Progress = require('../browser/progress');
2889
2947
  var escapeRe = require('escape-string-regexp');
2948
+ var constants = require('../runner').constants;
2949
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
2950
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
2951
+ var EVENT_SUITE_BEGIN = constants.EVENT_SUITE_BEGIN;
2952
+ var EVENT_SUITE_END = constants.EVENT_SUITE_END;
2953
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
2890
2954
  var escape = utils.escape;
2891
2955
 
2892
2956
  /**
@@ -2987,7 +3051,7 @@ function HTML(runner) {
2987
3051
  progress.size(40);
2988
3052
  }
2989
3053
 
2990
- runner.on('suite', function(suite) {
3054
+ runner.on(EVENT_SUITE_BEGIN, function(suite) {
2991
3055
  if (suite.root) {
2992
3056
  return;
2993
3057
  }
@@ -3006,7 +3070,7 @@ function HTML(runner) {
3006
3070
  el.appendChild(stack[0]);
3007
3071
  });
3008
3072
 
3009
- runner.on('suite end', function(suite) {
3073
+ runner.on(EVENT_SUITE_END, function(suite) {
3010
3074
  if (suite.root) {
3011
3075
  updateStats();
3012
3076
  return;
@@ -3014,7 +3078,7 @@ function HTML(runner) {
3014
3078
  stack.shift();
3015
3079
  });
3016
3080
 
3017
- runner.on('pass', function(test) {
3081
+ runner.on(EVENT_TEST_PASS, function(test) {
3018
3082
  var url = self.testURL(test);
3019
3083
  var markup =
3020
3084
  '<li class="test pass %e"><h2>%e<span class="duration">%ems</span> ' +
@@ -3027,7 +3091,7 @@ function HTML(runner) {
3027
3091
  updateStats();
3028
3092
  });
3029
3093
 
3030
- runner.on('fail', function(test) {
3094
+ runner.on(EVENT_TEST_FAIL, function(test) {
3031
3095
  var el = fragment(
3032
3096
  '<li class="test fail"><h2>%e <a href="%e" class="replay">' +
3033
3097
  playIcon +
@@ -3083,7 +3147,7 @@ function HTML(runner) {
3083
3147
  updateStats();
3084
3148
  });
3085
3149
 
3086
- runner.on('pending', function(test) {
3150
+ runner.on(EVENT_TEST_PENDING, function(test) {
3087
3151
  var el = fragment(
3088
3152
  '<li class="test pass pending"><h2>%e</h2></li>',
3089
3153
  test.title
@@ -3258,7 +3322,7 @@ function on(el, event, fn) {
3258
3322
  HTML.browserOnly = true;
3259
3323
 
3260
3324
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
3261
- },{"../browser/progress":3,"../utils":38,"./base":17,"escape-string-regexp":49}],21:[function(require,module,exports){
3325
+ },{"../browser/progress":3,"../runner":34,"../utils":38,"./base":17,"escape-string-regexp":49}],21:[function(require,module,exports){
3262
3326
  'use strict';
3263
3327
 
3264
3328
  // Alias exports to a their normalized format Mocha#reporter to prevent a need
@@ -3290,6 +3354,11 @@ exports.JSONStream = exports['json-stream'] = require('./json-stream');
3290
3354
  */
3291
3355
 
3292
3356
  var Base = require('./base');
3357
+ var constants = require('../runner').constants;
3358
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
3359
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
3360
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
3361
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
3293
3362
 
3294
3363
  /**
3295
3364
  * Expose `JSONStream`.
@@ -3312,22 +3381,22 @@ function JSONStream(runner) {
3312
3381
  var self = this;
3313
3382
  var total = runner.total;
3314
3383
 
3315
- runner.once('start', function() {
3384
+ runner.once(EVENT_RUN_BEGIN, function() {
3316
3385
  writeEvent(['start', {total: total}]);
3317
3386
  });
3318
3387
 
3319
- runner.on('pass', function(test) {
3388
+ runner.on(EVENT_TEST_PASS, function(test) {
3320
3389
  writeEvent(['pass', clean(test)]);
3321
3390
  });
3322
3391
 
3323
- runner.on('fail', function(test, err) {
3392
+ runner.on(EVENT_TEST_FAIL, function(test, err) {
3324
3393
  test = clean(test);
3325
3394
  test.err = err.message;
3326
3395
  test.stack = err.stack || null;
3327
3396
  writeEvent(['fail', test]);
3328
3397
  });
3329
3398
 
3330
- runner.once('end', function() {
3399
+ runner.once(EVENT_RUN_END, function() {
3331
3400
  writeEvent(['end', self.stats]);
3332
3401
  });
3333
3402
  }
@@ -3367,7 +3436,7 @@ function clean(test) {
3367
3436
  JSONStream.description = 'newline delimited JSON events';
3368
3437
 
3369
3438
  }).call(this,require('_process'))
3370
- },{"./base":17,"_process":68}],23:[function(require,module,exports){
3439
+ },{"../runner":34,"./base":17,"_process":68}],23:[function(require,module,exports){
3371
3440
  (function (process){
3372
3441
  'use strict';
3373
3442
  /**
@@ -3378,6 +3447,12 @@ JSONStream.description = 'newline delimited JSON events';
3378
3447
  */
3379
3448
 
3380
3449
  var Base = require('./base');
3450
+ var constants = require('../runner').constants;
3451
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
3452
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
3453
+ var EVENT_TEST_END = constants.EVENT_TEST_END;
3454
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
3455
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
3381
3456
 
3382
3457
  /**
3383
3458
  * Expose `JSON`.
@@ -3403,23 +3478,23 @@ function JSONReporter(runner) {
3403
3478
  var failures = [];
3404
3479
  var passes = [];
3405
3480
 
3406
- runner.on('test end', function(test) {
3481
+ runner.on(EVENT_TEST_END, function(test) {
3407
3482
  tests.push(test);
3408
3483
  });
3409
3484
 
3410
- runner.on('pass', function(test) {
3485
+ runner.on(EVENT_TEST_PASS, function(test) {
3411
3486
  passes.push(test);
3412
3487
  });
3413
3488
 
3414
- runner.on('fail', function(test) {
3489
+ runner.on(EVENT_TEST_FAIL, function(test) {
3415
3490
  failures.push(test);
3416
3491
  });
3417
3492
 
3418
- runner.on('pending', function(test) {
3493
+ runner.on(EVENT_TEST_PENDING, function(test) {
3419
3494
  pending.push(test);
3420
3495
  });
3421
3496
 
3422
- runner.once('end', function() {
3497
+ runner.once(EVENT_RUN_END, function() {
3423
3498
  var obj = {
3424
3499
  stats: self.stats,
3425
3500
  tests: tests.map(clean),
@@ -3499,7 +3574,7 @@ function errorJSON(err) {
3499
3574
  JSONReporter.description = 'single JSON object';
3500
3575
 
3501
3576
  }).call(this,require('_process'))
3502
- },{"./base":17,"_process":68}],24:[function(require,module,exports){
3577
+ },{"../runner":34,"./base":17,"_process":68}],24:[function(require,module,exports){
3503
3578
  (function (process){
3504
3579
  'use strict';
3505
3580
  /**
@@ -3511,6 +3586,12 @@ JSONReporter.description = 'single JSON object';
3511
3586
 
3512
3587
  var Base = require('./base');
3513
3588
  var inherits = require('../utils').inherits;
3589
+ var constants = require('../runner').constants;
3590
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
3591
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
3592
+ var EVENT_TEST_END = constants.EVENT_TEST_END;
3593
+ var STATE_FAILED = require('../runnable').constants.STATE_FAILED;
3594
+
3514
3595
  var cursor = Base.cursor;
3515
3596
  var color = Base.color;
3516
3597
 
@@ -3563,17 +3644,17 @@ function Landing(runner) {
3563
3644
  return ' ' + color('runway', buf);
3564
3645
  }
3565
3646
 
3566
- runner.on('start', function() {
3647
+ runner.on(EVENT_RUN_BEGIN, function() {
3567
3648
  stream.write('\n\n\n ');
3568
3649
  cursor.hide();
3569
3650
  });
3570
3651
 
3571
- runner.on('test end', function(test) {
3652
+ runner.on(EVENT_TEST_END, function(test) {
3572
3653
  // check if the plane crashed
3573
3654
  var col = crashed === -1 ? ((width * ++n) / total) | 0 : crashed;
3574
3655
 
3575
3656
  // show the crash
3576
- if (test.state === 'failed') {
3657
+ if (test.state === STATE_FAILED) {
3577
3658
  plane = color('plane crash', '✈');
3578
3659
  crashed = col;
3579
3660
  }
@@ -3589,7 +3670,7 @@ function Landing(runner) {
3589
3670
  stream.write('\u001b[0m');
3590
3671
  });
3591
3672
 
3592
- runner.once('end', function() {
3673
+ runner.once(EVENT_RUN_END, function() {
3593
3674
  cursor.show();
3594
3675
  console.log();
3595
3676
  self.epilogue();
@@ -3604,7 +3685,7 @@ inherits(Landing, Base);
3604
3685
  Landing.description = 'Unicode landing strip';
3605
3686
 
3606
3687
  }).call(this,require('_process'))
3607
- },{"../utils":38,"./base":17,"_process":68}],25:[function(require,module,exports){
3688
+ },{"../runnable":33,"../runner":34,"../utils":38,"./base":17,"_process":68}],25:[function(require,module,exports){
3608
3689
  (function (process){
3609
3690
  'use strict';
3610
3691
  /**
@@ -3616,6 +3697,13 @@ Landing.description = 'Unicode landing strip';
3616
3697
 
3617
3698
  var Base = require('./base');
3618
3699
  var inherits = require('../utils').inherits;
3700
+ var constants = require('../runner').constants;
3701
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
3702
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
3703
+ var EVENT_TEST_BEGIN = constants.EVENT_TEST_BEGIN;
3704
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
3705
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
3706
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
3619
3707
  var color = Base.color;
3620
3708
  var cursor = Base.cursor;
3621
3709
 
@@ -3640,20 +3728,20 @@ function List(runner) {
3640
3728
  var self = this;
3641
3729
  var n = 0;
3642
3730
 
3643
- runner.on('start', function() {
3731
+ runner.on(EVENT_RUN_BEGIN, function() {
3644
3732
  console.log();
3645
3733
  });
3646
3734
 
3647
- runner.on('test', function(test) {
3735
+ runner.on(EVENT_TEST_BEGIN, function(test) {
3648
3736
  process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
3649
3737
  });
3650
3738
 
3651
- runner.on('pending', function(test) {
3739
+ runner.on(EVENT_TEST_PENDING, function(test) {
3652
3740
  var fmt = color('checkmark', ' -') + color('pending', ' %s');
3653
3741
  console.log(fmt, test.fullTitle());
3654
3742
  });
3655
3743
 
3656
- runner.on('pass', function(test) {
3744
+ runner.on(EVENT_TEST_PASS, function(test) {
3657
3745
  var fmt =
3658
3746
  color('checkmark', ' ' + Base.symbols.ok) +
3659
3747
  color('pass', ' %s: ') +
@@ -3662,12 +3750,12 @@ function List(runner) {
3662
3750
  console.log(fmt, test.fullTitle(), test.duration);
3663
3751
  });
3664
3752
 
3665
- runner.on('fail', function(test) {
3753
+ runner.on(EVENT_TEST_FAIL, function(test) {
3666
3754
  cursor.CR();
3667
3755
  console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
3668
3756
  });
3669
3757
 
3670
- runner.once('end', self.epilogue.bind(self));
3758
+ runner.once(EVENT_RUN_END, self.epilogue.bind(self));
3671
3759
  }
3672
3760
 
3673
3761
  /**
@@ -3678,7 +3766,7 @@ inherits(List, Base);
3678
3766
  List.description = 'like "spec" reporter but flat';
3679
3767
 
3680
3768
  }).call(this,require('_process'))
3681
- },{"../utils":38,"./base":17,"_process":68}],26:[function(require,module,exports){
3769
+ },{"../runner":34,"../utils":38,"./base":17,"_process":68}],26:[function(require,module,exports){
3682
3770
  (function (process){
3683
3771
  'use strict';
3684
3772
  /**
@@ -3690,6 +3778,11 @@ List.description = 'like "spec" reporter but flat';
3690
3778
 
3691
3779
  var Base = require('./base');
3692
3780
  var utils = require('../utils');
3781
+ var constants = require('../runner').constants;
3782
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
3783
+ var EVENT_SUITE_BEGIN = constants.EVENT_SUITE_BEGIN;
3784
+ var EVENT_SUITE_END = constants.EVENT_SUITE_END;
3785
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
3693
3786
 
3694
3787
  /**
3695
3788
  * Constants
@@ -3759,18 +3852,18 @@ function Markdown(runner) {
3759
3852
 
3760
3853
  generateTOC(runner.suite);
3761
3854
 
3762
- runner.on('suite', function(suite) {
3855
+ runner.on(EVENT_SUITE_BEGIN, function(suite) {
3763
3856
  ++level;
3764
3857
  var slug = utils.slug(suite.fullTitle());
3765
3858
  buf += '<a name="' + slug + '"></a>' + '\n';
3766
3859
  buf += title(suite.title) + '\n';
3767
3860
  });
3768
3861
 
3769
- runner.on('suite end', function() {
3862
+ runner.on(EVENT_SUITE_END, function() {
3770
3863
  --level;
3771
3864
  });
3772
3865
 
3773
- runner.on('pass', function(test) {
3866
+ runner.on(EVENT_TEST_PASS, function(test) {
3774
3867
  var code = utils.clean(test.body);
3775
3868
  buf += test.title + '.\n';
3776
3869
  buf += '\n```js\n';
@@ -3778,7 +3871,7 @@ function Markdown(runner) {
3778
3871
  buf += '```\n\n';
3779
3872
  });
3780
3873
 
3781
- runner.once('end', function() {
3874
+ runner.once(EVENT_RUN_END, function() {
3782
3875
  process.stdout.write('# TOC\n');
3783
3876
  process.stdout.write(generateTOC(runner.suite));
3784
3877
  process.stdout.write(buf);
@@ -3788,7 +3881,7 @@ function Markdown(runner) {
3788
3881
  Markdown.description = 'GitHub Flavored Markdown';
3789
3882
 
3790
3883
  }).call(this,require('_process'))
3791
- },{"../utils":38,"./base":17,"_process":68}],27:[function(require,module,exports){
3884
+ },{"../runner":34,"../utils":38,"./base":17,"_process":68}],27:[function(require,module,exports){
3792
3885
  (function (process){
3793
3886
  'use strict';
3794
3887
  /**
@@ -3800,6 +3893,9 @@ Markdown.description = 'GitHub Flavored Markdown';
3800
3893
 
3801
3894
  var Base = require('./base');
3802
3895
  var inherits = require('../utils').inherits;
3896
+ var constants = require('../runner').constants;
3897
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
3898
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
3803
3899
 
3804
3900
  /**
3805
3901
  * Expose `Min`.
@@ -3819,14 +3915,14 @@ exports = module.exports = Min;
3819
3915
  function Min(runner) {
3820
3916
  Base.call(this, runner);
3821
3917
 
3822
- runner.on('start', function() {
3918
+ runner.on(EVENT_RUN_BEGIN, function() {
3823
3919
  // clear screen
3824
3920
  process.stdout.write('\u001b[2J');
3825
3921
  // set cursor position
3826
3922
  process.stdout.write('\u001b[1;3H');
3827
3923
  });
3828
3924
 
3829
- runner.once('end', this.epilogue.bind(this));
3925
+ runner.once(EVENT_RUN_END, this.epilogue.bind(this));
3830
3926
  }
3831
3927
 
3832
3928
  /**
@@ -3837,7 +3933,7 @@ inherits(Min, Base);
3837
3933
  Min.description = 'essentially just a summary';
3838
3934
 
3839
3935
  }).call(this,require('_process'))
3840
- },{"../utils":38,"./base":17,"_process":68}],28:[function(require,module,exports){
3936
+ },{"../runner":34,"../utils":38,"./base":17,"_process":68}],28:[function(require,module,exports){
3841
3937
  (function (process){
3842
3938
  'use strict';
3843
3939
  /**
@@ -3848,7 +3944,13 @@ Min.description = 'essentially just a summary';
3848
3944
  */
3849
3945
 
3850
3946
  var Base = require('./base');
3947
+ var constants = require('../runner').constants;
3851
3948
  var inherits = require('../utils').inherits;
3949
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
3950
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
3951
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
3952
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
3953
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
3852
3954
 
3853
3955
  /**
3854
3956
  * Expose `Dot`.
@@ -3881,24 +3983,24 @@ function NyanCat(runner) {
3881
3983
  this.trajectories = [[], [], [], []];
3882
3984
  this.trajectoryWidthMax = width - nyanCatWidth;
3883
3985
 
3884
- runner.on('start', function() {
3986
+ runner.on(EVENT_RUN_BEGIN, function() {
3885
3987
  Base.cursor.hide();
3886
3988
  self.draw();
3887
3989
  });
3888
3990
 
3889
- runner.on('pending', function() {
3991
+ runner.on(EVENT_TEST_PENDING, function() {
3890
3992
  self.draw();
3891
3993
  });
3892
3994
 
3893
- runner.on('pass', function() {
3995
+ runner.on(EVENT_TEST_PASS, function() {
3894
3996
  self.draw();
3895
3997
  });
3896
3998
 
3897
- runner.on('fail', function() {
3999
+ runner.on(EVENT_TEST_FAIL, function() {
3898
4000
  self.draw();
3899
4001
  });
3900
4002
 
3901
- runner.once('end', function() {
4003
+ runner.once(EVENT_RUN_END, function() {
3902
4004
  Base.cursor.show();
3903
4005
  for (var i = 0; i < self.numberOfLines; i++) {
3904
4006
  write('\n');
@@ -4111,7 +4213,7 @@ function write(string) {
4111
4213
  NyanCat.description = '"nyan cat"';
4112
4214
 
4113
4215
  }).call(this,require('_process'))
4114
- },{"../utils":38,"./base":17,"_process":68}],29:[function(require,module,exports){
4216
+ },{"../runner":34,"../utils":38,"./base":17,"_process":68}],29:[function(require,module,exports){
4115
4217
  (function (process){
4116
4218
  'use strict';
4117
4219
  /**
@@ -4122,6 +4224,10 @@ NyanCat.description = '"nyan cat"';
4122
4224
  */
4123
4225
 
4124
4226
  var Base = require('./base');
4227
+ var constants = require('../runner').constants;
4228
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
4229
+ var EVENT_TEST_END = constants.EVENT_TEST_END;
4230
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
4125
4231
  var inherits = require('../utils').inherits;
4126
4232
  var color = Base.color;
4127
4233
  var cursor = Base.cursor;
@@ -4168,13 +4274,13 @@ function Progress(runner, options) {
4168
4274
  options.verbose = reporterOptions.verbose || false;
4169
4275
 
4170
4276
  // tests started
4171
- runner.on('start', function() {
4277
+ runner.on(EVENT_RUN_BEGIN, function() {
4172
4278
  console.log();
4173
4279
  cursor.hide();
4174
4280
  });
4175
4281
 
4176
4282
  // tests complete
4177
- runner.on('test end', function() {
4283
+ runner.on(EVENT_TEST_END, function() {
4178
4284
  complete++;
4179
4285
 
4180
4286
  var percent = complete / total;
@@ -4200,7 +4306,7 @@ function Progress(runner, options) {
4200
4306
 
4201
4307
  // tests are complete, output some stats
4202
4308
  // and the failures if any
4203
- runner.once('end', function() {
4309
+ runner.once(EVENT_RUN_END, function() {
4204
4310
  cursor.show();
4205
4311
  console.log();
4206
4312
  self.epilogue();
@@ -4215,7 +4321,7 @@ inherits(Progress, Base);
4215
4321
  Progress.description = 'a progress bar';
4216
4322
 
4217
4323
  }).call(this,require('_process'))
4218
- },{"../utils":38,"./base":17,"_process":68}],30:[function(require,module,exports){
4324
+ },{"../runner":34,"../utils":38,"./base":17,"_process":68}],30:[function(require,module,exports){
4219
4325
  'use strict';
4220
4326
  /**
4221
4327
  * @module Spec
@@ -4225,6 +4331,14 @@ Progress.description = 'a progress bar';
4225
4331
  */
4226
4332
 
4227
4333
  var Base = require('./base');
4334
+ var constants = require('../runner').constants;
4335
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
4336
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
4337
+ var EVENT_SUITE_BEGIN = constants.EVENT_SUITE_BEGIN;
4338
+ var EVENT_SUITE_END = constants.EVENT_SUITE_END;
4339
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
4340
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
4341
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
4228
4342
  var inherits = require('../utils').inherits;
4229
4343
  var color = Base.color;
4230
4344
 
@@ -4254,28 +4368,28 @@ function Spec(runner) {
4254
4368
  return Array(indents).join(' ');
4255
4369
  }
4256
4370
 
4257
- runner.on('start', function() {
4371
+ runner.on(EVENT_RUN_BEGIN, function() {
4258
4372
  console.log();
4259
4373
  });
4260
4374
 
4261
- runner.on('suite', function(suite) {
4375
+ runner.on(EVENT_SUITE_BEGIN, function(suite) {
4262
4376
  ++indents;
4263
4377
  console.log(color('suite', '%s%s'), indent(), suite.title);
4264
4378
  });
4265
4379
 
4266
- runner.on('suite end', function() {
4380
+ runner.on(EVENT_SUITE_END, function() {
4267
4381
  --indents;
4268
4382
  if (indents === 1) {
4269
4383
  console.log();
4270
4384
  }
4271
4385
  });
4272
4386
 
4273
- runner.on('pending', function(test) {
4387
+ runner.on(EVENT_TEST_PENDING, function(test) {
4274
4388
  var fmt = indent() + color('pending', ' - %s');
4275
4389
  console.log(fmt, test.title);
4276
4390
  });
4277
4391
 
4278
- runner.on('pass', function(test) {
4392
+ runner.on(EVENT_TEST_PASS, function(test) {
4279
4393
  var fmt;
4280
4394
  if (test.speed === 'fast') {
4281
4395
  fmt =
@@ -4293,11 +4407,11 @@ function Spec(runner) {
4293
4407
  }
4294
4408
  });
4295
4409
 
4296
- runner.on('fail', function(test) {
4410
+ runner.on(EVENT_TEST_FAIL, function(test) {
4297
4411
  console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
4298
4412
  });
4299
4413
 
4300
- runner.once('end', self.epilogue.bind(self));
4414
+ runner.once(EVENT_RUN_END, self.epilogue.bind(self));
4301
4415
  }
4302
4416
 
4303
4417
  /**
@@ -4307,7 +4421,7 @@ inherits(Spec, Base);
4307
4421
 
4308
4422
  Spec.description = 'hierarchical & verbose [default]';
4309
4423
 
4310
- },{"../utils":38,"./base":17}],31:[function(require,module,exports){
4424
+ },{"../runner":34,"../utils":38,"./base":17}],31:[function(require,module,exports){
4311
4425
  (function (process){
4312
4426
  'use strict';
4313
4427
  /**
@@ -4319,6 +4433,13 @@ Spec.description = 'hierarchical & verbose [default]';
4319
4433
 
4320
4434
  var util = require('util');
4321
4435
  var Base = require('./base');
4436
+ var constants = require('../runner').constants;
4437
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
4438
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
4439
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
4440
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
4441
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
4442
+ var EVENT_TEST_END = constants.EVENT_TEST_END;
4322
4443
  var inherits = require('../utils').inherits;
4323
4444
  var sprintf = util.format;
4324
4445
 
@@ -4353,29 +4474,29 @@ function TAP(runner, options) {
4353
4474
 
4354
4475
  this._producer = createProducer(tapVersion);
4355
4476
 
4356
- runner.once('start', function() {
4477
+ runner.once(EVENT_RUN_BEGIN, function() {
4357
4478
  var ntests = runner.grepTotal(runner.suite);
4358
4479
  self._producer.writeVersion();
4359
4480
  self._producer.writePlan(ntests);
4360
4481
  });
4361
4482
 
4362
- runner.on('test end', function() {
4483
+ runner.on(EVENT_TEST_END, function() {
4363
4484
  ++n;
4364
4485
  });
4365
4486
 
4366
- runner.on('pending', function(test) {
4487
+ runner.on(EVENT_TEST_PENDING, function(test) {
4367
4488
  self._producer.writePending(n, test);
4368
4489
  });
4369
4490
 
4370
- runner.on('pass', function(test) {
4491
+ runner.on(EVENT_TEST_PASS, function(test) {
4371
4492
  self._producer.writePass(n, test);
4372
4493
  });
4373
4494
 
4374
- runner.on('fail', function(test, err) {
4495
+ runner.on(EVENT_TEST_FAIL, function(test, err) {
4375
4496
  self._producer.writeFail(n, test, err);
4376
4497
  });
4377
4498
 
4378
- runner.once('end', function() {
4499
+ runner.once(EVENT_RUN_END, function() {
4379
4500
  self._producer.writeEpilogue(runner.stats);
4380
4501
  });
4381
4502
  }
@@ -4598,7 +4719,7 @@ inherits(TAP13Producer, TAPProducer);
4598
4719
  TAP.description = 'TAP-compatible output';
4599
4720
 
4600
4721
  }).call(this,require('_process'))
4601
- },{"../utils":38,"./base":17,"_process":68,"util":88}],32:[function(require,module,exports){
4722
+ },{"../runner":34,"../utils":38,"./base":17,"_process":68,"util":88}],32:[function(require,module,exports){
4602
4723
  (function (process,global){
4603
4724
  'use strict';
4604
4725
  /**
@@ -4610,13 +4731,20 @@ TAP.description = 'TAP-compatible output';
4610
4731
 
4611
4732
  var Base = require('./base');
4612
4733
  var utils = require('../utils');
4613
- var inherits = utils.inherits;
4614
4734
  var fs = require('fs');
4615
- var escape = utils.escape;
4616
4735
  var mkdirp = require('mkdirp');
4617
4736
  var path = require('path');
4618
4737
  var errors = require('../errors');
4619
- var createNotSupportedError = errors.createNotSupportedError;
4738
+ var createUnsupportedError = errors.createUnsupportedError;
4739
+ var constants = require('../runner').constants;
4740
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
4741
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
4742
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
4743
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
4744
+ var STATE_FAILED = require('../runnable').constants.STATE_FAILED;
4745
+ var inherits = utils.inherits;
4746
+ var escape = utils.escape;
4747
+
4620
4748
  /**
4621
4749
  * Save timer references to avoid Sinon interfering (see GH-237).
4622
4750
  */
@@ -4653,7 +4781,7 @@ function XUnit(runner, options) {
4653
4781
  if (options && options.reporterOptions) {
4654
4782
  if (options.reporterOptions.output) {
4655
4783
  if (!fs.createWriteStream) {
4656
- throw createNotSupportedError('file output not supported in browser');
4784
+ throw createUnsupportedError('file output not supported in browser');
4657
4785
  }
4658
4786
 
4659
4787
  mkdirp.sync(path.dirname(options.reporterOptions.output));
@@ -4667,19 +4795,19 @@ function XUnit(runner, options) {
4667
4795
  // fall back to the default suite name
4668
4796
  suiteName = suiteName || DEFAULT_SUITE_NAME;
4669
4797
 
4670
- runner.on('pending', function(test) {
4798
+ runner.on(EVENT_TEST_PENDING, function(test) {
4671
4799
  tests.push(test);
4672
4800
  });
4673
4801
 
4674
- runner.on('pass', function(test) {
4802
+ runner.on(EVENT_TEST_PASS, function(test) {
4675
4803
  tests.push(test);
4676
4804
  });
4677
4805
 
4678
- runner.on('fail', function(test) {
4806
+ runner.on(EVENT_TEST_FAIL, function(test) {
4679
4807
  tests.push(test);
4680
4808
  });
4681
4809
 
4682
- runner.once('end', function() {
4810
+ runner.once(EVENT_RUN_END, function() {
4683
4811
  self.write(
4684
4812
  tag(
4685
4813
  'testsuite',
@@ -4754,7 +4882,7 @@ XUnit.prototype.test = function(test) {
4754
4882
  time: test.duration / 1000 || 0
4755
4883
  };
4756
4884
 
4757
- if (test.state === 'failed') {
4885
+ if (test.state === STATE_FAILED) {
4758
4886
  var err = test.err;
4759
4887
  var diff =
4760
4888
  Base.hideDiff || !err.actual || !err.expected
@@ -4810,14 +4938,17 @@ function tag(name, attrs, close, content) {
4810
4938
  XUnit.description = 'XUnit-compatible XML output';
4811
4939
 
4812
4940
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
4813
- },{"../errors":6,"../utils":38,"./base":17,"_process":68,"fs":42,"mkdirp":59,"path":42}],33:[function(require,module,exports){
4941
+ },{"../errors":6,"../runnable":33,"../runner":34,"../utils":38,"./base":17,"_process":68,"fs":42,"mkdirp":59,"path":42}],33:[function(require,module,exports){
4814
4942
  (function (global){
4815
4943
  'use strict';
4944
+
4816
4945
  var EventEmitter = require('events').EventEmitter;
4817
4946
  var Pending = require('./pending');
4818
4947
  var debug = require('debug')('mocha:runnable');
4819
4948
  var milliseconds = require('ms');
4820
4949
  var utils = require('./utils');
4950
+ var createInvalidExceptionError = require('./errors')
4951
+ .createInvalidExceptionError;
4821
4952
 
4822
4953
  /**
4823
4954
  * Save timer references to avoid Sinon interfering (see GH-237).
@@ -4830,10 +4961,11 @@ var toString = Object.prototype.toString;
4830
4961
  module.exports = Runnable;
4831
4962
 
4832
4963
  /**
4833
- * Initialize a new `Runnable` with the given `title` and callback `fn`. Derived from [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
4964
+ * Initialize a new `Runnable` with the given `title` and callback `fn`.
4834
4965
  *
4835
4966
  * @class
4836
- * @extends EventEmitter
4967
+ * @extends external:EventEmitter
4968
+ * @public
4837
4969
  * @param {String} title
4838
4970
  * @param {Function} fn
4839
4971
  */
@@ -4963,7 +5095,7 @@ Runnable.prototype.isPending = function() {
4963
5095
  * @private
4964
5096
  */
4965
5097
  Runnable.prototype.isFailed = function() {
4966
- return !this.isPending() && this.state === 'failed';
5098
+ return !this.isPending() && this.state === constants.STATE_FAILED;
4967
5099
  };
4968
5100
 
4969
5101
  /**
@@ -4972,7 +5104,7 @@ Runnable.prototype.isFailed = function() {
4972
5104
  * @private
4973
5105
  */
4974
5106
  Runnable.prototype.isPassed = function() {
4975
- return !this.isPending() && this.state === 'passed';
5107
+ return !this.isPending() && this.state === constants.STATE_PASSED;
4976
5108
  };
4977
5109
 
4978
5110
  /**
@@ -5167,7 +5299,7 @@ Runnable.prototype.run = function(fn) {
5167
5299
  callFnAsync(this.fn);
5168
5300
  } catch (err) {
5169
5301
  emitted = true;
5170
- done(utils.getError(err));
5302
+ done(Runnable.toValueOrError(err));
5171
5303
  }
5172
5304
  return;
5173
5305
  }
@@ -5190,7 +5322,7 @@ Runnable.prototype.run = function(fn) {
5190
5322
  }
5191
5323
  } catch (err) {
5192
5324
  emitted = true;
5193
- done(utils.getError(err));
5325
+ done(Runnable.toValueOrError(err));
5194
5326
  }
5195
5327
 
5196
5328
  function callFn(fn) {
@@ -5265,33 +5397,82 @@ Runnable.prototype._timeoutError = function(ms) {
5265
5397
  return new Error(msg);
5266
5398
  };
5267
5399
 
5400
+ var constants = utils.defineConstants(
5401
+ /**
5402
+ * {@link Runnable}-related constants.
5403
+ * @public
5404
+ * @memberof Runnable
5405
+ * @readonly
5406
+ * @static
5407
+ * @alias constants
5408
+ * @enum {string}
5409
+ */
5410
+ {
5411
+ /**
5412
+ * Value of `state` prop when a `Runnable` has failed
5413
+ */
5414
+ STATE_FAILED: 'failed',
5415
+ /**
5416
+ * Value of `state` prop when a `Runnable` has passed
5417
+ */
5418
+ STATE_PASSED: 'passed'
5419
+ }
5420
+ );
5421
+
5422
+ /**
5423
+ * Given `value`, return identity if truthy, otherwise create an "invalid exception" error and return that.
5424
+ * @param {*} [value] - Value to return, if present
5425
+ * @returns {*|Error} `value`, otherwise an `Error`
5426
+ * @private
5427
+ */
5428
+ Runnable.toValueOrError = function(value) {
5429
+ return (
5430
+ value ||
5431
+ createInvalidExceptionError(
5432
+ 'Runnable failed with falsy or undefined exception. Please throw an Error instead.',
5433
+ value
5434
+ )
5435
+ );
5436
+ };
5437
+
5438
+ Runnable.constants = constants;
5439
+
5268
5440
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
5269
- },{"./pending":16,"./utils":38,"debug":45,"events":50,"ms":60}],34:[function(require,module,exports){
5441
+ },{"./errors":6,"./pending":16,"./utils":38,"debug":45,"events":50,"ms":60}],34:[function(require,module,exports){
5270
5442
  (function (process,global){
5271
5443
  'use strict';
5272
5444
 
5273
- /**
5274
- * @module Runner
5275
- */
5276
5445
  /**
5277
5446
  * Module dependencies.
5278
5447
  */
5448
+ var util = require('util');
5279
5449
  var EventEmitter = require('events').EventEmitter;
5280
5450
  var Pending = require('./pending');
5281
5451
  var utils = require('./utils');
5282
5452
  var inherits = utils.inherits;
5283
5453
  var debug = require('debug')('mocha:runner');
5284
5454
  var Runnable = require('./runnable');
5285
- var createStatsCollector = require('./stats-collector');
5455
+ var Suite = require('./suite');
5456
+ var HOOK_TYPE_BEFORE_EACH = Suite.constants.HOOK_TYPE_BEFORE_EACH;
5457
+ var HOOK_TYPE_AFTER_EACH = Suite.constants.HOOK_TYPE_AFTER_EACH;
5458
+ var HOOK_TYPE_AFTER_ALL = Suite.constants.HOOK_TYPE_AFTER_ALL;
5459
+ var HOOK_TYPE_BEFORE_ALL = Suite.constants.HOOK_TYPE_BEFORE_ALL;
5460
+ var EVENT_ROOT_SUITE_RUN = Suite.constants.EVENT_ROOT_SUITE_RUN;
5461
+ var STATE_FAILED = Runnable.constants.STATE_FAILED;
5462
+ var STATE_PASSED = Runnable.constants.STATE_PASSED;
5463
+ var dQuote = utils.dQuote;
5464
+ var ngettext = utils.ngettext;
5465
+ var sQuote = utils.sQuote;
5286
5466
  var stackFilter = utils.stackTraceFilter();
5287
5467
  var stringify = utils.stringify;
5288
5468
  var type = utils.type;
5289
- var undefinedError = utils.undefinedError;
5469
+ var createInvalidExceptionError = require('./errors')
5470
+ .createInvalidExceptionError;
5290
5471
 
5291
5472
  /**
5292
5473
  * Non-enumerable globals.
5474
+ * @readonly
5293
5475
  */
5294
-
5295
5476
  var globals = [
5296
5477
  'setTimeout',
5297
5478
  'clearTimeout',
@@ -5303,33 +5484,85 @@ var globals = [
5303
5484
  'clearImmediate'
5304
5485
  ];
5305
5486
 
5306
- /**
5307
- * Expose `Runner`.
5308
- */
5487
+ var constants = utils.defineConstants(
5488
+ /**
5489
+ * {@link Runner}-related constants.
5490
+ * @public
5491
+ * @memberof Runner
5492
+ * @readonly
5493
+ * @alias constants
5494
+ * @static
5495
+ * @enum {string}
5496
+ */
5497
+ {
5498
+ /**
5499
+ * Emitted when {@link Hook} execution begins
5500
+ */
5501
+ EVENT_HOOK_BEGIN: 'hook',
5502
+ /**
5503
+ * Emitted when {@link Hook} execution ends
5504
+ */
5505
+ EVENT_HOOK_END: 'hook end',
5506
+ /**
5507
+ * Emitted when Root {@link Suite} execution begins (all files have been parsed and hooks/tests are ready for execution)
5508
+ */
5509
+ EVENT_RUN_BEGIN: 'start',
5510
+ /**
5511
+ * Emitted when Root {@link Suite} execution has been delayed via `delay` option
5512
+ */
5513
+ EVENT_DELAY_BEGIN: 'waiting',
5514
+ /**
5515
+ * Emitted when delayed Root {@link Suite} execution is triggered by user via `global.run()`
5516
+ */
5517
+ EVENT_DELAY_END: 'ready',
5518
+ /**
5519
+ * Emitted when Root {@link Suite} execution ends
5520
+ */
5521
+ EVENT_RUN_END: 'end',
5522
+ /**
5523
+ * Emitted when {@link Suite} execution begins
5524
+ */
5525
+ EVENT_SUITE_BEGIN: 'suite',
5526
+ /**
5527
+ * Emitted when {@link Suite} execution ends
5528
+ */
5529
+ EVENT_SUITE_END: 'suite end',
5530
+ /**
5531
+ * Emitted when {@link Test} execution begins
5532
+ */
5533
+ EVENT_TEST_BEGIN: 'test',
5534
+ /**
5535
+ * Emitted when {@link Test} execution ends
5536
+ */
5537
+ EVENT_TEST_END: 'test end',
5538
+ /**
5539
+ * Emitted when {@link Test} execution fails
5540
+ */
5541
+ EVENT_TEST_FAIL: 'fail',
5542
+ /**
5543
+ * Emitted when {@link Test} execution succeeds
5544
+ */
5545
+ EVENT_TEST_PASS: 'pass',
5546
+ /**
5547
+ * Emitted when {@link Test} becomes pending
5548
+ */
5549
+ EVENT_TEST_PENDING: 'pending',
5550
+ /**
5551
+ * Emitted when {@link Test} execution has failed, but will retry
5552
+ */
5553
+ EVENT_TEST_RETRY: 'retry'
5554
+ }
5555
+ );
5309
5556
 
5310
5557
  module.exports = Runner;
5311
5558
 
5312
5559
  /**
5313
- * Initialize a `Runner` for the given `suite`. Derived from [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
5314
- *
5315
- * Events:
5560
+ * Initialize a `Runner` at the Root {@link Suite}, which represents a hierarchy of {@link Suite|Suites} and {@link Test|Tests}.
5316
5561
  *
5317
- * - `start` execution started
5318
- * - `end` execution complete
5319
- * - `suite` (suite) test suite execution started
5320
- * - `suite end` (suite) all tests (and sub-suites) have finished
5321
- * - `test` (test) test execution started
5322
- * - `test end` (test) test completed
5323
- * - `hook` (hook) hook execution started
5324
- * - `hook end` (hook) hook complete
5325
- * - `pass` (test) test passed
5326
- * - `fail` (test, err) test failed
5327
- * - `pending` (test) test pending
5328
- *
5329
- * @memberof Mocha
5562
+ * @extends external:EventEmitter
5330
5563
  * @public
5331
5564
  * @class
5332
- * @param {Suite} [suite] Root suite
5565
+ * @param {Suite} suite Root suite
5333
5566
  * @param {boolean} [delay] Whether or not to delay execution of root suite
5334
5567
  * until ready.
5335
5568
  */
@@ -5342,16 +5575,15 @@ function Runner(suite, delay) {
5342
5575
  this.started = false;
5343
5576
  this.total = suite.total();
5344
5577
  this.failures = 0;
5345
- this.on('test end', function(test) {
5578
+ this.on(constants.EVENT_TEST_END, function(test) {
5346
5579
  self.checkGlobals(test);
5347
5580
  });
5348
- this.on('hook end', function(hook) {
5581
+ this.on(constants.EVENT_HOOK_END, function(hook) {
5349
5582
  self.checkGlobals(hook);
5350
5583
  });
5351
5584
  this._defaultGrep = /.*/;
5352
5585
  this.grep(this._defaultGrep);
5353
5586
  this.globals(this.globalProps().concat(extraGlobals()));
5354
- createStatsCollector(this);
5355
5587
  }
5356
5588
 
5357
5589
  /**
@@ -5372,7 +5604,7 @@ inherits(Runner, EventEmitter);
5372
5604
  * with number of tests matched.
5373
5605
  *
5374
5606
  * @public
5375
- * @memberof Mocha.Runner
5607
+ * @memberof Runner
5376
5608
  * @param {RegExp} re
5377
5609
  * @param {boolean} invert
5378
5610
  * @return {Runner} Runner instance.
@@ -5389,7 +5621,7 @@ Runner.prototype.grep = function(re, invert) {
5389
5621
  * Returns the number of tests matching the grep search for the
5390
5622
  * given suite.
5391
5623
  *
5392
- * @memberof Mocha.Runner
5624
+ * @memberof Runner
5393
5625
  * @public
5394
5626
  * @param {Suite} suite
5395
5627
  * @return {number}
@@ -5435,7 +5667,7 @@ Runner.prototype.globalProps = function() {
5435
5667
  * Allow the given `arr` of globals.
5436
5668
  *
5437
5669
  * @public
5438
- * @memberof Mocha.Runner
5670
+ * @memberof Runner
5439
5671
  * @param {Array} arr
5440
5672
  * @return {Runner} Runner instance.
5441
5673
  */
@@ -5474,13 +5706,14 @@ Runner.prototype.checkGlobals = function(test) {
5474
5706
  leaks = filterLeaks(ok, globals);
5475
5707
  this._globals = this._globals.concat(leaks);
5476
5708
 
5477
- if (leaks.length > 1) {
5478
- this.fail(
5479
- test,
5480
- new Error('global leaks detected: ' + leaks.join(', ') + '')
5709
+ if (leaks.length) {
5710
+ var format = ngettext(
5711
+ leaks.length,
5712
+ 'global leak detected: %s',
5713
+ 'global leaks detected: %s'
5481
5714
  );
5482
- } else if (leaks.length) {
5483
- this.fail(test, new Error('global leak detected: ' + leaks[0]));
5715
+ var error = new Error(util.format(format, leaks.map(sQuote).join(', ')));
5716
+ this.fail(test, error);
5484
5717
  }
5485
5718
  };
5486
5719
 
@@ -5497,7 +5730,7 @@ Runner.prototype.fail = function(test, err) {
5497
5730
  }
5498
5731
 
5499
5732
  ++this.failures;
5500
- test.state = 'failed';
5733
+ test.state = STATE_FAILED;
5501
5734
 
5502
5735
  if (!isError(err)) {
5503
5736
  err = thrown2Error(err);
@@ -5510,7 +5743,7 @@ Runner.prototype.fail = function(test, err) {
5510
5743
  // some environments do not take kindly to monkeying with the stack
5511
5744
  }
5512
5745
 
5513
- this.emit('fail', test, err);
5746
+ this.emit(constants.EVENT_TEST_FAIL, test, err);
5514
5747
  };
5515
5748
 
5516
5749
  /**
@@ -5535,10 +5768,18 @@ Runner.prototype.fail = function(test, err) {
5535
5768
  * @param {Error} err
5536
5769
  */
5537
5770
  Runner.prototype.failHook = function(hook, err) {
5771
+ hook.originalTitle = hook.originalTitle || hook.title;
5538
5772
  if (hook.ctx && hook.ctx.currentTest) {
5539
- hook.originalTitle = hook.originalTitle || hook.title;
5540
5773
  hook.title =
5541
- hook.originalTitle + ' for "' + hook.ctx.currentTest.title + '"';
5774
+ hook.originalTitle + ' for ' + dQuote(hook.ctx.currentTest.title);
5775
+ } else {
5776
+ var parentTitle;
5777
+ if (hook.parent.title) {
5778
+ parentTitle = hook.parent.title;
5779
+ } else {
5780
+ parentTitle = hook.parent.root ? '{root}' : '';
5781
+ }
5782
+ hook.title = hook.originalTitle + ' in ' + dQuote(parentTitle);
5542
5783
  }
5543
5784
 
5544
5785
  this.fail(hook, err);
@@ -5554,7 +5795,7 @@ Runner.prototype.failHook = function(hook, err) {
5554
5795
 
5555
5796
  Runner.prototype.hook = function(name, fn) {
5556
5797
  var suite = this.suite;
5557
- var hooks = suite['_' + name];
5798
+ var hooks = suite.getHooks(name);
5558
5799
  var self = this;
5559
5800
 
5560
5801
  function next(i) {
@@ -5564,9 +5805,15 @@ Runner.prototype.hook = function(name, fn) {
5564
5805
  }
5565
5806
  self.currentRunnable = hook;
5566
5807
 
5567
- hook.ctx.currentTest = self.test;
5808
+ if (name === 'beforeAll') {
5809
+ hook.ctx.currentTest = hook.parent.tests[0];
5810
+ } else if (name === 'afterAll') {
5811
+ hook.ctx.currentTest = hook.parent.tests[hook.parent.tests.length - 1];
5812
+ } else {
5813
+ hook.ctx.currentTest = self.test;
5814
+ }
5568
5815
 
5569
- self.emit('hook', hook);
5816
+ self.emit(constants.EVENT_HOOK_BEGIN, hook);
5570
5817
 
5571
5818
  if (!hook.listeners('error').length) {
5572
5819
  hook.on('error', function(err) {
@@ -5581,7 +5828,7 @@ Runner.prototype.hook = function(name, fn) {
5581
5828
  }
5582
5829
  if (err) {
5583
5830
  if (err instanceof Pending) {
5584
- if (name === 'beforeEach' || name === 'afterEach') {
5831
+ if (name === HOOK_TYPE_BEFORE_EACH || name === HOOK_TYPE_AFTER_EACH) {
5585
5832
  self.test.pending = true;
5586
5833
  } else {
5587
5834
  suite.tests.forEach(function(test) {
@@ -5600,7 +5847,7 @@ Runner.prototype.hook = function(name, fn) {
5600
5847
  return fn(err);
5601
5848
  }
5602
5849
  }
5603
- self.emit('hook end', hook);
5850
+ self.emit(constants.EVENT_HOOK_END, hook);
5604
5851
  delete hook.ctx.currentTest;
5605
5852
  next(++i);
5606
5853
  });
@@ -5700,7 +5947,9 @@ Runner.prototype.runTest = function(fn) {
5700
5947
  if (!test) {
5701
5948
  return;
5702
5949
  }
5703
- if (this.forbidOnly && hasOnly(this.parents().reverse()[0] || this.suite)) {
5950
+
5951
+ var suite = this.parents().reverse()[0] || this.suite;
5952
+ if (this.forbidOnly && suite.hasOnly()) {
5704
5953
  fn(new Error('`.only` forbidden'));
5705
5954
  return;
5706
5955
  }
@@ -5743,7 +5992,7 @@ Runner.prototype.runTests = function(suite, fn) {
5743
5992
 
5744
5993
  if (self.suite) {
5745
5994
  // call hookUp afterEach
5746
- self.hookUp('afterEach', function(err2, errSuite2) {
5995
+ self.hookUp(HOOK_TYPE_AFTER_EACH, function(err2, errSuite2) {
5747
5996
  self.suite = orig;
5748
5997
  // some hooks may fail even now
5749
5998
  if (err2) {
@@ -5809,24 +6058,24 @@ Runner.prototype.runTests = function(suite, fn) {
5809
6058
  self.fail(test, new Error('Pending test forbidden'));
5810
6059
  delete test.isPending;
5811
6060
  } else {
5812
- self.emit('pending', test);
6061
+ self.emit(constants.EVENT_TEST_PENDING, test);
5813
6062
  }
5814
- self.emit('test end', test);
6063
+ self.emit(constants.EVENT_TEST_END, test);
5815
6064
  return next();
5816
6065
  }
5817
6066
 
5818
6067
  // execute test and hook(s)
5819
- self.emit('test', (self.test = test));
5820
- self.hookDown('beforeEach', function(err, errSuite) {
6068
+ self.emit(constants.EVENT_TEST_BEGIN, (self.test = test));
6069
+ self.hookDown(HOOK_TYPE_BEFORE_EACH, function(err, errSuite) {
5821
6070
  if (test.isPending()) {
5822
6071
  if (self.forbidPending) {
5823
6072
  test.isPending = alwaysFalse;
5824
6073
  self.fail(test, new Error('Pending test forbidden'));
5825
6074
  delete test.isPending;
5826
6075
  } else {
5827
- self.emit('pending', test);
6076
+ self.emit(constants.EVENT_TEST_PENDING, test);
5828
6077
  }
5829
- self.emit('test end', test);
6078
+ self.emit(constants.EVENT_TEST_END, test);
5830
6079
  return next();
5831
6080
  }
5832
6081
  if (err) {
@@ -5841,33 +6090,33 @@ Runner.prototype.runTests = function(suite, fn) {
5841
6090
  self.fail(test, new Error('Pending test forbidden'));
5842
6091
  } else if (err instanceof Pending) {
5843
6092
  test.pending = true;
5844
- self.emit('pending', test);
6093
+ self.emit(constants.EVENT_TEST_PENDING, test);
5845
6094
  } else if (retry < test.retries()) {
5846
6095
  var clonedTest = test.clone();
5847
6096
  clonedTest.currentRetry(retry + 1);
5848
6097
  tests.unshift(clonedTest);
5849
6098
 
5850
- self.emit('retry', test, err);
6099
+ self.emit(constants.EVENT_TEST_RETRY, test, err);
5851
6100
 
5852
6101
  // Early return + hook trigger so that it doesn't
5853
6102
  // increment the count wrong
5854
- return self.hookUp('afterEach', next);
6103
+ return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
5855
6104
  } else {
5856
6105
  self.fail(test, err);
5857
6106
  }
5858
- self.emit('test end', test);
6107
+ self.emit(constants.EVENT_TEST_END, test);
5859
6108
 
5860
6109
  if (err instanceof Pending) {
5861
6110
  return next();
5862
6111
  }
5863
6112
 
5864
- return self.hookUp('afterEach', next);
6113
+ return self.hookUp(HOOK_TYPE_AFTER_EACH, next);
5865
6114
  }
5866
6115
 
5867
- test.state = 'passed';
5868
- self.emit('pass', test);
5869
- self.emit('test end', test);
5870
- self.hookUp('afterEach', next);
6116
+ test.state = STATE_PASSED;
6117
+ self.emit(constants.EVENT_TEST_PASS, test);
6118
+ self.emit(constants.EVENT_TEST_END, test);
6119
+ self.hookUp(HOOK_TYPE_AFTER_EACH, next);
5871
6120
  });
5872
6121
  });
5873
6122
  }
@@ -5900,7 +6149,7 @@ Runner.prototype.runSuite = function(suite, fn) {
5900
6149
  return fn();
5901
6150
  }
5902
6151
 
5903
- this.emit('suite', (this.suite = suite));
6152
+ this.emit(constants.EVENT_SUITE_BEGIN, (this.suite = suite));
5904
6153
 
5905
6154
  function next(errSuite) {
5906
6155
  if (errSuite) {
@@ -5950,8 +6199,8 @@ Runner.prototype.runSuite = function(suite, fn) {
5950
6199
  // remove reference to test
5951
6200
  delete self.test;
5952
6201
 
5953
- self.hook('afterAll', function() {
5954
- self.emit('suite end', suite);
6202
+ self.hook(HOOK_TYPE_AFTER_ALL, function() {
6203
+ self.emit(constants.EVENT_SUITE_END, suite);
5955
6204
  fn(errSuite);
5956
6205
  });
5957
6206
  }
@@ -5959,7 +6208,7 @@ Runner.prototype.runSuite = function(suite, fn) {
5959
6208
 
5960
6209
  this.nextSuite = next;
5961
6210
 
5962
- this.hook('beforeAll', function(err) {
6211
+ this.hook(HOOK_TYPE_BEFORE_ALL, function(err) {
5963
6212
  if (err) {
5964
6213
  return done();
5965
6214
  }
@@ -5975,18 +6224,13 @@ Runner.prototype.runSuite = function(suite, fn) {
5975
6224
  */
5976
6225
  Runner.prototype.uncaught = function(err) {
5977
6226
  if (err) {
5978
- debug(
5979
- 'uncaught exception %s',
5980
- err ===
5981
- function() {
5982
- return this;
5983
- }.call(err)
5984
- ? err.message || err
5985
- : err
5986
- );
6227
+ debug('uncaught exception %O', err);
5987
6228
  } else {
5988
- debug('uncaught undefined exception');
5989
- err = undefinedError();
6229
+ debug('uncaught undefined/falsy exception');
6230
+ err = createInvalidExceptionError(
6231
+ 'Caught falsy/undefined exception which would otherwise be uncaught. No stack trace found; try a debugger',
6232
+ err
6233
+ );
5990
6234
  }
5991
6235
 
5992
6236
  if (!isError(err)) {
@@ -6004,9 +6248,9 @@ Runner.prototype.uncaught = function(err) {
6004
6248
  this.fail(runnable, err);
6005
6249
  } else {
6006
6250
  // Can't recover from this failure
6007
- this.emit('start');
6251
+ this.emit(constants.EVENT_RUN_BEGIN);
6008
6252
  this.fail(runnable, err);
6009
- this.emit('end');
6253
+ this.emit(constants.EVENT_RUN_END);
6010
6254
  }
6011
6255
 
6012
6256
  return;
@@ -6026,14 +6270,17 @@ Runner.prototype.uncaught = function(err) {
6026
6270
  this.fail(runnable, err);
6027
6271
  if (!alreadyPassed) {
6028
6272
  // recover from test
6029
- if (runnable.type === 'test') {
6030
- this.emit('test end', runnable);
6031
- this.hookUp('afterEach', this.next);
6273
+ if (runnable.type === constants.EVENT_TEST_BEGIN) {
6274
+ this.emit(constants.EVENT_TEST_END, runnable);
6275
+ this.hookUp(HOOK_TYPE_AFTER_EACH, this.next);
6032
6276
  return;
6033
6277
  }
6278
+ debug(runnable);
6034
6279
 
6035
6280
  // recover from hooks
6036
6281
  var errSuite = this.suite;
6282
+
6283
+ // XXX how about a less awful way to determine this?
6037
6284
  // if hook failure is in afterEach block
6038
6285
  if (runnable.fullTitle().indexOf('after each') > -1) {
6039
6286
  return this.hookErr(err, errSuite, true);
@@ -6047,53 +6294,15 @@ Runner.prototype.uncaught = function(err) {
6047
6294
  }
6048
6295
 
6049
6296
  // bail
6050
- this.emit('end');
6297
+ this.emit(constants.EVENT_RUN_END);
6051
6298
  };
6052
6299
 
6053
- /**
6054
- * Cleans up the references to all the deferred functions
6055
- * (before/after/beforeEach/afterEach) and tests of a Suite.
6056
- * These must be deleted otherwise a memory leak can happen,
6057
- * as those functions may reference variables from closures,
6058
- * thus those variables can never be garbage collected as long
6059
- * as the deferred functions exist.
6060
- *
6061
- * @param {Suite} suite
6062
- */
6063
- function cleanSuiteReferences(suite) {
6064
- function cleanArrReferences(arr) {
6065
- for (var i = 0; i < arr.length; i++) {
6066
- delete arr[i].fn;
6067
- }
6068
- }
6069
-
6070
- if (Array.isArray(suite._beforeAll)) {
6071
- cleanArrReferences(suite._beforeAll);
6072
- }
6073
-
6074
- if (Array.isArray(suite._beforeEach)) {
6075
- cleanArrReferences(suite._beforeEach);
6076
- }
6077
-
6078
- if (Array.isArray(suite._afterAll)) {
6079
- cleanArrReferences(suite._afterAll);
6080
- }
6081
-
6082
- if (Array.isArray(suite._afterEach)) {
6083
- cleanArrReferences(suite._afterEach);
6084
- }
6085
-
6086
- for (var i = 0; i < suite.tests.length; i++) {
6087
- delete suite.tests[i].fn;
6088
- }
6089
- }
6090
-
6091
6300
  /**
6092
6301
  * Run the root suite and invoke `fn(failures)`
6093
6302
  * on completion.
6094
6303
  *
6095
6304
  * @public
6096
- * @memberof Mocha.Runner
6305
+ * @memberof Runner
6097
6306
  * @param {Function} fn
6098
6307
  * @return {Runner} Runner instance.
6099
6308
  */
@@ -6109,30 +6318,31 @@ Runner.prototype.run = function(fn) {
6109
6318
 
6110
6319
  function start() {
6111
6320
  // If there is an `only` filter
6112
- if (hasOnly(rootSuite)) {
6113
- filterOnly(rootSuite);
6321
+ if (rootSuite.hasOnly()) {
6322
+ rootSuite.filterOnly();
6114
6323
  }
6115
6324
  self.started = true;
6116
- Runner.immediately(function() {
6117
- self.emit('start');
6118
- });
6325
+ if (self._delay) {
6326
+ self.emit(constants.EVENT_DELAY_END);
6327
+ }
6328
+ self.emit(constants.EVENT_RUN_BEGIN);
6119
6329
 
6120
6330
  self.runSuite(rootSuite, function() {
6121
6331
  debug('finished running');
6122
- Runner.immediately(function() {
6123
- self.emit('end');
6124
- });
6332
+ self.emit(constants.EVENT_RUN_END);
6125
6333
  });
6126
6334
  }
6127
6335
 
6128
- debug('start');
6336
+ debug(constants.EVENT_RUN_BEGIN);
6129
6337
 
6130
6338
  // references cleanup to avoid memory leaks
6131
- this.on('suite end', cleanSuiteReferences);
6339
+ this.on(constants.EVENT_SUITE_END, function(suite) {
6340
+ suite.cleanReferences();
6341
+ });
6132
6342
 
6133
6343
  // callback
6134
- this.on('end', function() {
6135
- debug('end');
6344
+ this.on(constants.EVENT_RUN_END, function() {
6345
+ debug(constants.EVENT_RUN_END);
6136
6346
  process.removeListener('uncaughtException', uncaught);
6137
6347
  fn(self.failures);
6138
6348
  });
@@ -6143,8 +6353,8 @@ Runner.prototype.run = function(fn) {
6143
6353
  if (this._delay) {
6144
6354
  // for reporters, I guess.
6145
6355
  // might be nice to debounce some dots while we wait.
6146
- this.emit('waiting', rootSuite);
6147
- rootSuite.once('run', start);
6356
+ this.emit(constants.EVENT_DELAY_BEGIN, rootSuite);
6357
+ rootSuite.once(EVENT_ROOT_SUITE_RUN, start);
6148
6358
  } else {
6149
6359
  start();
6150
6360
  }
@@ -6155,7 +6365,7 @@ Runner.prototype.run = function(fn) {
6155
6365
  /**
6156
6366
  * Cleanly abort execution.
6157
6367
  *
6158
- * @memberof Mocha.Runner
6368
+ * @memberof Runner
6159
6369
  * @public
6160
6370
  * @return {Runner} Runner instance.
6161
6371
  */
@@ -6166,54 +6376,6 @@ Runner.prototype.abort = function() {
6166
6376
  return this;
6167
6377
  };
6168
6378
 
6169
- /**
6170
- * Filter suites based on `isOnly` logic.
6171
- *
6172
- * @param {Array} suite
6173
- * @returns {Boolean}
6174
- * @private
6175
- */
6176
- function filterOnly(suite) {
6177
- if (suite._onlyTests.length) {
6178
- // If the suite contains `only` tests, run those and ignore any nested suites.
6179
- suite.tests = suite._onlyTests;
6180
- suite.suites = [];
6181
- } else {
6182
- // Otherwise, do not run any of the tests in this suite.
6183
- suite.tests = [];
6184
- suite._onlySuites.forEach(function(onlySuite) {
6185
- // If there are other `only` tests/suites nested in the current `only` suite, then filter that `only` suite.
6186
- // Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
6187
- if (hasOnly(onlySuite)) {
6188
- filterOnly(onlySuite);
6189
- }
6190
- });
6191
- // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
6192
- suite.suites = suite.suites.filter(function(childSuite) {
6193
- return (
6194
- suite._onlySuites.indexOf(childSuite) !== -1 || filterOnly(childSuite)
6195
- );
6196
- });
6197
- }
6198
- // Keep the suite only if there is something to run
6199
- return suite.tests.length || suite.suites.length;
6200
- }
6201
-
6202
- /**
6203
- * Determines whether a suite has an `only` test or suite as a descendant.
6204
- *
6205
- * @param {Array} suite
6206
- * @returns {Boolean}
6207
- * @private
6208
- */
6209
- function hasOnly(suite) {
6210
- return (
6211
- suite._onlyTests.length ||
6212
- suite._onlySuites.length ||
6213
- suite.suites.some(hasOnly)
6214
- );
6215
- }
6216
-
6217
6379
  /**
6218
6380
  * Filter leaks with the given globals flagged as `ok`.
6219
6381
  *
@@ -6287,6 +6449,8 @@ function thrown2Error(err) {
6287
6449
  * Array of globals dependent on the environment.
6288
6450
  *
6289
6451
  * @return {Array}
6452
+ * @deprecated
6453
+ * @todo remove; long since unsupported
6290
6454
  * @private
6291
6455
  */
6292
6456
  function extraGlobals() {
@@ -6297,7 +6461,6 @@ function extraGlobals() {
6297
6461
  });
6298
6462
 
6299
6463
  // 'errno' was renamed to process._errno in v0.9.11.
6300
-
6301
6464
  if (nodeVersion < 0x00090b) {
6302
6465
  return ['errno'];
6303
6466
  }
@@ -6306,21 +6469,37 @@ function extraGlobals() {
6306
6469
  return [];
6307
6470
  }
6308
6471
 
6472
+ Runner.constants = constants;
6473
+
6474
+ /**
6475
+ * Node.js' `EventEmitter`
6476
+ * @external EventEmitter
6477
+ * @see {@link https://nodejs.org/api/events.html#events_class_eventemitter}
6478
+ */
6479
+
6309
6480
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
6310
- },{"./pending":16,"./runnable":33,"./stats-collector":35,"./utils":38,"_process":68,"debug":45,"events":50}],35:[function(require,module,exports){
6481
+ },{"./errors":6,"./pending":16,"./runnable":33,"./suite":36,"./utils":38,"_process":68,"debug":45,"events":50,"util":88}],35:[function(require,module,exports){
6311
6482
  (function (global){
6312
6483
  'use strict';
6313
6484
 
6314
6485
  /**
6315
6486
  * Provides a factory function for a {@link StatsCollector} object.
6316
- * @private
6317
6487
  * @module
6318
6488
  */
6319
6489
 
6490
+ var constants = require('./runner').constants;
6491
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
6492
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
6493
+ var EVENT_SUITE_BEGIN = constants.EVENT_SUITE_BEGIN;
6494
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
6495
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
6496
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
6497
+ var EVENT_TEST_END = constants.EVENT_TEST_END;
6498
+
6320
6499
  /**
6321
6500
  * Test statistics collector.
6322
6501
  *
6323
- * @private
6502
+ * @public
6324
6503
  * @typedef {Object} StatsCollector
6325
6504
  * @property {number} suites - integer count of suites run.
6326
6505
  * @property {number} tests - integer count of tests run.
@@ -6359,31 +6538,25 @@ function createStatsCollector(runner) {
6359
6538
 
6360
6539
  runner.stats = stats;
6361
6540
 
6362
- runner.once('start', function() {
6541
+ runner.once(EVENT_RUN_BEGIN, function() {
6363
6542
  stats.start = new Date();
6364
6543
  });
6365
-
6366
- runner.on('suite', function(suite) {
6544
+ runner.on(EVENT_SUITE_BEGIN, function(suite) {
6367
6545
  suite.root || stats.suites++;
6368
6546
  });
6369
-
6370
- runner.on('pass', function() {
6547
+ runner.on(EVENT_TEST_PASS, function() {
6371
6548
  stats.passes++;
6372
6549
  });
6373
-
6374
- runner.on('fail', function() {
6550
+ runner.on(EVENT_TEST_FAIL, function() {
6375
6551
  stats.failures++;
6376
6552
  });
6377
-
6378
- runner.on('pending', function() {
6553
+ runner.on(EVENT_TEST_PENDING, function() {
6379
6554
  stats.pending++;
6380
6555
  });
6381
-
6382
- runner.on('test end', function() {
6556
+ runner.on(EVENT_TEST_END, function() {
6383
6557
  stats.tests++;
6384
6558
  });
6385
-
6386
- runner.once('end', function() {
6559
+ runner.once(EVENT_RUN_END, function() {
6387
6560
  stats.end = new Date();
6388
6561
  stats.duration = stats.end - stats.start;
6389
6562
  });
@@ -6392,11 +6565,8 @@ function createStatsCollector(runner) {
6392
6565
  module.exports = createStatsCollector;
6393
6566
 
6394
6567
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
6395
- },{}],36:[function(require,module,exports){
6568
+ },{"./runner":34}],36:[function(require,module,exports){
6396
6569
  'use strict';
6397
- /**
6398
- * @module Suite
6399
- */
6400
6570
 
6401
6571
  /**
6402
6572
  * Module dependencies.
@@ -6417,17 +6587,14 @@ var createInvalidArgumentTypeError = errors.createInvalidArgumentTypeError;
6417
6587
  exports = module.exports = Suite;
6418
6588
 
6419
6589
  /**
6420
- * Create a new `Suite` with the given `title` and parent `Suite`. When a suite
6421
- * with the same title is already present, that suite is returned to provide
6422
- * nicer reporter and more flexible meta-testing.
6590
+ * Create a new `Suite` with the given `title` and parent `Suite`.
6423
6591
  *
6424
- * @memberof Mocha
6425
6592
  * @public
6426
- * @param {Suite} parent
6427
- * @param {string} title
6593
+ * @param {Suite} parent - Parent suite (required!)
6594
+ * @param {string} title - Title
6428
6595
  * @return {Suite}
6429
6596
  */
6430
- exports.create = function(parent, title) {
6597
+ Suite.create = function(parent, title) {
6431
6598
  var suite = new Suite(title, parent.ctx);
6432
6599
  suite.parent = parent;
6433
6600
  title = suite.fullTitle();
@@ -6436,15 +6603,17 @@ exports.create = function(parent, title) {
6436
6603
  };
6437
6604
 
6438
6605
  /**
6439
- * Initialize a new `Suite` with the given `title` and `ctx`. Derived from [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
6606
+ * Constructs a new `Suite` instance with the given `title`, `ctx`, and `isRoot`.
6440
6607
  *
6441
- * @memberof Mocha
6442
6608
  * @public
6443
6609
  * @class
6444
- * @param {string} title
6445
- * @param {Context} parentContext
6610
+ * @extends EventEmitter
6611
+ * @see {@link https://nodejs.org/api/events.html#events_class_eventemitter|EventEmitter}
6612
+ * @param {string} title - Suite title.
6613
+ * @param {Context} parentContext - Parent context instance.
6614
+ * @param {boolean} [isRoot=false] - Whether this is the root suite.
6446
6615
  */
6447
- function Suite(title, parentContext) {
6616
+ function Suite(title, parentContext, isRoot) {
6448
6617
  if (!utils.isString(title)) {
6449
6618
  throw createInvalidArgumentTypeError(
6450
6619
  'Suite argument "title" must be a string. Received type "' +
@@ -6465,7 +6634,7 @@ function Suite(title, parentContext) {
6465
6634
  this._beforeAll = [];
6466
6635
  this._afterEach = [];
6467
6636
  this._afterAll = [];
6468
- this.root = !title;
6637
+ this.root = isRoot === true;
6469
6638
  this._timeout = 2000;
6470
6639
  this._enableTimeouts = true;
6471
6640
  this._slow = 75;
@@ -6474,6 +6643,16 @@ function Suite(title, parentContext) {
6474
6643
  this._onlyTests = [];
6475
6644
  this._onlySuites = [];
6476
6645
  this.delayed = false;
6646
+
6647
+ this.on('newListener', function(event) {
6648
+ if (deprecatedEvents[event]) {
6649
+ utils.deprecate(
6650
+ 'Event "' +
6651
+ event +
6652
+ '" is deprecated. Please let the Mocha team know about your use case: https://git.io/v6Lwm'
6653
+ );
6654
+ }
6655
+ });
6477
6656
  }
6478
6657
 
6479
6658
  /**
@@ -6636,7 +6815,7 @@ Suite.prototype.beforeAll = function(title, fn) {
6636
6815
 
6637
6816
  var hook = this._createHook(title, fn);
6638
6817
  this._beforeAll.push(hook);
6639
- this.emit('beforeAll', hook);
6818
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_ALL, hook);
6640
6819
  return this;
6641
6820
  };
6642
6821
 
@@ -6660,7 +6839,7 @@ Suite.prototype.afterAll = function(title, fn) {
6660
6839
 
6661
6840
  var hook = this._createHook(title, fn);
6662
6841
  this._afterAll.push(hook);
6663
- this.emit('afterAll', hook);
6842
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_ALL, hook);
6664
6843
  return this;
6665
6844
  };
6666
6845
 
@@ -6684,7 +6863,7 @@ Suite.prototype.beforeEach = function(title, fn) {
6684
6863
 
6685
6864
  var hook = this._createHook(title, fn);
6686
6865
  this._beforeEach.push(hook);
6687
- this.emit('beforeEach', hook);
6866
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_EACH, hook);
6688
6867
  return this;
6689
6868
  };
6690
6869
 
@@ -6708,7 +6887,7 @@ Suite.prototype.afterEach = function(title, fn) {
6708
6887
 
6709
6888
  var hook = this._createHook(title, fn);
6710
6889
  this._afterEach.push(hook);
6711
- this.emit('afterEach', hook);
6890
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_EACH, hook);
6712
6891
  return this;
6713
6892
  };
6714
6893
 
@@ -6721,13 +6900,14 @@ Suite.prototype.afterEach = function(title, fn) {
6721
6900
  */
6722
6901
  Suite.prototype.addSuite = function(suite) {
6723
6902
  suite.parent = this;
6903
+ suite.root = false;
6724
6904
  suite.timeout(this.timeout());
6725
6905
  suite.retries(this.retries());
6726
6906
  suite.enableTimeouts(this.enableTimeouts());
6727
6907
  suite.slow(this.slow());
6728
6908
  suite.bail(this.bail());
6729
6909
  this.suites.push(suite);
6730
- this.emit('suite', suite);
6910
+ this.emit(constants.EVENT_SUITE_ADD_SUITE, suite);
6731
6911
  return this;
6732
6912
  };
6733
6913
 
@@ -6746,7 +6926,7 @@ Suite.prototype.addTest = function(test) {
6746
6926
  test.slow(this.slow());
6747
6927
  test.ctx = this.ctx;
6748
6928
  this.tests.push(test);
6749
- this.emit('test', test);
6929
+ this.emit(constants.EVENT_SUITE_ADD_TEST, test);
6750
6930
  return this;
6751
6931
  };
6752
6932
 
@@ -6754,7 +6934,7 @@ Suite.prototype.addTest = function(test) {
6754
6934
  * Return the full title generated by recursively concatenating the parent's
6755
6935
  * full title.
6756
6936
  *
6757
- * @memberof Mocha.Suite
6937
+ * @memberof Suite
6758
6938
  * @public
6759
6939
  * @return {string}
6760
6940
  */
@@ -6766,7 +6946,7 @@ Suite.prototype.fullTitle = function() {
6766
6946
  * Return the title path generated by recursively concatenating the parent's
6767
6947
  * title path.
6768
6948
  *
6769
- * @memberof Mocha.Suite
6949
+ * @memberof Suite
6770
6950
  * @public
6771
6951
  * @return {string}
6772
6952
  */
@@ -6784,7 +6964,7 @@ Suite.prototype.titlePath = function() {
6784
6964
  /**
6785
6965
  * Return the total number of tests.
6786
6966
  *
6787
- * @memberof Mocha.Suite
6967
+ * @memberof Suite
6788
6968
  * @public
6789
6969
  * @return {number}
6790
6970
  */
@@ -6814,13 +6994,219 @@ Suite.prototype.eachTest = function(fn) {
6814
6994
 
6815
6995
  /**
6816
6996
  * This will run the root suite if we happen to be running in delayed mode.
6997
+ * @private
6817
6998
  */
6818
6999
  Suite.prototype.run = function run() {
6819
7000
  if (this.root) {
6820
- this.emit('run');
7001
+ this.emit(constants.EVENT_ROOT_SUITE_RUN);
6821
7002
  }
6822
7003
  };
6823
7004
 
7005
+ /**
7006
+ * Determines whether a suite has an `only` test or suite as a descendant.
7007
+ *
7008
+ * @private
7009
+ * @returns {Boolean}
7010
+ */
7011
+ Suite.prototype.hasOnly = function hasOnly() {
7012
+ return (
7013
+ this._onlyTests.length > 0 ||
7014
+ this._onlySuites.length > 0 ||
7015
+ this.suites.some(function(suite) {
7016
+ return suite.hasOnly();
7017
+ })
7018
+ );
7019
+ };
7020
+
7021
+ /**
7022
+ * Filter suites based on `isOnly` logic.
7023
+ *
7024
+ * @private
7025
+ * @returns {Boolean}
7026
+ */
7027
+ Suite.prototype.filterOnly = function filterOnly() {
7028
+ if (this._onlyTests.length) {
7029
+ // If the suite contains `only` tests, run those and ignore any nested suites.
7030
+ this.tests = this._onlyTests;
7031
+ this.suites = [];
7032
+ } else {
7033
+ // Otherwise, do not run any of the tests in this suite.
7034
+ this.tests = [];
7035
+ this._onlySuites.forEach(function(onlySuite) {
7036
+ // If there are other `only` tests/suites nested in the current `only` suite, then filter that `only` suite.
7037
+ // Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
7038
+ if (onlySuite.hasOnly()) {
7039
+ onlySuite.filterOnly();
7040
+ }
7041
+ });
7042
+ // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
7043
+ var onlySuites = this._onlySuites;
7044
+ this.suites = this.suites.filter(function(childSuite) {
7045
+ return onlySuites.indexOf(childSuite) !== -1 || childSuite.filterOnly();
7046
+ });
7047
+ }
7048
+ // Keep the suite only if there is something to run
7049
+ return this.tests.length > 0 || this.suites.length > 0;
7050
+ };
7051
+
7052
+ /**
7053
+ * Adds a suite to the list of subsuites marked `only`.
7054
+ *
7055
+ * @private
7056
+ * @param {Suite} suite
7057
+ */
7058
+ Suite.prototype.appendOnlySuite = function(suite) {
7059
+ this._onlySuites.push(suite);
7060
+ };
7061
+
7062
+ /**
7063
+ * Adds a test to the list of tests marked `only`.
7064
+ *
7065
+ * @private
7066
+ * @param {Test} test
7067
+ */
7068
+ Suite.prototype.appendOnlyTest = function(test) {
7069
+ this._onlyTests.push(test);
7070
+ };
7071
+
7072
+ /**
7073
+ * Returns the array of hooks by hook name; see `HOOK_TYPE_*` constants.
7074
+ * @private
7075
+ */
7076
+ Suite.prototype.getHooks = function getHooks(name) {
7077
+ return this['_' + name];
7078
+ };
7079
+
7080
+ /**
7081
+ * Cleans up the references to all the deferred functions
7082
+ * (before/after/beforeEach/afterEach) and tests of a Suite.
7083
+ * These must be deleted otherwise a memory leak can happen,
7084
+ * as those functions may reference variables from closures,
7085
+ * thus those variables can never be garbage collected as long
7086
+ * as the deferred functions exist.
7087
+ *
7088
+ * @private
7089
+ */
7090
+ Suite.prototype.cleanReferences = function cleanReferences() {
7091
+ function cleanArrReferences(arr) {
7092
+ for (var i = 0; i < arr.length; i++) {
7093
+ delete arr[i].fn;
7094
+ }
7095
+ }
7096
+
7097
+ if (Array.isArray(this._beforeAll)) {
7098
+ cleanArrReferences(this._beforeAll);
7099
+ }
7100
+
7101
+ if (Array.isArray(this._beforeEach)) {
7102
+ cleanArrReferences(this._beforeEach);
7103
+ }
7104
+
7105
+ if (Array.isArray(this._afterAll)) {
7106
+ cleanArrReferences(this._afterAll);
7107
+ }
7108
+
7109
+ if (Array.isArray(this._afterEach)) {
7110
+ cleanArrReferences(this._afterEach);
7111
+ }
7112
+
7113
+ for (var i = 0; i < this.tests.length; i++) {
7114
+ delete this.tests[i].fn;
7115
+ }
7116
+ };
7117
+
7118
+ var constants = utils.defineConstants(
7119
+ /**
7120
+ * {@link Suite}-related constants.
7121
+ * @public
7122
+ * @memberof Suite
7123
+ * @alias constants
7124
+ * @readonly
7125
+ * @static
7126
+ * @enum {string}
7127
+ */
7128
+ {
7129
+ /**
7130
+ * Event emitted after a test file has been loaded Not emitted in browser.
7131
+ */
7132
+ EVENT_FILE_POST_REQUIRE: 'post-require',
7133
+ /**
7134
+ * Event emitted before a test file has been loaded. In browser, this is emitted once an interface has been selected.
7135
+ */
7136
+ EVENT_FILE_PRE_REQUIRE: 'pre-require',
7137
+ /**
7138
+ * Event emitted immediately after a test file has been loaded. Not emitted in browser.
7139
+ */
7140
+ EVENT_FILE_REQUIRE: 'require',
7141
+ /**
7142
+ * Event emitted when `global.run()` is called (use with `delay` option)
7143
+ */
7144
+ EVENT_ROOT_SUITE_RUN: 'run',
7145
+
7146
+ /**
7147
+ * Namespace for collection of a `Suite`'s "after all" hooks
7148
+ */
7149
+ HOOK_TYPE_AFTER_ALL: 'afterAll',
7150
+ /**
7151
+ * Namespace for collection of a `Suite`'s "after each" hooks
7152
+ */
7153
+ HOOK_TYPE_AFTER_EACH: 'afterEach',
7154
+ /**
7155
+ * Namespace for collection of a `Suite`'s "before all" hooks
7156
+ */
7157
+ HOOK_TYPE_BEFORE_ALL: 'beforeAll',
7158
+ /**
7159
+ * Namespace for collection of a `Suite`'s "before all" hooks
7160
+ */
7161
+ HOOK_TYPE_BEFORE_EACH: 'beforeEach',
7162
+
7163
+ // the following events are all deprecated
7164
+
7165
+ /**
7166
+ * Emitted after an "after all" `Hook` has been added to a `Suite`. Deprecated
7167
+ */
7168
+ EVENT_SUITE_ADD_HOOK_AFTER_ALL: 'afterAll',
7169
+ /**
7170
+ * Emitted after an "after each" `Hook` has been added to a `Suite` Deprecated
7171
+ */
7172
+ EVENT_SUITE_ADD_HOOK_AFTER_EACH: 'afterEach',
7173
+ /**
7174
+ * Emitted after an "before all" `Hook` has been added to a `Suite` Deprecated
7175
+ */
7176
+ EVENT_SUITE_ADD_HOOK_BEFORE_ALL: 'beforeAll',
7177
+ /**
7178
+ * Emitted after an "before each" `Hook` has been added to a `Suite` Deprecated
7179
+ */
7180
+ EVENT_SUITE_ADD_HOOK_BEFORE_EACH: 'beforeEach',
7181
+ /**
7182
+ * Emitted after a child `Suite` has been added to a `Suite`. Deprecated
7183
+ */
7184
+ EVENT_SUITE_ADD_SUITE: 'suite',
7185
+ /**
7186
+ * Emitted after a `Test` has been added to a `Suite`. Deprecated
7187
+ */
7188
+ EVENT_SUITE_ADD_TEST: 'test'
7189
+ }
7190
+ );
7191
+
7192
+ /**
7193
+ * @summary There are no known use cases for these events.
7194
+ * @desc This is a `Set`-like object having all keys being the constant's string value and the value being `true`.
7195
+ * @todo Remove eventually
7196
+ * @type {Object<string,boolean>}
7197
+ * @ignore
7198
+ */
7199
+ var deprecatedEvents = Object.keys(constants)
7200
+ .filter(function(constant) {
7201
+ return constant.substring(0, 15) === 'EVENT_SUITE_ADD';
7202
+ })
7203
+ .reduce(function(acc, constant) {
7204
+ acc[constants[constant]] = true;
7205
+ return acc;
7206
+ }, utils.createMap());
7207
+
7208
+ Suite.constants = constants;
7209
+
6824
7210
  },{"./errors":6,"./hook":7,"./utils":38,"debug":45,"events":50,"ms":60}],37:[function(require,module,exports){
6825
7211
  'use strict';
6826
7212
  var Runnable = require('./runnable');
@@ -6834,10 +7220,11 @@ module.exports = Test;
6834
7220
  /**
6835
7221
  * Initialize a new `Test` with the given `title` and callback `fn`.
6836
7222
  *
7223
+ * @public
6837
7224
  * @class
6838
7225
  * @extends Runnable
6839
- * @param {String} title
6840
- * @param {Function} fn
7226
+ * @param {String} title - Test title (required)
7227
+ * @param {Function} [fn] - Test callback. If omitted, the Test is considered "pending"
6841
7228
  */
6842
7229
  function Test(title, fn) {
6843
7230
  if (!isString(title)) {
@@ -6878,31 +7265,35 @@ Test.prototype.clone = function() {
6878
7265
  'use strict';
6879
7266
 
6880
7267
  /**
6881
- * @module
7268
+ * Various utility functions used throughout Mocha's codebase.
7269
+ * @module utils
6882
7270
  */
6883
7271
 
6884
7272
  /**
6885
7273
  * Module dependencies.
6886
7274
  */
6887
7275
 
6888
- var debug = require('debug')('mocha:watch');
6889
7276
  var fs = require('fs');
6890
- var glob = require('glob');
6891
7277
  var path = require('path');
6892
- var join = path.join;
7278
+ var util = require('util');
7279
+ var glob = require('glob');
6893
7280
  var he = require('he');
6894
7281
  var errors = require('./errors');
6895
7282
  var createNoFilesMatchPatternError = errors.createNoFilesMatchPatternError;
6896
7283
  var createMissingArgumentError = errors.createMissingArgumentError;
6897
- var createUndefinedError = errors.createUndefinedError;
7284
+
7285
+ var assign = (exports.assign = require('object.assign').getPolyfill());
6898
7286
 
6899
7287
  /**
6900
- * Ignored directories.
7288
+ * Inherit the prototype methods from one constructor into another.
7289
+ *
7290
+ * @param {function} ctor - Constructor function which needs to inherit the
7291
+ * prototype.
7292
+ * @param {function} superCtor - Constructor function to inherit prototype from.
7293
+ * @throws {TypeError} if either constructor is null, or if super constructor
7294
+ * lacks a prototype.
6901
7295
  */
6902
-
6903
- var ignore = ['node_modules', '.git'];
6904
-
6905
- exports.inherits = require('util').inherits;
7296
+ exports.inherits = util.inherits;
6906
7297
 
6907
7298
  /**
6908
7299
  * Escape special characters in the given string of html.
@@ -6936,6 +7327,7 @@ exports.isString = function(obj) {
6936
7327
  */
6937
7328
  exports.watch = function(files, fn) {
6938
7329
  var options = {interval: 100};
7330
+ var debug = require('debug')('mocha:watch');
6939
7331
  files.forEach(function(file) {
6940
7332
  debug('file %s', file);
6941
7333
  fs.watchFile(file, options, function(curr, prev) {
@@ -6947,39 +7339,52 @@ exports.watch = function(files, fn) {
6947
7339
  };
6948
7340
 
6949
7341
  /**
6950
- * Ignored files.
7342
+ * Predicate to screen `pathname` for further consideration.
7343
+ *
7344
+ * @description
7345
+ * Returns <code>false</code> for pathname referencing:
7346
+ * <ul>
7347
+ * <li>'npm' package installation directory
7348
+ * <li>'git' version control directory
7349
+ * </ul>
6951
7350
  *
6952
7351
  * @private
6953
- * @param {string} path
6954
- * @return {boolean}
7352
+ * @param {string} pathname - File or directory name to screen
7353
+ * @return {boolean} whether pathname should be further considered
7354
+ * @example
7355
+ * ['node_modules', 'test.js'].filter(considerFurther); // => ['test.js']
6955
7356
  */
6956
- function ignored(path) {
6957
- return !~ignore.indexOf(path);
7357
+ function considerFurther(pathname) {
7358
+ var ignore = ['node_modules', '.git'];
7359
+
7360
+ return !~ignore.indexOf(pathname);
6958
7361
  }
6959
7362
 
6960
7363
  /**
6961
7364
  * Lookup files in the given `dir`.
6962
7365
  *
7366
+ * @description
7367
+ * Filenames are returned in _traversal_ order by the OS/filesystem.
7368
+ * **Make no assumption that the names will be sorted in any fashion.**
7369
+ *
6963
7370
  * @private
6964
7371
  * @param {string} dir
6965
- * @param {string[]} [ext=['.js']]
7372
+ * @param {string[]} [exts=['js']]
6966
7373
  * @param {Array} [ret=[]]
6967
7374
  * @return {Array}
6968
7375
  */
6969
- exports.files = function(dir, ext, ret) {
7376
+ exports.files = function(dir, exts, ret) {
6970
7377
  ret = ret || [];
6971
- ext = ext || ['js'];
6972
-
6973
- var re = new RegExp('\\.(' + ext.join('|') + ')$');
7378
+ exts = exts || ['js'];
6974
7379
 
6975
7380
  fs.readdirSync(dir)
6976
- .filter(ignored)
6977
- .forEach(function(path) {
6978
- path = join(dir, path);
6979
- if (fs.lstatSync(path).isDirectory()) {
6980
- exports.files(path, ext, ret);
6981
- } else if (path.match(re)) {
6982
- ret.push(path);
7381
+ .filter(considerFurther)
7382
+ .forEach(function(dirent) {
7383
+ var pathname = path.join(dir, dirent);
7384
+ if (fs.lstatSync(pathname).isDirectory()) {
7385
+ exports.files(pathname, exts, ret);
7386
+ } else if (hasMatchingExtname(pathname, exts)) {
7387
+ ret.push(pathname);
6983
7388
  }
6984
7389
  });
6985
7390
 
@@ -7376,28 +7781,72 @@ exports.canonicalize = function canonicalize(value, stack, typeHint) {
7376
7781
  return canonicalizedObj;
7377
7782
  };
7378
7783
 
7784
+ /**
7785
+ * Determines if pathname has a matching file extension.
7786
+ *
7787
+ * @private
7788
+ * @param {string} pathname - Pathname to check for match.
7789
+ * @param {string[]} exts - List of file extensions (sans period).
7790
+ * @return {boolean} whether file extension matches.
7791
+ * @example
7792
+ * hasMatchingExtname('foo.html', ['js', 'css']); // => false
7793
+ */
7794
+ function hasMatchingExtname(pathname, exts) {
7795
+ var suffix = path.extname(pathname).slice(1);
7796
+ return exts.some(function(element) {
7797
+ return suffix === element;
7798
+ });
7799
+ }
7800
+
7801
+ /**
7802
+ * Determines if pathname would be a "hidden" file (or directory) on UN*X.
7803
+ *
7804
+ * @description
7805
+ * On UN*X, pathnames beginning with a full stop (aka dot) are hidden during
7806
+ * typical usage. Dotfiles, plain-text configuration files, are prime examples.
7807
+ *
7808
+ * @see {@link http://xahlee.info/UnixResource_dir/writ/unix_origin_of_dot_filename.html|Origin of Dot File Names}
7809
+ *
7810
+ * @private
7811
+ * @param {string} pathname - Pathname to check for match.
7812
+ * @return {boolean} whether pathname would be considered a hidden file.
7813
+ * @example
7814
+ * isHiddenOnUnix('.profile'); // => true
7815
+ */
7816
+ function isHiddenOnUnix(pathname) {
7817
+ return path.basename(pathname)[0] === '.';
7818
+ }
7819
+
7379
7820
  /**
7380
7821
  * Lookup file names at the given `path`.
7381
7822
  *
7382
- * @memberof Mocha.utils
7823
+ * @description
7824
+ * Filenames are returned in _traversal_ order by the OS/filesystem.
7825
+ * **Make no assumption that the names will be sorted in any fashion.**
7826
+ *
7383
7827
  * @public
7384
- * @param {string} filepath Base path to start searching from.
7385
- * @param {string[]} extensions File extensions to look for.
7386
- * @param {boolean} recursive Whether or not to recurse into subdirectories.
7828
+ * @memberof Mocha.utils
7387
7829
  * @todo Fix extension handling
7830
+ * @param {string} filepath - Base path to start searching from.
7831
+ * @param {string[]} extensions - File extensions to look for.
7832
+ * @param {boolean} recursive - Whether to recurse into subdirectories.
7388
7833
  * @return {string[]} An array of paths.
7834
+ * @throws {Error} if no files match pattern.
7835
+ * @throws {TypeError} if `filepath` is directory and `extensions` not provided.
7389
7836
  */
7390
7837
  exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) {
7391
7838
  var files = [];
7839
+ var stat;
7392
7840
 
7393
7841
  if (!fs.existsSync(filepath)) {
7394
7842
  if (fs.existsSync(filepath + '.js')) {
7395
7843
  filepath += '.js';
7396
7844
  } else {
7845
+ // Handle glob
7397
7846
  files = glob.sync(filepath);
7398
7847
  if (!files.length) {
7399
7848
  throw createNoFilesMatchPatternError(
7400
- 'cannot find any files matching pattern "' + filepath + '"',
7849
+ 'Cannot find any files matching pattern ' + exports.dQuote(filepath),
7401
7850
  filepath
7402
7851
  );
7403
7852
  }
@@ -7405,8 +7854,9 @@ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) {
7405
7854
  }
7406
7855
  }
7407
7856
 
7857
+ // Handle file
7408
7858
  try {
7409
- var stat = fs.statSync(filepath);
7859
+ stat = fs.statSync(filepath);
7410
7860
  if (stat.isFile()) {
7411
7861
  return filepath;
7412
7862
  }
@@ -7415,13 +7865,16 @@ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) {
7415
7865
  return;
7416
7866
  }
7417
7867
 
7418
- fs.readdirSync(filepath).forEach(function(file) {
7419
- file = path.join(filepath, file);
7868
+ // Handle directory
7869
+ fs.readdirSync(filepath).forEach(function(dirent) {
7870
+ var pathname = path.join(filepath, dirent);
7871
+ var stat;
7872
+
7420
7873
  try {
7421
- var stat = fs.statSync(file);
7874
+ stat = fs.statSync(pathname);
7422
7875
  if (stat.isDirectory()) {
7423
7876
  if (recursive) {
7424
- files = files.concat(lookupFiles(file, extensions, recursive));
7877
+ files = files.concat(lookupFiles(pathname, extensions, recursive));
7425
7878
  }
7426
7879
  return;
7427
7880
  }
@@ -7431,64 +7884,73 @@ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) {
7431
7884
  }
7432
7885
  if (!extensions) {
7433
7886
  throw createMissingArgumentError(
7434
- 'Argument "extensions" required when argument "filepath" is a directory',
7887
+ util.format(
7888
+ 'Argument %s required when argument %s is a directory',
7889
+ exports.sQuote('extensions'),
7890
+ exports.sQuote('filepath')
7891
+ ),
7435
7892
  'extensions',
7436
7893
  'array'
7437
7894
  );
7438
7895
  }
7439
- var re = new RegExp('\\.(?:' + extensions.join('|') + ')$');
7440
- if (!stat.isFile() || !re.test(file) || path.basename(file)[0] === '.') {
7896
+
7897
+ if (
7898
+ !stat.isFile() ||
7899
+ !hasMatchingExtname(pathname, extensions) ||
7900
+ isHiddenOnUnix(pathname)
7901
+ ) {
7441
7902
  return;
7442
7903
  }
7443
- files.push(file);
7904
+ files.push(pathname);
7444
7905
  });
7445
7906
 
7446
7907
  return files;
7447
7908
  };
7448
7909
 
7449
7910
  /**
7450
- * Generate an undefined error with a message warning the user.
7451
- *
7452
- * @return {Error}
7911
+ * process.emitWarning or a polyfill
7912
+ * @see https://nodejs.org/api/process.html#process_process_emitwarning_warning_options
7913
+ * @ignore
7453
7914
  */
7454
-
7455
- exports.undefinedError = function() {
7456
- return createUndefinedError(
7457
- 'Caught undefined error, did you throw without specifying what?'
7458
- );
7459
- };
7460
-
7461
- /**
7462
- * Generate an undefined error if `err` is not defined.
7463
- *
7464
- * @param {Error} err
7465
- * @return {Error}
7466
- */
7467
-
7468
- exports.getError = function(err) {
7469
- return err || exports.undefinedError();
7470
- };
7915
+ function emitWarning(msg, type) {
7916
+ if (process.emitWarning) {
7917
+ process.emitWarning(msg, type);
7918
+ } else {
7919
+ process.nextTick(function() {
7920
+ console.warn(type + ': ' + msg);
7921
+ });
7922
+ }
7923
+ }
7471
7924
 
7472
7925
  /**
7473
7926
  * Show a deprecation warning. Each distinct message is only displayed once.
7927
+ * Ignores empty messages.
7474
7928
  *
7475
- * @param {string} msg
7929
+ * @param {string} [msg] - Warning to print
7930
+ * @private
7476
7931
  */
7477
7932
  exports.deprecate = function deprecate(msg) {
7478
7933
  msg = String(msg);
7479
7934
  if (msg && !deprecate.cache[msg]) {
7480
7935
  deprecate.cache[msg] = true;
7481
- if (process.emitWarning) {
7482
- process.emitWarning(msg, 'DeprecationWarning');
7483
- } else {
7484
- process.nextTick(function() {
7485
- console.warn(msg);
7486
- });
7487
- }
7936
+ emitWarning(msg, 'DeprecationWarning');
7488
7937
  }
7489
7938
  };
7490
7939
  exports.deprecate.cache = {};
7491
7940
 
7941
+ /**
7942
+ * Show a generic warning.
7943
+ * Ignores empty messages.
7944
+ *
7945
+ * @param {string} [msg] - Warning to print
7946
+ * @private
7947
+ */
7948
+ exports.warn = function warn(msg) {
7949
+ if (msg) {
7950
+ emitWarning(msg);
7951
+ }
7952
+ };
7953
+
7492
7954
  /**
7493
7955
  * @summary
7494
7956
  * This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`)
@@ -7516,8 +7978,6 @@ exports.stackTraceFilter = function() {
7516
7978
  function isMochaInternal(line) {
7517
7979
  return (
7518
7980
  ~line.indexOf('node_modules' + slash + 'mocha' + slash) ||
7519
- ~line.indexOf('node_modules' + slash + 'mocha.js') ||
7520
- ~line.indexOf('bower_components' + slash + 'mocha.js') ||
7521
7981
  ~line.indexOf(slash + 'mocha.js')
7522
7982
  );
7523
7983
  }
@@ -7546,7 +8006,7 @@ exports.stackTraceFilter = function() {
7546
8006
  }
7547
8007
 
7548
8008
  // Clean up cwd(absolute)
7549
- if (/\(?.+:\d+:\d+\)?$/.test(line)) {
8009
+ if (/:\d+:\d+\)?$/.test(line)) {
7550
8010
  line = line.replace('(' + cwd, '(');
7551
8011
  }
7552
8012
 
@@ -7583,14 +8043,125 @@ exports.clamp = function clamp(value, range) {
7583
8043
  return Math.min(Math.max(value, range[0]), range[1]);
7584
8044
  };
7585
8045
 
8046
+ /**
8047
+ * Single quote text by combining with undirectional ASCII quotation marks.
8048
+ *
8049
+ * @description
8050
+ * Provides a simple means of markup for quoting text to be used in output.
8051
+ * Use this to quote names of variables, methods, and packages.
8052
+ *
8053
+ * <samp>package 'foo' cannot be found</samp>
8054
+ *
8055
+ * @private
8056
+ * @param {string} str - Value to be quoted.
8057
+ * @returns {string} quoted value
8058
+ * @example
8059
+ * sQuote('n') // => 'n'
8060
+ */
8061
+ exports.sQuote = function(str) {
8062
+ return "'" + str + "'";
8063
+ };
8064
+
8065
+ /**
8066
+ * Double quote text by combining with undirectional ASCII quotation marks.
8067
+ *
8068
+ * @description
8069
+ * Provides a simple means of markup for quoting text to be used in output.
8070
+ * Use this to quote names of datatypes, classes, pathnames, and strings.
8071
+ *
8072
+ * <samp>argument 'value' must be "string" or "number"</samp>
8073
+ *
8074
+ * @private
8075
+ * @param {string} str - Value to be quoted.
8076
+ * @returns {string} quoted value
8077
+ * @example
8078
+ * dQuote('number') // => "number"
8079
+ */
8080
+ exports.dQuote = function(str) {
8081
+ return '"' + str + '"';
8082
+ };
8083
+
8084
+ /**
8085
+ * Provides simplistic message translation for dealing with plurality.
8086
+ *
8087
+ * @description
8088
+ * Use this to create messages which need to be singular or plural.
8089
+ * Some languages have several plural forms, so _complete_ message clauses
8090
+ * are preferable to generating the message on the fly.
8091
+ *
8092
+ * @private
8093
+ * @param {number} n - Non-negative integer
8094
+ * @param {string} msg1 - Message to be used in English for `n = 1`
8095
+ * @param {string} msg2 - Message to be used in English for `n = 0, 2, 3, ...`
8096
+ * @returns {string} message corresponding to value of `n`
8097
+ * @example
8098
+ * var sprintf = require('util').format;
8099
+ * var pkgs = ['one', 'two'];
8100
+ * var msg = sprintf(
8101
+ * ngettext(
8102
+ * pkgs.length,
8103
+ * 'cannot load package: %s',
8104
+ * 'cannot load packages: %s'
8105
+ * ),
8106
+ * pkgs.map(sQuote).join(', ')
8107
+ * );
8108
+ * console.log(msg); // => cannot load packages: 'one', 'two'
8109
+ */
8110
+ exports.ngettext = function(n, msg1, msg2) {
8111
+ if (typeof n === 'number' && n >= 0) {
8112
+ return n === 1 ? msg1 : msg2;
8113
+ }
8114
+ };
8115
+
7586
8116
  /**
7587
8117
  * It's a noop.
7588
8118
  * @public
7589
8119
  */
7590
8120
  exports.noop = function() {};
7591
8121
 
8122
+ /**
8123
+ * Creates a map-like object.
8124
+ *
8125
+ * @description
8126
+ * A "map" is an object with no prototype, for our purposes. In some cases
8127
+ * this would be more appropriate than a `Map`, especially if your environment
8128
+ * doesn't support it. Recommended for use in Mocha's public APIs.
8129
+ *
8130
+ * @public
8131
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map|MDN:Map}
8132
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Custom_and_Null_objects|MDN:Object.create - Custom objects}
8133
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign|MDN:Object.assign}
8134
+ * @param {...*} [obj] - Arguments to `Object.assign()`.
8135
+ * @returns {Object} An object with no prototype, having `...obj` properties
8136
+ */
8137
+ exports.createMap = function(obj) {
8138
+ return assign.apply(
8139
+ null,
8140
+ [Object.create(null)].concat(Array.prototype.slice.call(arguments))
8141
+ );
8142
+ };
8143
+
8144
+ /**
8145
+ * Creates a read-only map-like object.
8146
+ *
8147
+ * @description
8148
+ * This differs from {@link module:utils.createMap createMap} only in that
8149
+ * the argument must be non-empty, because the result is frozen.
8150
+ *
8151
+ * @see {@link module:utils.createMap createMap}
8152
+ * @param {...*} [obj] - Arguments to `Object.assign()`.
8153
+ * @returns {Object} A frozen object with no prototype, having `...obj` properties
8154
+ * @throws {TypeError} if argument is not a non-empty object.
8155
+ */
8156
+ exports.defineConstants = function(obj) {
8157
+ if (type(obj) !== 'object' || !Object.keys(obj).length) {
8158
+ throw new TypeError('Invalid argument; expected a non-empty object');
8159
+ }
8160
+ return Object.freeze(exports.createMap(obj));
8161
+ };
8162
+
7592
8163
  }).call(this,require('_process'),require("buffer").Buffer)
7593
- },{"./errors":6,"_process":68,"buffer":43,"debug":45,"fs":42,"glob":42,"he":54,"path":42,"util":88}],39:[function(require,module,exports){
8164
+ },{"./errors":6,"_process":68,"buffer":43,"debug":45,"fs":42,"glob":42,"he":54,"object.assign":64,"path":42,"util":88}],39:[function(require,module,exports){
7594
8165
  'use strict'
7595
8166
 
7596
8167
  exports.byteLength = byteLength
@@ -17337,7 +17908,7 @@ function hasOwnProperty(obj, prop) {
17337
17908
  },{"./support/isBuffer":87,"_process":68,"inherits":86}],89:[function(require,module,exports){
17338
17909
  module.exports={
17339
17910
  "name": "mocha",
17340
- "version": "6.0.0-1",
17911
+ "version": "6.0.0",
17341
17912
  "homepage": "https://mochajs.org/",
17342
17913
  "notifyLogo": "https://ibin.co/4QuRuGjXvl36.png"
17343
17914
  }