mocha 5.1.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +686 -984
  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 +121 -61
  7. package/bin/options.js +6 -39
  8. package/browser-entry.js +21 -17
  9. package/lib/browser/growl.js +165 -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 +69 -0
  19. package/lib/cli/one-and-dones.js +70 -0
  20. package/lib/cli/options.js +330 -0
  21. package/lib/cli/run-helpers.js +337 -0
  22. package/lib/cli/run-option-metadata.js +76 -0
  23. package/lib/cli/run.js +297 -0
  24. package/lib/context.js +14 -14
  25. package/lib/errors.js +141 -0
  26. package/lib/growl.js +136 -0
  27. package/lib/hook.js +5 -16
  28. package/lib/interfaces/bdd.js +16 -13
  29. package/lib/interfaces/common.js +62 -18
  30. package/lib/interfaces/exports.js +5 -8
  31. package/lib/interfaces/qunit.js +10 -10
  32. package/lib/interfaces/tdd.js +12 -11
  33. package/lib/mocha.js +477 -256
  34. package/lib/mocharc.json +10 -0
  35. package/lib/pending.js +1 -5
  36. package/lib/reporters/base.js +95 -117
  37. package/lib/reporters/doc.js +23 -9
  38. package/lib/reporters/dot.js +19 -13
  39. package/lib/reporters/html.js +82 -47
  40. package/lib/reporters/json-stream.js +43 -23
  41. package/lib/reporters/json.js +32 -23
  42. package/lib/reporters/landing.js +16 -9
  43. package/lib/reporters/list.js +19 -11
  44. package/lib/reporters/markdown.js +18 -12
  45. package/lib/reporters/min.js +8 -4
  46. package/lib/reporters/nyan.js +42 -35
  47. package/lib/reporters/progress.js +12 -7
  48. package/lib/reporters/spec.js +23 -12
  49. package/lib/reporters/tap.js +250 -32
  50. package/lib/reporters/xunit.js +61 -35
  51. package/lib/runnable.js +152 -95
  52. package/lib/runner.js +296 -248
  53. package/lib/stats-collector.js +83 -0
  54. package/lib/suite.js +294 -75
  55. package/lib/test.js +16 -15
  56. package/lib/utils.js +419 -146
  57. package/mocha.js +4589 -2228
  58. package/package.json +137 -38
  59. package/lib/ms.js +0 -94
  60. package/lib/reporters/base.js.orig +0 -498
  61. package/lib/reporters/json.js.orig +0 -128
@@ -6,7 +6,17 @@
6
6
  * Module dependencies.
7
7
  */
8
8
 
9
+ var util = require('util');
9
10
  var Base = require('./base');
11
+ var constants = require('../runner').constants;
12
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
13
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
14
+ var EVENT_RUN_BEGIN = constants.EVENT_RUN_BEGIN;
15
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
16
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
17
+ var EVENT_TEST_END = constants.EVENT_TEST_END;
18
+ var inherits = require('../utils').inherits;
19
+ var sprintf = util.format;
10
20
 
11
21
  /**
12
22
  * Expose `TAP`.
@@ -15,62 +25,270 @@ var Base = require('./base');
15
25
  exports = module.exports = TAP;
16
26
 
17
27
  /**
18
- * Initialize a new `TAP` reporter.
28
+ * Constructs a new TAP reporter with runner instance and reporter options.
19
29
  *
20
30
  * @public
21
31
  * @class
22
- * @memberof Mocha.reporters
23
32
  * @extends Mocha.reporters.Base
24
- * @api public
25
- * @param {Runner} runner
33
+ * @memberof Mocha.reporters
34
+ * @param {Runner} runner - Instance triggers reporter actions.
35
+ * @param {Object} [options] - runner options
26
36
  */
