mocha 6.1.0 → 6.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1776 -1751
- package/LICENSE +22 -22
- package/README.md +105 -105
- package/bin/_mocha +10 -10
- package/bin/mocha +149 -149
- package/bin/options.js +10 -10
- package/browser-entry.js +191 -191
- package/index.js +3 -3
- package/lib/browser/growl.js +168 -168
- package/lib/browser/progress.js +119 -119
- package/lib/browser/template.html +18 -18
- package/lib/browser/tty.js +13 -13
- package/lib/cli/cli.js +69 -69
- package/lib/cli/commands.js +13 -13
- package/lib/cli/config.js +101 -101
- package/lib/cli/index.js +9 -9
- package/lib/cli/init.js +37 -37
- package/lib/cli/node-flags.js +86 -86
- package/lib/cli/one-and-dones.js +70 -70
- package/lib/cli/options.js +347 -347
- package/lib/cli/run-helpers.js +337 -337
- package/lib/cli/run-option-metadata.js +76 -76
- package/lib/cli/run.js +297 -297
- package/lib/context.js +101 -101
- package/lib/errors.js +141 -141
- package/lib/growl.js +136 -136
- package/lib/hook.js +46 -46
- package/lib/interfaces/bdd.js +118 -118
- package/lib/interfaces/common.js +191 -191
- package/lib/interfaces/exports.js +60 -60
- package/lib/interfaces/index.js +6 -6
- package/lib/interfaces/qunit.js +99 -99
- package/lib/interfaces/tdd.js +107 -107
- package/lib/mocha.js +843 -843
- package/lib/mocharc.json +10 -10
- package/lib/pending.js +12 -12
- package/lib/reporters/base.js +491 -491
- package/lib/reporters/doc.js +85 -85
- package/lib/reporters/dot.js +81 -81
- package/lib/reporters/html.js +390 -390
- package/lib/reporters/index.js +19 -19
- package/lib/reporters/json-stream.js +90 -90
- package/lib/reporters/json.js +135 -135
- package/lib/reporters/landing.js +108 -108
- package/lib/reporters/list.js +78 -78
- package/lib/reporters/markdown.js +112 -112
- package/lib/reporters/min.js +52 -52
- package/lib/reporters/nyan.js +276 -276
- package/lib/reporters/progress.js +104 -104
- package/lib/reporters/spec.js +99 -99
- package/lib/reporters/tap.js +294 -294
- package/lib/reporters/xunit.js +216 -216
- package/lib/runnable.js +496 -496
- package/lib/runner.js +1049 -1049
- package/lib/stats-collector.js +83 -83
- package/lib/suite.js +642 -642
- package/lib/test.js +51 -51
- package/lib/utils.js +897 -897
- package/mocha.css +326 -326
- package/mocha.js +8170 -8476
- package/package.json +630 -628
package/lib/reporters/base.js
CHANGED
|
@@ -1,491 +1,491 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
/**
|
|
3
|
-
* @module Base
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Module dependencies.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
var tty = require('tty');
|
|
10
|
-
var diff = require('diff');
|
|
11
|
-
var milliseconds = require('ms');
|
|
12
|
-
var utils = require('../utils');
|
|
13
|
-
var supportsColor = process.browser ? null : require('supports-color');
|
|
14
|
-
var constants = require('../runner').constants;
|
|
15
|
-
var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
|
|
16
|
-
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Expose `Base`.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
exports = module.exports = Base;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Check if both stdio streams are associated with a tty.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
var isatty = tty.isatty(1) && tty.isatty(2);
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Enable coloring by default, except in the browser interface.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
exports.useColors =
|
|
35
|
-
!process.browser &&
|
|
36
|
-
(supportsColor.stdout || process.env.MOCHA_COLORS !== undefined);
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Inline diffs instead of +/-
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
exports.inlineDiffs = false;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Default color map.
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
exports.colors = {
|
|
49
|
-
pass: 90,
|
|
50
|
-
fail: 31,
|
|
51
|
-
'bright pass': 92,
|
|
52
|
-
'bright fail': 91,
|
|
53
|
-
'bright yellow': 93,
|
|
54
|
-
pending: 36,
|
|
55
|
-
suite: 0,
|
|
56
|
-
'error title': 0,
|
|
57
|
-
'error message': 31,
|
|
58
|
-
'error stack': 90,
|
|
59
|
-
checkmark: 32,
|
|
60
|
-
fast: 90,
|
|
61
|
-
medium: 33,
|
|
62
|
-
slow: 31,
|
|
63
|
-
green: 32,
|
|
64
|
-
light: 90,
|
|
65
|
-
'diff gutter': 90,
|
|
66
|
-
'diff added': 32,
|
|
67
|
-
'diff removed': 31
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Default symbol map.
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
|
-
exports.symbols = {
|
|
75
|
-
ok: '✓',
|
|
76
|
-
err: '✖',
|
|
77
|
-
dot: '․',
|
|
78
|
-
comma: ',',
|
|
79
|
-
bang: '!'
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// With node.js on Windows: use symbols available in terminal default fonts
|
|
83
|
-
if (process.platform === 'win32') {
|
|
84
|
-
exports.symbols.ok = '\u221A';
|
|
85
|
-
exports.symbols.err = '\u00D7';
|
|
86
|
-
exports.symbols.dot = '.';
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Color `str` with the given `type`,
|
|
91
|
-
* allowing colors to be disabled,
|
|
92
|
-
* as well as user-defined color
|
|
93
|
-
* schemes.
|
|
94
|
-
*
|
|
95
|
-
* @private
|
|
96
|
-
* @param {string} type
|
|
97
|
-
* @param {string} str
|
|
98
|
-
* @return {string}
|
|
99
|
-
*/
|
|
100
|
-
var color = (exports.color = function(type, str) {
|
|
101
|
-
if (!exports.useColors) {
|
|
102
|
-
return String(str);
|
|
103
|
-
}
|
|
104
|
-
return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Expose term window size, with some defaults for when stderr is not a tty.
|
|
109
|
-
*/
|
|
110
|
-
|
|
111
|
-
exports.window = {
|
|
112
|
-
width: 75
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
if (isatty) {
|
|
116
|
-
exports.window.width = process.stdout.getWindowSize
|
|
117
|
-
? process.stdout.getWindowSize(1)[0]
|
|
118
|
-
: tty.getWindowSize()[1];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Expose some basic cursor interactions that are common among reporters.
|
|
123
|
-
*/
|
|
124
|
-
|
|
125
|
-
exports.cursor = {
|
|
126
|
-
hide: function() {
|
|
127
|
-
isatty && process.stdout.write('\u001b[?25l');
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
show: function() {
|
|
131
|
-
isatty && process.stdout.write('\u001b[?25h');
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
deleteLine: function() {
|
|
135
|
-
isatty && process.stdout.write('\u001b[2K');
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
beginningOfLine: function() {
|
|
139
|
-
isatty && process.stdout.write('\u001b[0G');
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
CR: function() {
|
|
143
|
-
if (isatty) {
|
|
144
|
-
exports.cursor.deleteLine();
|
|
145
|
-
exports.cursor.beginningOfLine();
|
|
146
|
-
} else {
|
|
147
|
-
process.stdout.write('\r');
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
function showDiff(err) {
|
|
153
|
-
return (
|
|
154
|
-
err &&
|
|
155
|
-
err.showDiff !== false &&
|
|
156
|
-
sameType(err.actual, err.expected) &&
|
|
157
|
-
err.expected !== undefined
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function stringifyDiffObjs(err) {
|
|
162
|
-
if (!utils.isString(err.actual) || !utils.isString(err.expected)) {
|
|
163
|
-
err.actual = utils.stringify(err.actual);
|
|
164
|
-
err.expected = utils.stringify(err.expected);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Returns a diff between 2 strings with coloured ANSI output.
|
|
170
|
-
*
|
|
171
|
-
* @description
|
|
172
|
-
* The diff will be either inline or unified dependent on the value
|
|
173
|
-
* of `Base.inlineDiff`.
|
|
174
|
-
*
|
|
175
|
-
* @param {string} actual
|
|
176
|
-
* @param {string} expected
|
|
177
|
-
* @return {string} Diff
|
|
178
|
-
*/
|
|
179
|
-
var generateDiff = (exports.generateDiff = function(actual, expected) {
|
|
180
|
-
return exports.inlineDiffs
|
|
181
|
-
? inlineDiff(actual, expected)
|
|
182
|
-
: unifiedDiff(actual, expected);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Outputs the given `failures` as a list.
|
|
187
|
-
*
|
|
188
|
-
* @public
|
|
189
|
-
* @memberof Mocha.reporters.Base
|
|
190
|
-
* @variation 1
|
|
191
|
-
* @param {Object[]} failures - Each is Test instance with corresponding
|
|
192
|
-
* Error property
|
|
193
|
-
*/
|
|
194
|
-
exports.list = function(failures) {
|
|
195
|
-
console.log();
|
|
196
|
-
failures.forEach(function(test, i) {
|
|
197
|
-
// format
|
|
198
|
-
var fmt =
|
|
199
|
-
color('error title', ' %s) %s:\n') +
|
|
200
|
-
color('error message', ' %s') +
|
|
201
|
-
color('error stack', '\n%s\n');
|
|
202
|
-
|
|
203
|
-
// msg
|
|
204
|
-
var msg;
|
|
205
|
-
var err = test.err;
|
|
206
|
-
var message;
|
|
207
|
-
if (err.message && typeof err.message.toString === 'function') {
|
|
208
|
-
message = err.message + '';
|
|
209
|
-
} else if (typeof err.inspect === 'function') {
|
|
210
|
-
message = err.inspect() + '';
|
|
211
|
-
} else {
|
|
212
|
-
message = '';
|
|
213
|
-
}
|
|
214
|
-
var stack = err.stack || message;
|
|
215
|
-
var index = message ? stack.indexOf(message) : -1;
|
|
216
|
-
|
|
217
|
-
if (index === -1) {
|
|
218
|
-
msg = message;
|
|
219
|
-
} else {
|
|
220
|
-
index += message.length;
|
|
221
|
-
msg = stack.slice(0, index);
|
|
222
|
-
// remove msg from stack
|
|
223
|
-
stack = stack.slice(index + 1);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// uncaught
|
|
227
|
-
if (err.uncaught) {
|
|
228
|
-
msg = 'Uncaught ' + msg;
|
|
229
|
-
}
|
|
230
|
-
// explicitly show diff
|
|
231
|
-
if (!exports.hideDiff && showDiff(err)) {
|
|
232
|
-
stringifyDiffObjs(err);
|
|
233
|
-
fmt =
|
|
234
|
-
color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
|
|
235
|
-
var match = message.match(/^([^:]+): expected/);
|
|
236
|
-
msg = '\n ' + color('error message', match ? match[1] : msg);
|
|
237
|
-
|
|
238
|
-
msg += generateDiff(err.actual, err.expected);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// indent stack trace
|
|
242
|
-
stack = stack.replace(/^/gm, ' ');
|
|
243
|
-
|
|
244
|
-
// indented test title
|
|
245
|
-
var testTitle = '';
|
|
246
|
-
test.titlePath().forEach(function(str, index) {
|
|
247
|
-
if (index !== 0) {
|
|
248
|
-
testTitle += '\n ';
|
|
249
|
-
}
|
|
250
|
-
for (var i = 0; i < index; i++) {
|
|
251
|
-
testTitle += ' ';
|
|
252
|
-
}
|
|
253
|
-
testTitle += str;
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
console.log(fmt, i + 1, testTitle, msg, stack);
|
|
257
|
-
});
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Constructs a new `Base` reporter instance.
|
|
262
|
-
*
|
|
263
|
-
* @description
|
|
264
|
-
* All other reporters generally inherit from this reporter.
|
|
265
|
-
*
|
|
266
|
-
* @public
|
|
267
|
-
* @class
|
|
268
|
-
* @memberof Mocha.reporters
|
|
269
|
-
* @param {Runner} runner - Instance triggers reporter actions.
|
|
270
|
-
* @param {Object} [options] - runner options
|
|
271
|
-
*/
|
|
272
|
-
function Base(runner, options) {
|
|
273
|
-
var failures = (this.failures = []);
|
|
274
|
-
|
|
275
|
-
if (!runner) {
|
|
276
|
-
throw new TypeError('Missing runner argument');
|
|
277
|
-
}
|
|
278
|
-
this.options = options || {};
|
|
279
|
-
this.runner = runner;
|
|
280
|
-
this.stats = runner.stats; // assigned so Reporters keep a closer reference
|
|
281
|
-
|
|
282
|
-
runner.on(EVENT_TEST_PASS, function(test) {
|
|
283
|
-
if (test.duration > test.slow()) {
|
|
284
|
-
test.speed = 'slow';
|
|
285
|
-
} else if (test.duration > test.slow() / 2) {
|
|
286
|
-
test.speed = 'medium';
|
|
287
|
-
} else {
|
|
288
|
-
test.speed = 'fast';
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
runner.on(EVENT_TEST_FAIL, function(test, err) {
|
|
293
|
-
if (showDiff(err)) {
|
|
294
|
-
stringifyDiffObjs(err);
|
|
295
|
-
}
|
|
296
|
-
test.err = err;
|
|
297
|
-
failures.push(test);
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Outputs common epilogue used by many of the bundled reporters.
|
|
303
|
-
*
|
|
304
|
-
* @public
|
|
305
|
-
* @memberof Mocha.reporters.Base
|
|
306
|
-
*/
|
|
307
|
-
Base.prototype.epilogue = function() {
|
|
308
|
-
var stats = this.stats;
|
|
309
|
-
var fmt;
|
|
310
|
-
|
|
311
|
-
console.log();
|
|
312
|
-
|
|
313
|
-
// passes
|
|
314
|
-
fmt =
|
|
315
|
-
color('bright pass', ' ') +
|
|
316
|
-
color('green', ' %d passing') +
|
|
317
|
-
color('light', ' (%s)');
|
|
318
|
-
|
|
319
|
-
console.log(fmt, stats.passes || 0, milliseconds(stats.duration));
|
|
320
|
-
|
|
321
|
-
// pending
|
|
322
|
-
if (stats.pending) {
|
|
323
|
-
fmt = color('pending', ' ') + color('pending', ' %d pending');
|
|
324
|
-
|
|
325
|
-
console.log(fmt, stats.pending);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// failures
|
|
329
|
-
if (stats.failures) {
|
|
330
|
-
fmt = color('fail', ' %d failing');
|
|
331
|
-
|
|
332
|
-
console.log(fmt, stats.failures);
|
|
333
|
-
|
|
334
|
-
Base.list(this.failures);
|
|
335
|
-
console.log();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
console.log();
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Pads the given `str` to `len`.
|
|
343
|
-
*
|
|
344
|
-
* @private
|
|
345
|
-
* @param {string} str
|
|
346
|
-
* @param {string} len
|
|
347
|
-
* @return {string}
|
|
348
|
-
*/
|
|
349
|
-
function pad(str, len) {
|
|
350
|
-
str = String(str);
|
|
351
|
-
return Array(len - str.length + 1).join(' ') + str;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Returns inline diff between 2 strings with coloured ANSI output.
|
|
356
|
-
*
|
|
357
|
-
* @private
|
|
358
|
-
* @param {String} actual
|
|
359
|
-
* @param {String} expected
|
|
360
|
-
* @return {string} Diff
|
|
361
|
-
*/
|
|
362
|
-
function inlineDiff(actual, expected) {
|
|
363
|
-
var msg = errorDiff(actual, expected);
|
|
364
|
-
|
|
365
|
-
// linenos
|
|
366
|
-
var lines = msg.split('\n');
|
|
367
|
-
if (lines.length > 4) {
|
|
368
|
-
var width = String(lines.length).length;
|
|
369
|
-
msg = lines
|
|
370
|
-
.map(function(str, i) {
|
|
371
|
-
return pad(++i, width) + ' |' + ' ' + str;
|
|
372
|
-
})
|
|
373
|
-
.join('\n');
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// legend
|
|
377
|
-
msg =
|
|
378
|
-
'\n' +
|
|
379
|
-
color('diff removed', 'actual') +
|
|
380
|
-
' ' +
|
|
381
|
-
color('diff added', 'expected') +
|
|
382
|
-
'\n\n' +
|
|
383
|
-
msg +
|
|
384
|
-
'\n';
|
|
385
|
-
|
|
386
|
-
// indent
|
|
387
|
-
msg = msg.replace(/^/gm, ' ');
|
|
388
|
-
return msg;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Returns unified diff between two strings with coloured ANSI output.
|
|
393
|
-
*
|
|
394
|
-
* @private
|
|
395
|
-
* @param {String} actual
|
|
396
|
-
* @param {String} expected
|
|
397
|
-
* @return {string} The diff.
|
|
398
|
-
*/
|
|
399
|
-
function unifiedDiff(actual, expected) {
|
|
400
|
-
var indent = ' ';
|
|
401
|
-
function cleanUp(line) {
|
|
402
|
-
if (line[0] === '+') {
|
|
403
|
-
return indent + colorLines('diff added', line);
|
|
404
|
-
}
|
|
405
|
-
if (line[0] === '-') {
|
|
406
|
-
return indent + colorLines('diff removed', line);
|
|
407
|
-
}
|
|
408
|
-
if (line.match(/@@/)) {
|
|
409
|
-
return '--';
|
|
410
|
-
}
|
|
411
|
-
if (line.match(/\\ No newline/)) {
|
|
412
|
-
return null;
|
|
413
|
-
}
|
|
414
|
-
return indent + line;
|
|
415
|
-
}
|
|
416
|
-
function notBlank(line) {
|
|
417
|
-
return typeof line !== 'undefined' && line !== null;
|
|
418
|
-
}
|
|
419
|
-
var msg = diff.createPatch('string', actual, expected);
|
|
420
|
-
var lines = msg.split('\n').splice(5);
|
|
421
|
-
return (
|
|
422
|
-
'\n ' +
|
|
423
|
-
colorLines('diff added', '+ expected') +
|
|
424
|
-
' ' +
|
|
425
|
-
colorLines('diff removed', '- actual') +
|
|
426
|
-
'\n\n' +
|
|
427
|
-
lines
|
|
428
|
-
.map(cleanUp)
|
|
429
|
-
.filter(notBlank)
|
|
430
|
-
.join('\n')
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* Returns character diff for `err`.
|
|
436
|
-
*
|
|
437
|
-
* @private
|
|
438
|
-
* @param {String} actual
|
|
439
|
-
* @param {String} expected
|
|
440
|
-
* @return {string} the diff
|
|
441
|
-
*/
|
|
442
|
-
function errorDiff(actual, expected) {
|
|
443
|
-
return diff
|
|
444
|
-
.diffWordsWithSpace(actual, expected)
|
|
445
|
-
.map(function(str) {
|
|
446
|
-
if (str.added) {
|
|
447
|
-
return colorLines('diff added', str.value);
|
|
448
|
-
}
|
|
449
|
-
if (str.removed) {
|
|
450
|
-
return colorLines('diff removed', str.value);
|
|
451
|
-
}
|
|
452
|
-
return str.value;
|
|
453
|
-
})
|
|
454
|
-
.join('');
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Colors lines for `str`, using the color `name`.
|
|
459
|
-
*
|
|
460
|
-
* @private
|
|
461
|
-
* @param {string} name
|
|
462
|
-
* @param {string} str
|
|
463
|
-
* @return {string}
|
|
464
|
-
*/
|
|
465
|
-
function colorLines(name, str) {
|
|
466
|
-
return str
|
|
467
|
-
.split('\n')
|
|
468
|
-
.map(function(str) {
|
|
469
|
-
return color(name, str);
|
|
470
|
-
})
|
|
471
|
-
.join('\n');
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Object#toString reference.
|
|
476
|
-
*/
|
|
477
|
-
var objToString = Object.prototype.toString;
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Checks that a / b have the same type.
|
|
481
|
-
*
|
|
482
|
-
* @private
|
|
483
|
-
* @param {Object} a
|
|
484
|
-
* @param {Object} b
|
|
485
|
-
* @return {boolean}
|
|
486
|
-
*/
|
|
487
|
-
function sameType(a, b) {
|
|
488
|
-
return objToString.call(a) === objToString.call(b);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
Base.abstract = true;
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* @module Base
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Module dependencies.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
var tty = require('tty');
|
|
10
|
+
var diff = require('diff');
|
|
11
|
+
var milliseconds = require('ms');
|
|
12
|
+
var utils = require('../utils');
|
|
13
|
+
var supportsColor = process.browser ? null : require('supports-color');
|
|
14
|
+
var constants = require('../runner').constants;
|
|
15
|
+
var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
|
|
16
|
+
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Expose `Base`.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
exports = module.exports = Base;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Check if both stdio streams are associated with a tty.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
var isatty = tty.isatty(1) && tty.isatty(2);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Enable coloring by default, except in the browser interface.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
exports.useColors =
|
|
35
|
+
!process.browser &&
|
|
36
|
+
(supportsColor.stdout || process.env.MOCHA_COLORS !== undefined);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Inline diffs instead of +/-
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
exports.inlineDiffs = false;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Default color map.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
exports.colors = {
|
|
49
|
+
pass: 90,
|
|
50
|
+
fail: 31,
|
|
51
|
+
'bright pass': 92,
|
|
52
|
+
'bright fail': 91,
|
|
53
|
+
'bright yellow': 93,
|
|
54
|
+
pending: 36,
|
|
55
|
+
suite: 0,
|
|
56
|
+
'error title': 0,
|
|
57
|
+
'error message': 31,
|
|
58
|
+
'error stack': 90,
|
|
59
|
+
checkmark: 32,
|
|
60
|
+
fast: 90,
|
|
61
|
+
medium: 33,
|
|
62
|
+
slow: 31,
|
|
63
|
+
green: 32,
|
|
64
|
+
light: 90,
|
|
65
|
+
'diff gutter': 90,
|
|
66
|
+
'diff added': 32,
|
|
67
|
+
'diff removed': 31
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Default symbol map.
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
exports.symbols = {
|
|
75
|
+
ok: '✓',
|
|
76
|
+
err: '✖',
|
|
77
|
+
dot: '․',
|
|
78
|
+
comma: ',',
|
|
79
|
+
bang: '!'
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// With node.js on Windows: use symbols available in terminal default fonts
|
|
83
|
+
if (process.platform === 'win32') {
|
|
84
|
+
exports.symbols.ok = '\u221A';
|
|
85
|
+
exports.symbols.err = '\u00D7';
|
|
86
|
+
exports.symbols.dot = '.';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Color `str` with the given `type`,
|
|
91
|
+
* allowing colors to be disabled,
|
|
92
|
+
* as well as user-defined color
|
|
93
|
+
* schemes.
|
|
94
|
+
*
|
|
95
|
+
* @private
|
|
96
|
+
* @param {string} type
|
|
97
|
+
* @param {string} str
|
|
98
|
+
* @return {string}
|
|
99
|
+
*/
|
|
100
|
+
var color = (exports.color = function(type, str) {
|
|
101
|
+
if (!exports.useColors) {
|
|
102
|
+
return String(str);
|
|
103
|
+
}
|
|
104
|
+
return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Expose term window size, with some defaults for when stderr is not a tty.
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
exports.window = {
|
|
112
|
+
width: 75
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
if (isatty) {
|
|
116
|
+
exports.window.width = process.stdout.getWindowSize
|
|
117
|
+
? process.stdout.getWindowSize(1)[0]
|
|
118
|
+
: tty.getWindowSize()[1];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Expose some basic cursor interactions that are common among reporters.
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
exports.cursor = {
|
|
126
|
+
hide: function() {
|
|
127
|
+
isatty && process.stdout.write('\u001b[?25l');
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
show: function() {
|
|
131
|
+
isatty && process.stdout.write('\u001b[?25h');
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
deleteLine: function() {
|
|
135
|
+
isatty && process.stdout.write('\u001b[2K');
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
beginningOfLine: function() {
|
|
139
|
+
isatty && process.stdout.write('\u001b[0G');
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
CR: function() {
|
|
143
|
+
if (isatty) {
|
|
144
|
+
exports.cursor.deleteLine();
|
|
145
|
+
exports.cursor.beginningOfLine();
|
|
146
|
+
} else {
|
|
147
|
+
process.stdout.write('\r');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
function showDiff(err) {
|
|
153
|
+
return (
|
|
154
|
+
err &&
|
|
155
|
+
err.showDiff !== false &&
|
|
156
|
+
sameType(err.actual, err.expected) &&
|
|
157
|
+
err.expected !== undefined
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function stringifyDiffObjs(err) {
|
|
162
|
+
if (!utils.isString(err.actual) || !utils.isString(err.expected)) {
|
|
163
|
+
err.actual = utils.stringify(err.actual);
|
|
164
|
+
err.expected = utils.stringify(err.expected);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Returns a diff between 2 strings with coloured ANSI output.
|
|
170
|
+
*
|
|
171
|
+
* @description
|
|
172
|
+
* The diff will be either inline or unified dependent on the value
|
|
173
|
+
* of `Base.inlineDiff`.
|
|
174
|
+
*
|
|
175
|
+
* @param {string} actual
|
|
176
|
+
* @param {string} expected
|
|
177
|
+
* @return {string} Diff
|
|
178
|
+
*/
|
|
179
|
+
var generateDiff = (exports.generateDiff = function(actual, expected) {
|
|
180
|
+
return exports.inlineDiffs
|
|
181
|
+
? inlineDiff(actual, expected)
|
|
182
|
+
: unifiedDiff(actual, expected);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Outputs the given `failures` as a list.
|
|
187
|
+
*
|
|
188
|
+
* @public
|
|
189
|
+
* @memberof Mocha.reporters.Base
|
|
190
|
+
* @variation 1
|
|
191
|
+
* @param {Object[]} failures - Each is Test instance with corresponding
|
|
192
|
+
* Error property
|
|
193
|
+
*/
|
|
194
|
+
exports.list = function(failures) {
|
|
195
|
+
console.log();
|
|
196
|
+
failures.forEach(function(test, i) {
|
|
197
|
+
// format
|
|
198
|
+
var fmt =
|
|
199
|
+
color('error title', ' %s) %s:\n') +
|
|
200
|
+
color('error message', ' %s') +
|
|
201
|
+
color('error stack', '\n%s\n');
|
|
202
|
+
|
|
203
|
+
// msg
|
|
204
|
+
var msg;
|
|
205
|
+
var err = test.err;
|
|
206
|
+
var message;
|
|
207
|
+
if (err.message && typeof err.message.toString === 'function') {
|
|
208
|
+
message = err.message + '';
|
|
209
|
+
} else if (typeof err.inspect === 'function') {
|
|
210
|
+
message = err.inspect() + '';
|
|
211
|
+
} else {
|
|
212
|
+
message = '';
|
|
213
|
+
}
|
|
214
|
+
var stack = err.stack || message;
|
|
215
|
+
var index = message ? stack.indexOf(message) : -1;
|
|
216
|
+
|
|
217
|
+
if (index === -1) {
|
|
218
|
+
msg = message;
|
|
219
|
+
} else {
|
|
220
|
+
index += message.length;
|
|
221
|
+
msg = stack.slice(0, index);
|
|
222
|
+
// remove msg from stack
|
|
223
|
+
stack = stack.slice(index + 1);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// uncaught
|
|
227
|
+
if (err.uncaught) {
|
|
228
|
+
msg = 'Uncaught ' + msg;
|
|
229
|
+
}
|
|
230
|
+
// explicitly show diff
|
|
231
|
+
if (!exports.hideDiff && showDiff(err)) {
|
|
232
|
+
stringifyDiffObjs(err);
|
|
233
|
+
fmt =
|
|
234
|
+
color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
|
|
235
|
+
var match = message.match(/^([^:]+): expected/);
|
|
236
|
+
msg = '\n ' + color('error message', match ? match[1] : msg);
|
|
237
|
+
|
|
238
|
+
msg += generateDiff(err.actual, err.expected);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// indent stack trace
|
|
242
|
+
stack = stack.replace(/^/gm, ' ');
|
|
243
|
+
|
|
244
|
+
// indented test title
|
|
245
|
+
var testTitle = '';
|
|
246
|
+
test.titlePath().forEach(function(str, index) {
|
|
247
|
+
if (index !== 0) {
|
|
248
|
+
testTitle += '\n ';
|
|
249
|
+
}
|
|
250
|
+
for (var i = 0; i < index; i++) {
|
|
251
|
+
testTitle += ' ';
|
|
252
|
+
}
|
|
253
|
+
testTitle += str;
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
console.log(fmt, i + 1, testTitle, msg, stack);
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Constructs a new `Base` reporter instance.
|
|
262
|
+
*
|
|
263
|
+
* @description
|
|
264
|
+
* All other reporters generally inherit from this reporter.
|
|
265
|
+
*
|
|
266
|
+
* @public
|
|
267
|
+
* @class
|
|
268
|
+
* @memberof Mocha.reporters
|
|
269
|
+
* @param {Runner} runner - Instance triggers reporter actions.
|
|
270
|
+
* @param {Object} [options] - runner options
|
|
271
|
+
*/
|
|
272
|
+
function Base(runner, options) {
|
|
273
|
+
var failures = (this.failures = []);
|
|
274
|
+
|
|
275
|
+
if (!runner) {
|
|
276
|
+
throw new TypeError('Missing runner argument');
|
|
277
|
+
}
|
|
278
|
+
this.options = options || {};
|
|
279
|
+
this.runner = runner;
|
|
280
|
+
this.stats = runner.stats; // assigned so Reporters keep a closer reference
|
|
281
|
+
|
|
282
|
+
runner.on(EVENT_TEST_PASS, function(test) {
|
|
283
|
+
if (test.duration > test.slow()) {
|
|
284
|
+
test.speed = 'slow';
|
|
285
|
+
} else if (test.duration > test.slow() / 2) {
|
|
286
|
+
test.speed = 'medium';
|
|
287
|
+
} else {
|
|
288
|
+
test.speed = 'fast';
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
runner.on(EVENT_TEST_FAIL, function(test, err) {
|
|
293
|
+
if (showDiff(err)) {
|
|
294
|
+
stringifyDiffObjs(err);
|
|
295
|
+
}
|
|
296
|
+
test.err = err;
|
|
297
|
+
failures.push(test);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Outputs common epilogue used by many of the bundled reporters.
|
|
303
|
+
*
|
|
304
|
+
* @public
|
|
305
|
+
* @memberof Mocha.reporters.Base
|
|
306
|
+
*/
|
|
307
|
+
Base.prototype.epilogue = function() {
|
|
308
|
+
var stats = this.stats;
|
|
309
|
+
var fmt;
|
|
310
|
+
|
|
311
|
+
console.log();
|
|
312
|
+
|
|
313
|
+
// passes
|
|
314
|
+
fmt =
|
|
315
|
+
color('bright pass', ' ') +
|
|
316
|
+
color('green', ' %d passing') +
|
|
317
|
+
color('light', ' (%s)');
|
|
318
|
+
|
|
319
|
+
console.log(fmt, stats.passes || 0, milliseconds(stats.duration));
|
|
320
|
+
|
|
321
|
+
// pending
|
|
322
|
+
if (stats.pending) {
|
|
323
|
+
fmt = color('pending', ' ') + color('pending', ' %d pending');
|
|
324
|
+
|
|
325
|
+
console.log(fmt, stats.pending);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// failures
|
|
329
|
+
if (stats.failures) {
|
|
330
|
+
fmt = color('fail', ' %d failing');
|
|
331
|
+
|
|
332
|
+
console.log(fmt, stats.failures);
|
|
333
|
+
|
|
334
|
+
Base.list(this.failures);
|
|
335
|
+
console.log();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
console.log();
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Pads the given `str` to `len`.
|
|
343
|
+
*
|
|
344
|
+
* @private
|
|
345
|
+
* @param {string} str
|
|
346
|
+
* @param {string} len
|
|
347
|
+
* @return {string}
|
|
348
|
+
*/
|
|
349
|
+
function pad(str, len) {
|
|
350
|
+
str = String(str);
|
|
351
|
+
return Array(len - str.length + 1).join(' ') + str;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Returns inline diff between 2 strings with coloured ANSI output.
|
|
356
|
+
*
|
|
357
|
+
* @private
|
|
358
|
+
* @param {String} actual
|
|
359
|
+
* @param {String} expected
|
|
360
|
+
* @return {string} Diff
|
|
361
|
+
*/
|
|
362
|
+
function inlineDiff(actual, expected) {
|
|
363
|
+
var msg = errorDiff(actual, expected);
|
|
364
|
+
|
|
365
|
+
// linenos
|
|
366
|
+
var lines = msg.split('\n');
|
|
367
|
+
if (lines.length > 4) {
|
|
368
|
+
var width = String(lines.length).length;
|
|
369
|
+
msg = lines
|
|
370
|
+
.map(function(str, i) {
|
|
371
|
+
return pad(++i, width) + ' |' + ' ' + str;
|
|
372
|
+
})
|
|
373
|
+
.join('\n');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// legend
|
|
377
|
+
msg =
|
|
378
|
+
'\n' +
|
|
379
|
+
color('diff removed', 'actual') +
|
|
380
|
+
' ' +
|
|
381
|
+
color('diff added', 'expected') +
|
|
382
|
+
'\n\n' +
|
|
383
|
+
msg +
|
|
384
|
+
'\n';
|
|
385
|
+
|
|
386
|
+
// indent
|
|
387
|
+
msg = msg.replace(/^/gm, ' ');
|
|
388
|
+
return msg;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Returns unified diff between two strings with coloured ANSI output.
|
|
393
|
+
*
|
|
394
|
+
* @private
|
|
395
|
+
* @param {String} actual
|
|
396
|
+
* @param {String} expected
|
|
397
|
+
* @return {string} The diff.
|
|
398
|
+
*/
|
|
399
|
+
function unifiedDiff(actual, expected) {
|
|
400
|
+
var indent = ' ';
|
|
401
|
+
function cleanUp(line) {
|
|
402
|
+
if (line[0] === '+') {
|
|
403
|
+
return indent + colorLines('diff added', line);
|
|
404
|
+
}
|
|
405
|
+
if (line[0] === '-') {
|
|
406
|
+
return indent + colorLines('diff removed', line);
|
|
407
|
+
}
|
|
408
|
+
if (line.match(/@@/)) {
|
|
409
|
+
return '--';
|
|
410
|
+
}
|
|
411
|
+
if (line.match(/\\ No newline/)) {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
return indent + line;
|
|
415
|
+
}
|
|
416
|
+
function notBlank(line) {
|
|
417
|
+
return typeof line !== 'undefined' && line !== null;
|
|
418
|
+
}
|
|
419
|
+
var msg = diff.createPatch('string', actual, expected);
|
|
420
|
+
var lines = msg.split('\n').splice(5);
|
|
421
|
+
return (
|
|
422
|
+
'\n ' +
|
|
423
|
+
colorLines('diff added', '+ expected') +
|
|
424
|
+
' ' +
|
|
425
|
+
colorLines('diff removed', '- actual') +
|
|
426
|
+
'\n\n' +
|
|
427
|
+
lines
|
|
428
|
+
.map(cleanUp)
|
|
429
|
+
.filter(notBlank)
|
|
430
|
+
.join('\n')
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Returns character diff for `err`.
|
|
436
|
+
*
|
|
437
|
+
* @private
|
|
438
|
+
* @param {String} actual
|
|
439
|
+
* @param {String} expected
|
|
440
|
+
* @return {string} the diff
|
|
441
|
+
*/
|
|
442
|
+
function errorDiff(actual, expected) {
|
|
443
|
+
return diff
|
|
444
|
+
.diffWordsWithSpace(actual, expected)
|
|
445
|
+
.map(function(str) {
|
|
446
|
+
if (str.added) {
|
|
447
|
+
return colorLines('diff added', str.value);
|
|
448
|
+
}
|
|
449
|
+
if (str.removed) {
|
|
450
|
+
return colorLines('diff removed', str.value);
|
|
451
|
+
}
|
|
452
|
+
return str.value;
|
|
453
|
+
})
|
|
454
|
+
.join('');
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Colors lines for `str`, using the color `name`.
|
|
459
|
+
*
|
|
460
|
+
* @private
|
|
461
|
+
* @param {string} name
|
|
462
|
+
* @param {string} str
|
|
463
|
+
* @return {string}
|
|
464
|
+
*/
|
|
465
|
+
function colorLines(name, str) {
|
|
466
|
+
return str
|
|
467
|
+
.split('\n')
|
|
468
|
+
.map(function(str) {
|
|
469
|
+
return color(name, str);
|
|
470
|
+
})
|
|
471
|
+
.join('\n');
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Object#toString reference.
|
|
476
|
+
*/
|
|
477
|
+
var objToString = Object.prototype.toString;
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Checks that a / b have the same type.
|
|
481
|
+
*
|
|
482
|
+
* @private
|
|
483
|
+
* @param {Object} a
|
|
484
|
+
* @param {Object} b
|
|
485
|
+
* @return {boolean}
|
|
486
|
+
*/
|
|
487
|
+
function sameType(a, b) {
|
|
488
|
+
return objToString.call(a) === objToString.call(b);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
Base.abstract = true;
|