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.
@@ -2,14 +2,22 @@
2
2
 
3
3
  /**
4
4
  * Provides a factory function for a {@link StatsCollector} object.
5
- * @private
6
5
  * @module
7
6
  */
8
7
 
8
+ var constants = require('./runner').constants;
9
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
10
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
11
+ var EVENT_SUITE_BEGIN = constants.EVENT_SUITE_BEGIN;
12
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
13
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
14
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
15
+ var EVENT_TEST_END = constants.EVENT_TEST_END;
16
+
9
17
  /**
10
18
  * Test statistics collector.
11
19
  *
12
- * @private
20
+ * @public
13
21
  * @typedef {Object} StatsCollector
14
22
  * @property {number} suites - integer count of suites run.
15
23
  * @property {number} tests - integer count of tests run.
@@ -48,31 +56,25 @@ function createStatsCollector(runner) {
48
56
 
49
57
  runner.stats = stats;
50
58
 
51
- runner.once('start', function() {
59
+ runner.once(EVENT_RUN_BEGIN, function() {
52
60
  stats.start = new Date();
53
61
  });
54
-
55
- runner.on('suite', function(suite) {
62
+ runner.on(EVENT_SUITE_BEGIN, function(suite) {
56
63
  suite.root || stats.suites++;
57
64
  });
58
-
59
- runner.on('pass', function() {
65
+ runner.on(EVENT_TEST_PASS, function() {
60
66
  stats.passes++;
61
67
  });
62
-
63
- runner.on('fail', function() {
68
+ runner.on(EVENT_TEST_FAIL, function() {
64
69
  stats.failures++;
65
70
  });
66
-
67
- runner.on('pending', function() {
71
+ runner.on(EVENT_TEST_PENDING, function() {
68
72
  stats.pending++;
69
73
  });
70
-
71
- runner.on('test end', function() {
74
+ runner.on(EVENT_TEST_END, function() {
72
75
  stats.tests++;
73
76
  });
74
-
75
- runner.once('end', function() {
77
+ runner.once(EVENT_RUN_END, function() {
76
78
  stats.end = new Date();
77
79
  stats.duration = stats.end - stats.start;
78
80
  });
package/lib/suite.js CHANGED
@@ -1,7 +1,4 @@
1
1
  'use strict';
2
- /**
3
- * @module Suite
4
- */
5
2
 
6
3
  /**
7
4
  * Module dependencies.
@@ -22,17 +19,14 @@ var createInvalidArgumentTypeError = errors.createInvalidArgumentTypeError;
22
19
  exports = module.exports = Suite;
23
20
 
24
21
  /**
25
- * Create a new `Suite` with the given `title` and parent `Suite`. When a suite
26
- * with the same title is already present, that suite is returned to provide
27
- * nicer reporter and more flexible meta-testing.
22
+ * Create a new `Suite` with the given `title` and parent `Suite`.
28
23
  *
29
- * @memberof Mocha
30
24
  * @public
31
- * @param {Suite} parent
32
- * @param {string} title
25
+ * @param {Suite} parent - Parent suite (required!)
26
+ * @param {string} title - Title
33
27
  * @return {Suite}
34
28
  */
