mocha 5.1.0 → 6.0.0-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +653 -981
  2. package/README.md +2 -1
  3. package/{images → assets/growl}/error.png +0 -0
  4. package/{images → assets/growl}/ok.png +0 -0
  5. package/bin/_mocha +4 -595
  6. package/bin/mocha +84 -58
  7. package/bin/options.js +6 -39
  8. package/browser-entry.js +21 -17
  9. package/lib/browser/growl.js +164 -2
  10. package/lib/browser/progress.js +11 -11
  11. package/lib/{template.html → browser/template.html} +0 -0
  12. package/lib/browser/tty.js +2 -2
  13. package/lib/cli/cli.js +68 -0
  14. package/lib/cli/commands.js +13 -0
  15. package/lib/cli/config.js +79 -0
  16. package/lib/cli/index.js +9 -0
  17. package/lib/cli/init.js +37 -0
  18. package/lib/cli/node-flags.js +48 -0
  19. package/lib/cli/one-and-dones.js +70 -0
  20. package/lib/cli/options.js +299 -0
  21. package/lib/cli/run-helpers.js +328 -0
  22. package/lib/cli/run-option-metadata.js +72 -0
  23. package/lib/cli/run.js +293 -0
  24. package/lib/context.js +14 -14
  25. package/lib/errors.js +139 -0
  26. package/lib/growl.js +135 -0
  27. package/lib/hook.js +5 -16
  28. package/lib/interfaces/bdd.js +14 -13
  29. package/lib/interfaces/common.js +59 -16
  30. package/lib/interfaces/exports.js +4 -7
  31. package/lib/interfaces/qunit.js +8 -10
  32. package/lib/interfaces/tdd.js +10 -11
  33. package/lib/mocha.js +442 -255
  34. package/lib/mocharc.json +10 -0
  35. package/lib/pending.js +1 -5
  36. package/lib/reporters/base.js +92 -117
  37. package/lib/reporters/doc.js +18 -9
  38. package/lib/reporters/dot.js +13 -13
  39. package/lib/reporters/html.js +76 -47
  40. package/lib/reporters/json-stream.js +38 -23
  41. package/lib/reporters/json.js +26 -23
  42. package/lib/reporters/landing.js +9 -8
  43. package/lib/reporters/list.js +11 -10
  44. package/lib/reporters/markdown.js +13 -12
  45. package/lib/reporters/min.js +4 -3
  46. package/lib/reporters/nyan.js +36 -35
  47. package/lib/reporters/progress.js +8 -7
  48. package/lib/reporters/spec.js +14 -11
  49. package/lib/reporters/tap.js +243 -32
  50. package/lib/reporters/xunit.js +52 -33
  51. package/lib/runnable.js +103 -90
  52. package/lib/runner.js +156 -107
  53. package/lib/stats-collector.js +81 -0
  54. package/lib/suite.js +57 -51
  55. package/lib/test.js +13 -13
  56. package/lib/utils.js +192 -103
  57. package/mocha.js +3836 -2046
  58. package/package.json +122 -38
  59. package/bin/.eslintrc.yml +0 -3
  60. package/lib/browser/.eslintrc.yml +0 -4
  61. package/lib/ms.js +0 -94
  62. package/lib/reporters/base.js.orig +0 -498
  63. package/lib/reporters/json.js.orig +0 -128
package/lib/context.js CHANGED
@@ -11,18 +11,18 @@ module.exports = Context;
11
11
  /**
12
12
  * Initialize a new `Context`.
13
13
  *
14
- * @api private
14
+ * @private
15
15
  */
16
- function Context () {}
16
+ function Context() {}
17
17
 
18
18
  /**
19
19
  * Set or get the context `Runnable` to `runnable`.
20
20
  *
21
- * @api private
21
+ * @private
22
22
  * @param {Runnable} runnable
23
23
  * @return {Context} context
24
24
  */