27
- function TAP (runner) {
28
- Base.call(this, runner);
37
+ function TAP(runner, options) {
38
+ Base.call(this, runner, options);
29
39
 
40
+ var self = this;
30
41
  var n = 1;
31
- var passes = 0;
32
- var failures = 0;
33
42
 
34
- runner.on('start', function () {
35
- var total = runner.grepTotal(runner.suite);
36
- console.log('%d..%d', 1, total);
43
+ var tapVersion = '12';
44
+ if (options && options.reporterOptions) {
45
+ if (options.reporterOptions.tapVersion) {
46
+ tapVersion = options.reporterOptions.tapVersion.toString();
47
+ }
48
+ }
49
+
50
+ this._producer = createProducer(tapVersion);
51
+
52
+ runner.once(EVENT_RUN_BEGIN, function() {
53
+ var ntests = runner.grepTotal(runner.suite);
54
+ self._producer.writeVersion();
55
+ self._producer.writePlan(ntests);
37
56
  });
38
57
 
39
- runner.on('test end', function () {
58
+ runner.on(EVENT_TEST_END, function() {
40
59
  ++n;
41
60
  });
42
61
 
43
- runner.on('pending', function (test) {
44
- console.log('ok %d %s # SKIP -', n, title(test));
62
+ runner.on(EVENT_TEST_PENDING, function(test) {
63
+ self._producer.writePending(n, test);
45
64
  });
46
65
 
47
- runner.on('pass', function (test) {
48
- passes++;
49
- console.log('ok %d %s', n, title(test));
66
+ runner.on(EVENT_TEST_PASS, function(test) {
67
+ self._producer.writePass(n, test);
50
68
  });
51
69
 
52
- runner.on('fail', function (test, err) {
53
- failures++;
54
- console.log('not ok %d %s', n, title(test));
55
- if (err.stack) {
56
- console.log(err.stack.replace(/^/gm, ' '));
57
- }
70
+ runner.on(EVENT_TEST_FAIL, function(test, err) {
71
+ self._producer.writeFail(n, test, err);
58
72
  });
59
73
 
60
- runner.once('end', function () {
61
- console.log('# tests ' + (passes + failures));
62
- console.log('# pass ' + passes);
63
- console.log('# fail ' + failures);
74
+ runner.once(EVENT_RUN_END, function() {
75
+ self._producer.writeEpilogue(runner.stats);
64
76
  });
65
77
  }
66
78
 
67
79
  /**
68
- * Return a TAP-safe title of `test`
80
+ * Inherit from `Base.prototype`.
81
+ */
82
+ inherits(TAP, Base);
83
+
84
+ /**
85
+ * Returns a TAP-safe title of `test`.
69
86
  *
70
- * @api private
71
- * @param {Object} test
72
- * @return {String}
87
+ * @private
88
+ * @param {Test} test - Test instance.
89
+ * @return {String} title with any hash character removed
73
90
  */
74
- function title (test) {
91
+ function title(test) {
75
92
  return test.fullTitle().replace(/#/g, '');
76
93
  }
94
+
95
+ /**
96
+ * Writes newline-terminated formatted string to reporter output stream.
97
+ *
98
+ * @private
99
+ * @param {string} format - `printf`-like format string
100
+ * @param {...*} [varArgs] - Format string arguments
101
+ */
102
+ function println(format, varArgs) {
103
+ var vargs = Array.from(arguments);
104
+ vargs[0] += '\n';
105
+ process.stdout.write(sprintf.apply(null, vargs));
106
+ }
107
+
108
+ /**
109
+ * Returns a `tapVersion`-appropriate TAP producer instance, if possible.
110
+ *
111
+ * @private
112
+ * @param {string} tapVersion - Version of TAP specification to produce.
113
+ * @returns {TAPProducer} specification-appropriate instance
114
+ * @throws {Error} if specification version has no associated producer.
115
+ */
116
+ function createProducer(tapVersion) {
117
+ var producers = {
118
+ '12': new TAP12Producer(),
119
+ '13': new TAP13Producer()
120
+ };
121
+ var producer = producers[tapVersion];
122
+
123
+ if (!producer) {
124
+ throw new Error(
125
+ 'invalid or unsupported TAP version: ' + JSON.stringify(tapVersion)
126
+ );
127
+ }
128
+
129
+ return producer;
130
+ }
131
+
132
+ /**
133
+ * @summary
134
+ * Constructs a new TAPProducer.
135
+ *
136
+ * @description
137
+ * <em>Only</em> to be used as an abstract base class.
138
+ *
139
+ * @private
140
+ * @constructor
141
+ */
142
+ function TAPProducer() {}
143
+
144
+ /**
145
+ * Writes the TAP version to reporter output stream.
146
+ *
147
+ * @abstract
148
+ */
149
+ TAPProducer.prototype.writeVersion = function() {};
150
+
151
+ /**
152
+ * Writes the plan to reporter output stream.
153
+ *
154
+ * @abstract
155
+ * @param {number} ntests - Number of tests that are planned to run.
156
+ */
157
+ TAPProducer.prototype.writePlan = function(ntests) {
158
+ println('%d..%d', 1, ntests);
159
+ };
160
+
161
+ /**
162
+ * Writes that test passed to reporter output stream.
163
+ *
164
+ * @abstract
165
+ * @param {number} n - Index of test that passed.
166
+ * @param {Test} test - Instance containing test information.
167
+ */
168
+ TAPProducer.prototype.writePass = function(n, test) {
169
+ println('ok %d %s', n, title(test));
170
+ };
171
+
172
+ /**
173
+ * Writes that test was skipped to reporter output stream.
174
+ *
175
+ * @abstract
176
+ * @param {number} n - Index of test that was skipped.
177
+ * @param {Test} test - Instance containing test information.
178
+ */
179
+ TAPProducer.prototype.writePending = function(n, test) {
180
+ println('ok %d %s # SKIP -', n, title(test));
181
+ };
182
+
183
+ /**
184
+ * Writes that test failed to reporter output stream.
185
+ *
186
+ * @abstract
187
+ * @param {number} n - Index of test that failed.
188
+ * @param {Test} test - Instance containing test information.
189
+ * @param {Error} err - Reason the test failed.
190
+ */
191
+ TAPProducer.prototype.writeFail = function(n, test, err) {
192
+ println('not ok %d %s', n, title(test));
193
+ };
194
+
195
+ /**
196
+ * Writes the summary epilogue to reporter output stream.
197
+ *
198
+ * @abstract
199
+ * @param {Object} stats - Object containing run statistics.
200
+ */
201
+ TAPProducer.prototype.writeEpilogue = function(stats) {
202
+ // :TBD: Why is this not counting pending tests?
203
+ println('# tests ' + (stats.passes + stats.failures));
204
+ println('# pass ' + stats.passes);
205
+ // :TBD: Why are we not showing pending results?
206
+ println('# fail ' + stats.failures);
207
+ };
208
+
209
+ /**
210
+ * @summary
211
+ * Constructs a new TAP12Producer.
212
+ *
213
+ * @description
214
+ * Produces output conforming to the TAP12 specification.
215
+ *
216
+ * @private
217
+ * @constructor
218
+ * @extends TAPProducer
219
+ * @see {@link https://testanything.org/tap-specification.html|Specification}
220
+ */
221
+ function TAP12Producer() {
222
+ /**
223
+ * Writes that test failed to reporter output stream, with error formatting.
224
+ * @override
225
+ */
226
+ this.writeFail = function(n, test, err) {
227
+ TAPProducer.prototype.writeFail.call(this, n, test, err);
228
+ if (err.message) {
229
+ println(err.message.replace(/^/gm, ' '));
230
+ }
231
+ if (err.stack) {
232
+ println(err.stack.replace(/^/gm, ' '));
233
+ }
234
+ };
235
+ }
236
+
237
+ /**
238
+ * Inherit from `TAPProducer.prototype`.
239
+ */
240
+ inherits(TAP12Producer, TAPProducer);
241
+
242
+ /**
243
+ * @summary
244
+ * Constructs a new TAP13Producer.
245
+ *
246
+ * @description
247
+ * Produces output conforming to the TAP13 specification.
248
+ *
249
+ * @private
250
+ * @constructor
251
+ * @extends TAPProducer
252
+ * @see {@link https://testanything.org/tap-version-13-specification.html|Specification}
253
+ */
254
+ function TAP13Producer() {
255
+ /**
256
+ * Writes the TAP version to reporter output stream.
257
+ * @override
258
+ */
259
+ this.writeVersion = function() {
260
+ println('TAP version 13');
261
+ };
262
+
263
+ /**
264
+ * Writes that test failed to reporter output stream, with error formatting.
265
+ * @override
266
+ */
267
+ this.writeFail = function(n, test, err) {
268
+ TAPProducer.prototype.writeFail.call(this, n, test, err);
269
+ var emitYamlBlock = err.message != null || err.stack != null;
270
+ if (emitYamlBlock) {
271
+ println(indent(1) + '---');
272
+ if (err.message) {
273
+ println(indent(2) + 'message: |-');
274
+ println(err.message.replace(/^/gm, indent(3)));
275
+ }
276
+ if (err.stack) {
277
+ println(indent(2) + 'stack: |-');
278
+ println(err.stack.replace(/^/gm, indent(3)));
279
+ }
280
+ println(indent(1) + '...');
281
+ }
282
+ };
283
+
284
+ function indent(level) {
285
+ return Array(level + 1).join(' ');
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Inherit from `TAPProducer.prototype`.
291
+ */
292
+ inherits(TAP13Producer, TAPProducer);
293
+
294
+ TAP.description = 'TAP-compatible output';
@@ -8,23 +8,24 @@
8
8
 
9
9
  var Base = require('./base');
10
10
  var utils = require('../utils');
11
- var inherits = utils.inherits;
12
11
  var fs = require('fs');
13
- var escape = utils.escape;
14
12
  var mkdirp = require('mkdirp');
15
13
  var path = require('path');
14
+ var errors = require('../errors');
15
+ var createUnsupportedError = errors.createUnsupportedError;
16
+ var constants = require('../runner').constants;
17
+ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
18
+ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
19
+ var EVENT_RUN_END = constants.EVENT_RUN_END;
20
+ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
21
+ var STATE_FAILED = require('../runnable').constants.STATE_FAILED;
22
+ var inherits = utils.inherits;
23
+ var escape = utils.escape;
16
24
 
17
25
  /**
18
26
  * Save timer references to avoid Sinon interfering (see GH-237).
19
27
  */
20
-
21
- /* eslint-disable no-unused-vars, no-native-reassign */
22
28
  var Date = global.Date;
23
- var setTimeout = global.setTimeout;
24
- var setInterval = global.setInterval;
25
- var clearTimeout = global.clearTimeout;
26
- var clearInterval = global.clearInterval;
27
- /* eslint-enable no-unused-vars, no-native-reassign */
28
29
 
29
30
  /**
30
31
  * Expose `XUnit`.
@@ -39,10 +40,9 @@ exports = module.exports = XUnit;
39
40
  * @class
40
41
  * @memberof Mocha.reporters
41
42
  * @extends Mocha.reporters.Base
42
- * @api public
43
43
  * @param {Runner} runner
44
44
  */
45
- function XUnit (runner, options) {
45
+ function XUnit(runner, options) {
46
46
  Base.call(this, runner);
47
47
 
48
48
  var stats = this.stats;
@@ -58,7 +58,7 @@ function XUnit (runner, options) {
58
58
  if (options && options.reporterOptions) {
59
59
  if (options.reporterOptions.output) {
60
60
  if (!fs.createWriteStream) {
61
- throw new Error('file output not supported in browser');
61
+ throw createUnsupportedError('file output not supported in browser');
62
62
  }
63
63
 
64
64
  mkdirp.sync(path.dirname(options.reporterOptions.output));
@@ -72,30 +72,36 @@ function XUnit (runner, options) {
72
72
  // fall back to the default suite name
73
73
  suiteName = suiteName || DEFAULT_SUITE_NAME;
74
74
 
75
- runner.on('pending', function (test) {
75
+ runner.on(EVENT_TEST_PENDING, function(test) {
76
76
  tests.push(test);
77
77
  });
78
78
 
79
- runner.on('pass', function (test) {
79
+ runner.on(EVENT_TEST_PASS, function(test) {
80
80
  tests.push(test);
81
81
  });
82
82
 
83
- runner.on('fail', function (test) {
83
+ runner.on(EVENT_TEST_FAIL, function(test) {
84
84
  tests.push(test);
85
85
  });
86
86
 
87
- runner.once('end', function () {
88
- self.write(tag('testsuite', {
89
- name: suiteName,
90
- tests: stats.tests,
91
- failures: stats.failures,
92
- errors: stats.failures,
93
- skipped: stats.tests - stats.failures - stats.passes,
94
- timestamp: (new Date()).toUTCString(),
95
- time: (stats.duration / 1000) || 0
96
- }, false));
97
-
98
- tests.forEach(function (t) {
87
+ runner.once(EVENT_RUN_END, function() {
88
+ self.write(
89
+ tag(
90
+ 'testsuite',
91
+ {
92
+ name: suiteName,
93
+ tests: stats.tests,
94
+ failures: 0,
95
+ errors: stats.failures,
96
+ skipped: stats.tests - stats.failures - stats.passes,
97
+ timestamp: new Date().toUTCString(),
98
+ time: stats.duration / 1000 || 0
99
+ },
100
+ false
101
+ )
102
+ );
103
+
104
+ tests.forEach(function(t) {
99
105
  self.test(t);
100
106
  });
101
107
 
@@ -114,9 +120,9 @@ inherits(XUnit, Base);
114
120
  * @param failures
115
121
  * @param {Function} fn
116
122
  */
117
- XUnit.prototype.done = function (failures, fn) {
123
+ XUnit.prototype.done = function(failures, fn) {
118
124
  if (this.fileStream) {
119
- this.fileStream.end(function () {
125
+ this.fileStream.end(function() {
120
126
  fn(failures);
121
127
  });
122
128
  } else {
@@ -129,7 +135,7 @@ XUnit.prototype.done = function (failures, fn) {
129
135
  *
130
136
  * @param {string} line
131
137
  */
132
- XUnit.prototype.write = function (line) {
138
+ XUnit.prototype.write = function(line) {
133
139
  if (this.fileStream) {
134
140
  this.fileStream.write(line + '\n');
135
141
  } else if (typeof process === 'object' && process.stdout) {
@@ -144,16 +150,34 @@ XUnit.prototype.write = function (line) {
144
150
  *
145
151
  * @param {Test} test
146
152
  */
147
- XUnit.prototype.test = function (test) {
153
+ XUnit.prototype.test = function(test) {
154
+ Base.useColors = false;
155
+
148
156
  var attrs = {
149
157
  classname: test.parent.fullTitle(),
150
158
  name: test.title,
151
- time: (test.duration / 1000) || 0
159
+ time: test.duration / 1000 || 0
152
160
  };
153
161
 
154
- if (test.state === 'failed') {
162
+ if (test.state === STATE_FAILED) {
155
163
  var err = test.err;
156
- this.write(tag('testcase', attrs, false, tag('failure', {}, false, escape(err.message) + '\n' + escape(err.stack))));
164
+ var diff =
165
+ Base.hideDiff || !err.actual || !err.expected
166
+ ? ''
167
+ : '\n' + Base.generateDiff(err.actual, err.expected);
168
+ this.write(
169
+ tag(
170
+ 'testcase',
171
+ attrs,
172
+ false,
173
+ tag(
174
+ 'failure',
175
+ {},
176
+ false,
177
+ escape(err.message) + escape(diff) + '\n' + escape(err.stack)
178
+ )
179
+ )
180
+ );
157
181
  } else if (test.isPending()) {
158
182
  this.write(tag('testcase', attrs, false, tag('skipped', {}, true)));
159
183
  } else {
@@ -170,7 +194,7 @@ XUnit.prototype.test = function (test) {
170
194
  * @param content
171
195
  * @return {string}
172
196
  */
173
- function tag (name, attrs, close, content) {
197
+ function tag(name, attrs, close, content) {
174
198
  var end = close ? '/>' : '>';
175
199
  var pairs = [];
176
200
  var tag;
@@ -187,3 +211,5 @@ function tag (name, attrs, close, content) {
187
211
  }
188
212
  return tag;
189
213
  }
214
+
215
+ XUnit.description = 'XUnit-compatible XML output';