35
- exports.create = function(parent, title) {
29
+ Suite.create = function(parent, title) {
36
30
  var suite = new Suite(title, parent.ctx);
37
31
  suite.parent = parent;
38
32
  title = suite.fullTitle();
@@ -41,15 +35,17 @@ exports.create = function(parent, title) {
41
35
  };
42
36
 
43
37
  /**
44
- * Initialize a new `Suite` with the given `title` and `ctx`. Derived from [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
38
+ * Constructs a new `Suite` instance with the given `title`, `ctx`, and `isRoot`.
45
39
  *
46
- * @memberof Mocha
47
40
  * @public
48
41
  * @class
49
- * @param {string} title
50
- * @param {Context} parentContext
42
+ * @extends EventEmitter
43
+ * @see {@link https://nodejs.org/api/events.html#events_class_eventemitter|EventEmitter}
44
+ * @param {string} title - Suite title.
45
+ * @param {Context} parentContext - Parent context instance.
46
+ * @param {boolean} [isRoot=false] - Whether this is the root suite.
51
47
  */
52
- function Suite(title, parentContext) {
48
+ function Suite(title, parentContext, isRoot) {
53
49
  if (!utils.isString(title)) {
54
50
  throw createInvalidArgumentTypeError(
55
51
  'Suite argument "title" must be a string. Received type "' +
@@ -70,7 +66,7 @@ function Suite(title, parentContext) {
70
66
  this._beforeAll = [];
71
67
  this._afterEach = [];
72
68
  this._afterAll = [];
73
- this.root = !title;
69
+ this.root = isRoot === true;
74
70
  this._timeout = 2000;
75
71
  this._enableTimeouts = true;
76
72
  this._slow = 75;
@@ -79,6 +75,16 @@ function Suite(title, parentContext) {
79
75
  this._onlyTests = [];
80
76
  this._onlySuites = [];
81
77
  this.delayed = false;
78
+
79
+ this.on('newListener', function(event) {
80
+ if (deprecatedEvents[event]) {
81
+ utils.deprecate(
82
+ 'Event "' +
83
+ event +
84
+ '" is deprecated. Please let the Mocha team know about your use case: https://git.io/v6Lwm'
85
+ );
86
+ }
87
+ });
82
88
  }
83
89
 
84
90
  /**
@@ -241,7 +247,7 @@ Suite.prototype.beforeAll = function(title, fn) {
241
247
 
242
248
  var hook = this._createHook(title, fn);
243
249
  this._beforeAll.push(hook);
244
- this.emit('beforeAll', hook);
250
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_ALL, hook);
245
251
  return this;
246
252
  };
247
253
 
@@ -265,7 +271,7 @@ Suite.prototype.afterAll = function(title, fn) {
265
271
 
266
272
  var hook = this._createHook(title, fn);
267
273
  this._afterAll.push(hook);
268
- this.emit('afterAll', hook);
274
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_ALL, hook);
269
275
  return this;
270
276
  };
271
277
 
@@ -289,7 +295,7 @@ Suite.prototype.beforeEach = function(title, fn) {
289
295
 
290
296
  var hook = this._createHook(title, fn);
291
297
  this._beforeEach.push(hook);
292
- this.emit('beforeEach', hook);
298
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_BEFORE_EACH, hook);
293
299
  return this;
294
300
  };
295
301
 
@@ -313,7 +319,7 @@ Suite.prototype.afterEach = function(title, fn) {
313
319
 
314
320
  var hook = this._createHook(title, fn);
315
321
  this._afterEach.push(hook);
316
- this.emit('afterEach', hook);
322
+ this.emit(constants.EVENT_SUITE_ADD_HOOK_AFTER_EACH, hook);
317
323
  return this;
318
324
  };
319
325
 
@@ -326,13 +332,14 @@ Suite.prototype.afterEach = function(title, fn) {
326
332
  */
327
333
  Suite.prototype.addSuite = function(suite) {
328
334
  suite.parent = this;
335
+ suite.root = false;
329
336
  suite.timeout(this.timeout());
330
337
  suite.retries(this.retries());
331
338
  suite.enableTimeouts(this.enableTimeouts());
332
339
  suite.slow(this.slow());
333
340
  suite.bail(this.bail());
334
341
  this.suites.push(suite);
335
- this.emit('suite', suite);
342
+ this.emit(constants.EVENT_SUITE_ADD_SUITE, suite);
336
343
  return this;
337
344
  };
338
345
 
@@ -351,7 +358,7 @@ Suite.prototype.addTest = function(test) {
351
358
  test.slow(this.slow());
352
359
  test.ctx = this.ctx;
353
360
  this.tests.push(test);
354
- this.emit('test', test);
361
+ this.emit(constants.EVENT_SUITE_ADD_TEST, test);
355
362
  return this;
356
363
  };
357
364
 
@@ -359,7 +366,7 @@ Suite.prototype.addTest = function(test) {
359
366
  * Return the full title generated by recursively concatenating the parent's
360
367
  * full title.
361
368
  *
362
- * @memberof Mocha.Suite
369
+ * @memberof Suite
363
370
  * @public
364
371
  * @return {string}
365
372
  */
@@ -371,7 +378,7 @@ Suite.prototype.fullTitle = function() {
371
378
  * Return the title path generated by recursively concatenating the parent's
372
379
  * title path.
373
380
  *
374
- * @memberof Mocha.Suite
381
+ * @memberof Suite
375
382
  * @public
376
383
  * @return {string}
377
384
  */
@@ -389,7 +396,7 @@ Suite.prototype.titlePath = function() {
389
396
  /**
390
397
  * Return the total number of tests.
391
398
  *
392
- * @memberof Mocha.Suite
399
+ * @memberof Suite
393
400
  * @public
394
401
  * @return {number}
395
402
  */
@@ -419,9 +426,215 @@ Suite.prototype.eachTest = function(fn) {
419
426
 
420
427
  /**
421
428
  * This will run the root suite if we happen to be running in delayed mode.
429
+ * @private
422
430
  */
423
431
  Suite.prototype.run = function run() {
424
432
  if (this.root) {
425
- this.emit('run');
433
+ this.emit(constants.EVENT_ROOT_SUITE_RUN);
434
+ }
435
+ };
436
+
437
+ /**
438
+ * Determines whether a suite has an `only` test or suite as a descendant.
439
+ *
440
+ * @private
441
+ * @returns {Boolean}
442
+ */
443
+ Suite.prototype.hasOnly = function hasOnly() {
444
+ return (
445
+ this._onlyTests.length > 0 ||
446
+ this._onlySuites.length > 0 ||
447
+ this.suites.some(function(suite) {
448
+ return suite.hasOnly();
449
+ })
450
+ );
451
+ };
452
+
453
+ /**
454
+ * Filter suites based on `isOnly` logic.
455
+ *
456
+ * @private
457
+ * @returns {Boolean}
458
+ */
459
+ Suite.prototype.filterOnly = function filterOnly() {
460
+ if (this._onlyTests.length) {
461
+ // If the suite contains `only` tests, run those and ignore any nested suites.
462
+ this.tests = this._onlyTests;
463
+ this.suites = [];
464
+ } else {
465
+ // Otherwise, do not run any of the tests in this suite.
466
+ this.tests = [];
467
+ this._onlySuites.forEach(function(onlySuite) {
468
+ // If there are other `only` tests/suites nested in the current `only` suite, then filter that `only` suite.
469
+ // Otherwise, all of the tests on this `only` suite should be run, so don't filter it.
470
+ if (onlySuite.hasOnly()) {
471
+ onlySuite.filterOnly();
472
+ }
473
+ });
474
+ // Run the `only` suites, as well as any other suites that have `only` tests/suites as descendants.
475
+ var onlySuites = this._onlySuites;
476
+ this.suites = this.suites.filter(function(childSuite) {
477
+ return onlySuites.indexOf(childSuite) !== -1 || childSuite.filterOnly();
478
+ });
426
479
  }
480
+ // Keep the suite only if there is something to run
481
+ return this.tests.length > 0 || this.suites.length > 0;
427
482
  };
483
+
484
+ /**
485
+ * Adds a suite to the list of subsuites marked `only`.
486
+ *
487
+ * @private
488
+ * @param {Suite} suite
489
+ */
490
+ Suite.prototype.appendOnlySuite = function(suite) {
491
+ this._onlySuites.push(suite);
492
+ };
493
+
494
+ /**
495
+ * Adds a test to the list of tests marked `only`.
496
+ *
497
+ * @private
498
+ * @param {Test} test
499
+ */
500
+ Suite.prototype.appendOnlyTest = function(test) {
501
+ this._onlyTests.push(test);
502
+ };
503
+
504
+ /**
505
+ * Returns the array of hooks by hook name; see `HOOK_TYPE_*` constants.
506
+ * @private
507
+ */
508
+ Suite.prototype.getHooks = function getHooks(name) {
509
+ return this['_' + name];
510
+ };
511
+
512
+ /**
513
+ * Cleans up the references to all the deferred functions
514
+ * (before/after/beforeEach/afterEach) and tests of a Suite.
515
+ * These must be deleted otherwise a memory leak can happen,
516
+ * as those functions may reference variables from closures,
517
+ * thus those variables can never be garbage collected as long
518
+ * as the deferred functions exist.
519
+ *
520
+ * @private
521
+ */
522
+ Suite.prototype.cleanReferences = function cleanReferences() {
523
+ function cleanArrReferences(arr) {
524
+ for (var i = 0; i < arr.length; i++) {
525
+ delete arr[i].fn;
526
+ }
527
+ }
528
+
529
+ if (Array.isArray(this._beforeAll)) {
530
+ cleanArrReferences(this._beforeAll);
531
+ }
532
+
533
+ if (Array.isArray(this._beforeEach)) {
534
+ cleanArrReferences(this._beforeEach);
535
+ }
536
+
537
+ if (Array.isArray(this._afterAll)) {
538
+ cleanArrReferences(this._afterAll);
539
+ }
540
+
541
+ if (Array.isArray(this._afterEach)) {
542
+ cleanArrReferences(this._afterEach);
543
+ }
544
+
545
+ for (var i = 0; i < this.tests.length; i++) {
546
+ delete this.tests[i].fn;
547
+ }
548
+ };
549
+
550
+ var constants = utils.defineConstants(
551
+ /**
552
+ * {@link Suite}-related constants.
553
+ * @public
554
+ * @memberof Suite
555
+ * @alias constants
556
+ * @readonly
557
+ * @static
558
+ * @enum {string}
559
+ */
560
+ {
561
+ /**
562
+ * Event emitted after a test file has been loaded Not emitted in browser.
563
+ */
564
+ EVENT_FILE_POST_REQUIRE: 'post-require',
565
+ /**
566
+ * Event emitted before a test file has been loaded. In browser, this is emitted once an interface has been selected.
567
+ */
568
+ EVENT_FILE_PRE_REQUIRE: 'pre-require',
569
+ /**
570
+ * Event emitted immediately after a test file has been loaded. Not emitted in browser.
571
+ */
572
+ EVENT_FILE_REQUIRE: 'require',
573
+ /**
574
+ * Event emitted when `global.run()` is called (use with `delay` option)
575
+ */
576
+ EVENT_ROOT_SUITE_RUN: 'run',
577
+
578
+ /**
579
+ * Namespace for collection of a `Suite`'s "after all" hooks
580
+ */
581
+ HOOK_TYPE_AFTER_ALL: 'afterAll',
582
+ /**
583
+ * Namespace for collection of a `Suite`'s "after each" hooks
584
+ */
585
+ HOOK_TYPE_AFTER_EACH: 'afterEach',
586
+ /**
587
+ * Namespace for collection of a `Suite`'s "before all" hooks
588
+ */
589
+ HOOK_TYPE_BEFORE_ALL: 'beforeAll',
590
+ /**
591
+ * Namespace for collection of a `Suite`'s "before all" hooks
592
+ */
593
+ HOOK_TYPE_BEFORE_EACH: 'beforeEach',
594
+
595
+ // the following events are all deprecated
596
+
597
+ /**
598
+ * Emitted after an "after all" `Hook` has been added to a `Suite`. Deprecated
599
+ */
600
+ EVENT_SUITE_ADD_HOOK_AFTER_ALL: 'afterAll',
601
+ /**
602
+ * Emitted after an "after each" `Hook` has been added to a `Suite` Deprecated
603
+ */
604
+ EVENT_SUITE_ADD_HOOK_AFTER_EACH: 'afterEach',
605
+ /**
606
+ * Emitted after an "before all" `Hook` has been added to a `Suite` Deprecated
607
+ */
608
+ EVENT_SUITE_ADD_HOOK_BEFORE_ALL: 'beforeAll',
609
+ /**
610
+ * Emitted after an "before each" `Hook` has been added to a `Suite` Deprecated
611
+ */
612
+ EVENT_SUITE_ADD_HOOK_BEFORE_EACH: 'beforeEach',
613
+ /**
614
+ * Emitted after a child `Suite` has been added to a `Suite`. Deprecated
615
+ */
616
+ EVENT_SUITE_ADD_SUITE: 'suite',
617
+ /**
618
+ * Emitted after a `Test` has been added to a `Suite`. Deprecated
619
+ */
620
+ EVENT_SUITE_ADD_TEST: 'test'
621
+ }
622
+ );
623
+
624
+ /**
625
+ * @summary There are no known use cases for these events.
626
+ * @desc This is a `Set`-like object having all keys being the constant's string value and the value being `true`.
627
+ * @todo Remove eventually
628
+ * @type {Object<string,boolean>}
629
+ * @ignore
630
+ */
631
+ var deprecatedEvents = Object.keys(constants)
632
+ .filter(function(constant) {
633
+ return constant.substring(0, 15) === 'EVENT_SUITE_ADD';
634
+ })
635
+ .reduce(function(acc, constant) {
636
+ acc[constants[constant]] = true;
637
+ return acc;
638
+ }, utils.createMap());
639
+
640
+ Suite.constants = constants;
package/lib/test.js CHANGED
@@ -10,10 +10,11 @@ module.exports = Test;
10
10
  /**
11
11
  * Initialize a new `Test` with the given `title` and callback `fn`.
12
12
  *
13
+ * @public
13
14
  * @class
14
15
  * @extends Runnable
15
- * @param {String} title
16
- * @param {Function} fn
16
+ * @param {String} title - Test title (required)
17
+ * @param {Function} [fn] - Test callback. If omitted, the Test is considered "pending"
17
18
  */
18
19
  function Test(title, fn) {
19
20
  if (!isString(title)) {