25
- Context.prototype.runnable = function (runnable) {
25
+ Context.prototype.runnable = function(runnable) {
26
26
  if (!arguments.length) {
27
27
  return this._runnable;
28
28
  }
@@ -33,11 +33,11 @@ Context.prototype.runnable = function (runnable) {
33
33
  /**
34
34
  * Set or get test timeout `ms`.
35
35
  *
36
- * @api private
36
+ * @private
37
37
  * @param {number} ms
38
38
  * @return {Context} self
39
39
  */
40
- Context.prototype.timeout = function (ms) {
40
+ Context.prototype.timeout = function(ms) {
41
41
  if (!arguments.length) {
42
42
  return this.runnable().timeout();
43
43
  }
@@ -48,11 +48,11 @@ Context.prototype.timeout = function (ms) {
48
48
  /**
49
49
  * Set test timeout `enabled`.
50
50
  *
51
- * @api private
51
+ * @private
52
52
  * @param {boolean} enabled
53
53
  * @return {Context} self
54
54
  */
55
- Context.prototype.enableTimeouts = function (enabled) {
55
+ Context.prototype.enableTimeouts = function(enabled) {
56
56
  if (!arguments.length) {
57
57
  return this.runnable().enableTimeouts();
58
58
  }
@@ -63,11 +63,11 @@ Context.prototype.enableTimeouts = function (enabled) {
63
63
  /**
64
64
  * Set or get test slowness threshold `ms`.
65
65
  *
66
- * @api private
66
+ * @private
67
67
  * @param {number} ms
68
68
  * @return {Context} self
69
69
  */
70
- Context.prototype.slow = function (ms) {
70
+ Context.prototype.slow = function(ms) {
71
71
  if (!arguments.length) {
72
72
  return this.runnable().slow();
73
73
  }
@@ -78,21 +78,21 @@ Context.prototype.slow = function (ms) {
78
78
  /**
79
79
  * Mark a test as skipped.
80
80
  *
81
- * @api private
81
+ * @private
82
82
  * @throws Pending
83
83
  */
84
- Context.prototype.skip = function () {
84
+ Context.prototype.skip = function() {
85
85
  this.runnable().skip();
86
86
  };
87
87
 
88
88
  /**
89
89
  * Set or get a number of allowed retries on failed tests
90
90
  *
91
- * @api private
91
+ * @private
92
92
  * @param {number} n
93
93
  * @return {Context} self
94
94
  */
95
- Context.prototype.retries = function (n) {
95
+ Context.prototype.retries = function(n) {
96
96
  if (!arguments.length) {
97
97
  return this.runnable().retries();
98
98
  }
package/lib/errors.js ADDED
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+ /**
3
+ * @module Errors
4
+ */
5
+ /**
6
+ * Factory functions to create throwable error objects
7
+ */
8
+
9
+ /**
10
+ * Creates an error object used when no files to be tested could be found using specified pattern.
11
+ *
12
+ * @public
13
+ * @param {string} message - Error message to be displayed.
14
+ * @param {string} pattern - User-specified argument value.
15
+ * @returns {Error} instance detailing the error condition
16
+ */
17
+ function createNoFilesMatchPatternError(message, pattern) {
18
+ var err = new Error(message);
19
+ err.code = 'ERR_MOCHA_NO_FILES_MATCH_PATTERN';
20
+ err.pattern = pattern;
21
+ return err;
22
+ }
23
+
24
+ /**
25
+ * Creates an error object used when the reporter specified in the options was not found.
26
+ *
27
+ * @public
28
+ * @param {string} message - Error message to be displayed.
29
+ * @param {string} reporter - User-specified reporter value.
30
+ * @returns {Error} instance detailing the error condition
31
+ */
32
+ function createInvalidReporterError(message, reporter) {
33
+ var err = new TypeError(message);
34
+ err.code = 'ERR_MOCHA_INVALID_REPORTER';
35
+ err.reporter = reporter;
36
+ return err;
37
+ }
38
+
39
+ /**
40
+ * Creates an error object used when the interface specified in the options was not found.
41
+ *
42
+ * @public
43
+ * @param {string} message - Error message to be displayed.
44
+ * @param {string} ui - User-specified interface value.
45
+ * @returns {Error} instance detailing the error condition
46
+ */
47
+ function createInvalidInterfaceError(message, ui) {
48
+ var err = new Error(message);
49
+ err.code = 'ERR_MOCHA_INVALID_INTERFACE';
50
+ err.interface = ui;
51
+ return err;
52
+ }
53
+
54
+ /**
55
+ * Creates an error object used when the type of output specified was not supported.
56
+ *
57
+ * @public
58
+ * @param {string} message - Error message to be displayed.
59
+ * @returns {Error} instance detailing the error condition
60
+ */
61
+ function createNotSupportedError(message) {
62
+ var err = new Error(message);
63
+ err.code = 'ERR_MOCHA_NOT_SUPPORTED';
64
+ return err;
65
+ }
66
+
67
+ /**
68
+ * Creates an error object used when an argument is missing.
69
+ *
70
+ * @public
71
+ * @param {string} message - Error message to be displayed.
72
+ * @param {string} argument - Argument name.
73
+ * @param {string} expected - Expected argument datatype.
74
+ * @returns {Error} instance detailing the error condition
75
+ */
76
+ function createMissingArgumentError(message, argument, expected) {
77
+ return createInvalidArgumentTypeError(message, argument, expected);
78
+ }
79
+
80
+ /**
81
+ * Creates an error object used when an argument did not use the supported type
82
+ *
83
+ * @public
84
+ * @param {string} message - Error message to be displayed.
85
+ * @param {string} argument - Argument name.
86
+ * @param {string} expected - Expected argument datatype.
87
+ * @returns {Error} instance detailing the error condition
88
+ */
89
+ function createInvalidArgumentTypeError(message, argument, expected) {
90
+ var err = new TypeError(message);
91
+ err.code = 'ERR_MOCHA_INVALID_ARG_TYPE';
92
+ err.argument = argument;
93
+ err.expected = expected;
94
+ err.actual = typeof argument;
95
+ return err;
96
+ }
97
+
98
+ /**
99
+ * Creates an error object used when an argument did not use the supported value
100
+ *
101
+ * @public
102
+ * @param {string} message - Error message to be displayed.
103
+ * @param {string} argument - Argument name.
104
+ * @param {string} value - Argument value.
105
+ * @param {string} [reason] - Why value is invalid.
106
+ * @returns {Error} instance detailing the error condition
107
+ */
108
+ function createInvalidArgumentValueError(message, argument, value, reason) {
109
+ var err = new TypeError(message);
110
+ err.code = 'ERR_MOCHA_INVALID_ARG_VALUE';
111
+ err.argument = argument;
112
+ err.value = value;
113
+ err.reason = typeof reason !== 'undefined' ? reason : 'is invalid';
114
+ return err;
115
+ }
116
+
117
+ /**
118
+ * Creates an error object used when an error was thrown but no details were specified.
119
+ *
120
+ * @public
121
+ * @param {string} message - Error message to be displayed.
122
+ * @returns {Error} instance detailing the error condition
123
+ */
124
+ function createUndefinedError(message) {
125
+ var err = new Error(message);
126
+ err.code = 'ERR_MOCHA_UNDEFINED_ERROR';
127
+ return err;
128
+ }
129
+
130
+ module.exports = {
131
+ createInvalidArgumentTypeError: createInvalidArgumentTypeError,
132
+ createInvalidArgumentValueError: createInvalidArgumentValueError,
133
+ createInvalidInterfaceError: createInvalidInterfaceError,
134
+ createInvalidReporterError: createInvalidReporterError,
135
+ createMissingArgumentError: createMissingArgumentError,
136
+ createNoFilesMatchPatternError: createNoFilesMatchPatternError,
137
+ createNotSupportedError: createNotSupportedError,
138
+ createUndefinedError: createUndefinedError
139
+ };
package/lib/growl.js ADDED
@@ -0,0 +1,135 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Desktop Notifications module.
5
+ * @module Growl
6
+ */
7
+
8
+ const os = require('os');
9
+ const path = require('path');
10
+ const {sync: which} = require('which');
11
+
12
+ /**
13
+ * @summary
14
+ * Checks if Growl notification support seems likely.
15
+ *
16
+ * @description
17
+ * Glosses over the distinction between an unsupported platform
18
+ * and one that lacks prerequisite software installations.
19
+ *
20
+ * @public
21
+ * @see {@link https://github.com/tj/node-growl/blob/master/README.md|Prerequisite Installs}
22
+ * @see {@link Mocha#growl}
23
+ * @see {@link Mocha#isGrowlCapable}
24
+ * @return {boolean} whether Growl notification support can be expected
25
+ */
26
+ exports.isCapable = () => {
27
+ if (!process.browser) {
28
+ return getSupportBinaries().reduce(
29
+ (acc, binary) => acc || Boolean(which(binary, {nothrow: true})),
30
+ false
31
+ );
32
+ }
33
+ return false;
34
+ };
35
+
36
+ /**
37
+ * Implements desktop notifications as a pseudo-reporter.
38
+ *
39
+ * @public
40
+ * @see {@link Mocha#_growl}
41
+ * @param {Runner} runner - Runner instance.
42
+ */
43
+ exports.notify = runner => {
44
+ runner.once('end', () => {
45
+ display(runner);
46
+ });
47
+ };
48
+
49
+ /**
50
+ * Displays the notification.
51
+ *
52
+ * @private
53
+ * @param {Runner} runner - Runner instance.
54
+ */
55
+ const display = runner => {
56
+ const growl = require('growl');
57
+ const stats = runner.stats;
58
+ const symbol = {
59
+ cross: '\u274C',
60
+ tick: '\u2705'
61
+ };
62
+ let _message;
63
+ let message;
64
+ let title;
65
+
66
+ if (stats.failures) {
67
+ _message = `${stats.failures} of ${runner.total} tests failed`;
68
+ message = `${symbol.cross} ${_message}`;
69
+ title = 'Failed';
70
+ } else {
71
+ _message = `${stats.passes} tests passed in ${stats.duration}ms`;
72
+ message = `${symbol.tick} ${_message}`;
73
+ title = 'Passed';
74
+ }
75
+
76
+ // Send notification
77
+ const options = {
78
+ image: logo(),
79
+ name: 'mocha',
80
+ title
81
+ };
82
+ growl(message, options, onCompletion);
83
+ };
84
+
85
+ /**
86
+ * @summary
87
+ * Callback for result of attempted Growl notification.
88
+ *
89
+ * @description
90
+ * Despite its appearance, this is <strong>not</strong> an Error-first
91
+ * callback -- all parameters are populated regardless of success.
92
+ *
93
+ * @private
94
+ * @callback Growl~growlCB
95
+ * @param {*} err - Error object, or <code>null</code> if successful.
96
+ */
97
+ function onCompletion(err) {
98
+ if (err) {
99
+ // As notifications are tangential to our purpose, just log the error.
100
+ const message =
101
+ err.code === 'ENOENT' ? 'prerequisite software not found' : err.message;
102
+ console.error('notification error:', message);
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Returns Mocha logo image path.
108
+ *
109
+ * @private
110
+ * @return {string} Pathname of Mocha logo
111
+ */
112
+ const logo = () => {
113
+ return path.join(__dirname, '..', 'assets', 'mocha-logo-96.png');
114
+ };
115
+
116
+ /**
117
+ * @summary
118
+ * Gets platform-specific Growl support binaries.
119
+ *
120
+ * @description
121
+ * Somewhat brittle dependency on `growl` package implementation, but it
122
+ * rarely changes.
123
+ *
124
+ * @private
125
+ * @see {@link https://github.com/tj/node-growl/blob/master/lib/growl.js#L28-L126|setupCmd}
126
+ * @return {string[]} names of Growl support binaries
127
+ */
128
+ const getSupportBinaries = () => {
129
+ const binaries = {
130
+ Darwin: ['terminal-notifier', 'growlnotify'],
131
+ Linux: ['notify-send', 'growl'],
132
+ Windows_NT: ['growlnotify.exe']
133
+ };
134
+ return binaries[os.type()] || [];
135
+ };
package/lib/hook.js CHANGED
@@ -1,11 +1,4 @@
1
1
  'use strict';
2
- /**
3
- * @module Hook
4
- *
5
- */
6
- /**
7
- * Module dependencies.
8
- */
9
2
 
10
3
  var Runnable = require('./runnable');
11
4
  var inherits = require('./utils').inherits;
@@ -17,17 +10,14 @@ var inherits = require('./utils').inherits;
17
10
  module.exports = Hook;
18
11
 
19
12
  /**
20
- * Initialize a new `Hook` with the given `title` and callback `fn`. Derived from
21
- * `Runnable`.
13
+ * Initialize a new `Hook` with the given `title` and callback `fn`
22
14
  *
23
- * @memberof Mocha
24
- * @public
25
15
  * @class
16
+ * @extends Runnable
26
17
  * @param {String} title
27
18
  * @param {Function} fn
28
- * @api private
29
19
  */
30
- function Hook (title, fn) {
20
+ function Hook(title, fn) {
31
21
  Runnable.call(this, title, fn);
32
22
  this.type = 'hook';
33
23
  }
@@ -40,13 +30,12 @@ inherits(Hook, Runnable);
40
30
  /**
41
31
  * Get or set the test `err`.
42
32
  *
43
- * @memberof Mocha.Hook
33
+ * @memberof Hook
44
34
  * @public
45
35
  * @param {Error} err
46
36
  * @return {Error}
47
- * @api public
48
37
  */
49
- Hook.prototype.error = function (err) {
38
+ Hook.prototype.error = function(err) {
50
39
  if (!arguments.length) {
51
40
  err = this._error;
52
41
  this._error = null;
@@ -1,9 +1,5 @@
1
1
  'use strict';
2
2
 
3
- /**
4
- * Module dependencies.
5
- */
6
-
7
3
  var Test = require('../test');
8
4
 
9
5
  /**
@@ -23,10 +19,10 @@ var Test = require('../test');
23
19
  *
24
20
  * @param {Suite} suite Root suite.
25
21
  */
26
- module.exports = function (suite) {
22
+ module.exports = function bddInterface(suite) {
27
23
  var suites = [suite];
28
24
 
29
- suite.on('pre-require', function (context, file, mocha) {
25
+ suite.on('pre-require', function(context, file, mocha) {
30
26
  var common = require('./common')(suites, context, mocha);
31
27
 
32
28
  context.before = common.before;
@@ -40,7 +36,7 @@ module.exports = function (suite) {
40
36
  * and/or tests.
41
37
  */
42
38
 
43
- context.describe = context.context = function (title, fn) {
39
+ context.describe = context.context = function(title, fn) {
44
40
  return common.suite.create({
45
41
  title: title,
46
42
  file: file,
@@ -52,7 +48,10 @@ module.exports = function (suite) {
52
48
  * Pending describe.
53
49
  */
54
50
 
55
- context.xdescribe = context.xcontext = context.describe.skip = function (title, fn) {
51
+ context.xdescribe = context.xcontext = context.describe.skip = function(
52
+ title,
53
+ fn
54
+ ) {
56
55
  return common.suite.skip({
57
56
  title: title,
58
57
  file: file,
@@ -64,7 +63,7 @@ module.exports = function (suite) {
64
63
  * Exclusive suite.
65
64
  */
66
65
 
67
- context.describe.only = function (title, fn) {
66
+ context.describe.only = function(title, fn) {
68
67
  return common.suite.only({
69
68
  title: title,
70
69
  file: file,
@@ -78,7 +77,7 @@ module.exports = function (suite) {
78
77
  * acting as a thunk.
79
78
  */
80
79
 
81
- context.it = context.specify = function (title, fn) {
80
+ context.it = context.specify = function(title, fn) {
82
81
  var suite = suites[0];
83
82
  if (suite.isPending()) {
84
83
  fn = null;
@@ -93,7 +92,7 @@ module.exports = function (suite) {
93
92
  * Exclusive test-case.
94
93
  */
95
94
 
96
- context.it.only = function (title, fn) {
95
+ context.it.only = function(title, fn) {
97
96
  return common.test.only(mocha, context.it(title, fn));
98
97
  };
99
98
 
@@ -101,15 +100,17 @@ module.exports = function (suite) {
101
100
  * Pending test case.
102
101
  */
103
102
 
104
- context.xit = context.xspecify = context.it.skip = function (title) {
103
+ context.xit = context.xspecify = context.it.skip = function(title) {
105
104
  return context.it(title);
106
105
  };
107
106
 
108
107
  /**
109
108
  * Number of attempts to retry.
110
109
  */
111
- context.it.retries = function (n) {
110
+ context.it.retries = function(n) {
112
111
  context.retries(n);
113
112
  };
114
113
  });
115
114
  };
115
+
116
+ module.exports.description = 'BDD or RSpec style [default]';
@@ -1,6 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var Suite = require('../suite');
4
+ var utils = require('../utils');
5
+ var errors = require('../errors');
6
+ var createMissingArgumentError = errors.createMissingArgumentError;
4
7
 
5
8
  /**
6
9
  * Functions common to more than one interface.
@@ -10,7 +13,23 @@ var Suite = require('../suite');
10
13
  * @param {Mocha} mocha
11
14
  * @return {Object} An object containing common functions.
12
15
  */
13
- module.exports = function (suites, context, mocha) {
16
+ module.exports = function(suites, context, mocha) {
17
+ /**
18
+ * Check if the suite should be tested.
19
+ *
20
+ * @private
21
+ * @param {Suite} suite - suite to check
22
+ * @returns {boolean}
23
+ */
24
+ function shouldBeTested(suite) {
25
+ return (
26
+ !mocha.options.grep ||
27
+ (mocha.options.grep &&
28
+ mocha.options.grep.test(suite.fullTitle()) &&
29
+ !mocha.options.invert)
30
+ );
31
+ }
32
+
14
33
  return {
15
34
  /**
16
35
  * This is only present if flag --delay is passed into Mocha. It triggers
@@ -19,8 +38,8 @@ module.exports = function (suites, context, mocha) {
19
38
  * @param {Suite} suite The root suite.
20
39
  * @return {Function} A function which runs the root suite
21
40
  */
22
- runWithSuite: function runWithSuite (suite) {
23
- return function run () {
41
+ runWithSuite: function runWithSuite(suite) {
42
+ return function run() {
24
43
  suite.run();
25
44
  };
26
45
  },
@@ -31,7 +50,7 @@ module.exports = function (suites, context, mocha) {
31
50
  * @param {string} name
32
51
  * @param {Function} fn
33
52
  */
34
- before: function (name, fn) {
53
+ before: function(name, fn) {
35
54
  suites[0].beforeAll(name, fn);
36
55
  },
37
56
 
@@ -41,7 +60,7 @@ module.exports = function (suites, context, mocha) {
41
60
  * @param {string} name
42
61
  * @param {Function} fn
43
62
  */
44
- after: function (name, fn) {
63
+ after: function(name, fn) {
45
64
  suites[0].afterAll(name, fn);
46
65
  },
47
66
 
@@ -51,7 +70,7 @@ module.exports = function (suites, context, mocha) {
51
70
  * @param {string} name
52
71
  * @param {Function} fn
53
72
  */
54
- beforeEach: function (name, fn) {
73
+ beforeEach: function(name, fn) {
55
74
  suites[0].beforeEach(name, fn);
56
75
  },
57
76
 
@@ -61,7 +80,7 @@ module.exports = function (suites, context, mocha) {
61
80
  * @param {string} name
62
81
  * @param {Function} fn
63
82
  */
64
- afterEach: function (name, fn) {
83
+ afterEach: function(name, fn) {
65
84
  suites[0].afterEach(name, fn);
66
85
  },
67
86
 
@@ -73,7 +92,7 @@ module.exports = function (suites, context, mocha) {
73
92
  * @param {Object} opts
74
93
  * @returns {Suite}
75
94
  */
76
- only: function only (opts) {
95
+ only: function only(opts) {
77
96
  opts.isOnly = true;
78
97
  return this.create(opts);
79
98
  },
@@ -85,13 +104,14 @@ module.exports = function (suites, context, mocha) {
85
104
  * @param {Object} opts
86
105
  * @returns {Suite}
87
106
  */
88
- skip: function skip (opts) {
107
+ skip: function skip(opts) {
89
108
  opts.pending = true;
90
109
  return this.create(opts);
91
110
  },
92
111
 
93
112
  /**
94
113
  * Creates a suite.
114
+ *
95
115
  * @param {Object} opts Options
96
116
  * @param {string} opts.title Title of Suite
97
117
  * @param {Function} [opts.fn] Suite Function (not always applicable)
@@ -100,19 +120,43 @@ module.exports = function (suites, context, mocha) {
100
120
  * @param {boolean} [opts.isOnly] Is Suite exclusive?
101
121
  * @returns {Suite}
102
122
  */
103
- create: function create (opts) {
123
+ create: function create(opts) {
104
124
  var suite = Suite.create(suites[0], opts.title);
105
125
  suite.pending = Boolean(opts.pending);
106
126
  suite.file = opts.file;
107
127
  suites.unshift(suite);
108
128
  if (opts.isOnly) {
129
+ if (mocha.options.forbidOnly && shouldBeTested(suite)) {
130
+ throw new Error('`.only` forbidden');
131
+ }
132
+
109
133
  suite.parent._onlySuites = suite.parent._onlySuites.concat(suite);
110
134
  }
135
+ if (suite.pending) {
136
+ if (mocha.options.forbidPending && shouldBeTested(suite)) {
137
+ throw new Error('Pending test forbidden');
138
+ }
139
+ }
111
140
  if (typeof opts.fn === 'function') {
112
- opts.fn.call(suite);
141
+ var result = opts.fn.call(suite);
142
+ if (typeof result !== 'undefined') {
143
+ utils.deprecate(
144
+ 'Deprecation Warning: Suites do not support a return value;' +
145
+ opts.title +
146
+ ' returned :' +
147
+ result
148
+ );
149
+ }
113
150
  suites.shift();
114
151
  } else if (typeof opts.fn === 'undefined' && !suite.pending) {
115
- throw new Error('Suite "' + suite.fullTitle() + '" was defined but no callback was supplied. Supply a callback or explicitly skip the suite.');
152
+ throw createMissingArgumentError(
153
+ 'Suite "' +
154
+ suite.fullTitle() +
155
+ '" was defined but no callback was supplied. ' +
156
+ 'Supply a callback or explicitly skip the suite.',
157
+ 'callback',
158
+ 'function'
159
+ );
116
160
  } else if (!opts.fn && suite.pending) {
117
161
  suites.shift();
118
162
  }
@@ -122,7 +166,6 @@ module.exports = function (suites, context, mocha) {
122
166
  },
123
167
 
124
168
  test: {
125
-
126
169
  /**
127
170
  * Exclusive test-case.
128
171
  *
@@ -130,7 +173,7 @@ module.exports = function (suites, context, mocha) {
130
173
  * @param {Function} test
131
174
  * @returns {*}
132
175
  */
133
- only: function (mocha, test) {
176
+ only: function(mocha, test) {
134
177
  test.parent._onlyTests = test.parent._onlyTests.concat(test);
135
178
  return test;
136
179
  },
@@ -140,7 +183,7 @@ module.exports = function (suites, context, mocha) {
140
183
  *
141
184
  * @param {string} title
142
185
  */
143
- skip: function (title) {
186
+ skip: function(title) {
144
187
  context.test(title);
145
188
  },
146
189
 
@@ -149,7 +192,7 @@ module.exports = function (suites, context, mocha) {
149
192
  *
150
193
  * @param {number} n
151
194
  */
152
- retries: function (n) {
195
+ retries: function(n) {
153
196
  context.retries(n);
154
197
  }
155
198
  }