1 | ;
|
2 |
|
3 | /*!
|
4 | * mocha
|
5 | * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
|
6 | * MIT Licensed
|
7 | */
|
8 |
|
9 | var escapeRe = require('escape-string-regexp');
|
10 | var path = require('path');
|
11 | var builtinReporters = require('./reporters');
|
12 | var growl = require('./growl');
|
13 | var utils = require('./utils');
|
14 | var mocharc = require('./mocharc.json');
|
15 | var errors = require('./errors');
|
16 | var Suite = require('./suite');
|
17 | var createStatsCollector = require('./stats-collector');
|
18 | var createInvalidReporterError = errors.createInvalidReporterError;
|
19 | var createInvalidInterfaceError = errors.createInvalidInterfaceError;
|
20 | var EVENT_FILE_PRE_REQUIRE = Suite.constants.EVENT_FILE_PRE_REQUIRE;
|
21 | var EVENT_FILE_POST_REQUIRE = Suite.constants.EVENT_FILE_POST_REQUIRE;
|
22 | var EVENT_FILE_REQUIRE = Suite.constants.EVENT_FILE_REQUIRE;
|
23 | var sQuote = utils.sQuote;
|
24 |
|
25 | exports = module.exports = Mocha;
|
26 |
|
27 | /**
|
28 | * To require local UIs and reporters when running in node.
|
29 | */
|
30 |
|
31 | if (!process.browser) {
|
32 | var cwd = process.cwd();
|
33 | module.paths.push(cwd, path.join(cwd, 'node_modules'));
|
34 | }
|
35 |
|
36 | /**
|
37 | * Expose internals.
|
38 | */
|
39 |
|
40 | /**
|
41 | * @public
|
42 | * @class utils
|
43 | * @memberof Mocha
|
44 | */
|
45 | exports.utils = utils;
|
46 | exports.interfaces = require('./interfaces');
|
47 | /**
|
48 | * @public
|
49 | * @memberof Mocha
|
50 | */
|
51 | exports.reporters = builtinReporters;
|
52 | exports.Runnable = require('./runnable');
|
53 | exports.Context = require('./context');
|
54 | /**
|
55 | *
|
56 | * @memberof Mocha
|
57 | */
|
58 | exports.Runner = require('./runner');
|
59 | exports.Suite = Suite;
|
60 | exports.Hook = require('./hook');
|
61 | exports.Test = require('./test');
|
62 |
|
63 | /**
|
64 | * Constructs a new Mocha instance with `options`.
|
65 | *
|
66 | * @public
|
67 | * @class Mocha
|
68 | * @param {Object} [options] - Settings object.
|
69 | * @param {boolean} [options.allowUncaught] - Propagate uncaught errors?
|
70 | * @param {boolean} [options.asyncOnly] - Force `done` callback or promise?
|
71 | * @param {boolean} [options.bail] - Bail after first test failure?
|
72 | * @param {boolean} [options.checkLeaks] - If true, check leaks.
|
73 | * @param {boolean} [options.delay] - Delay root suite execution?
|
74 | * @param {boolean} [options.enableTimeouts] - Enable timeouts?
|
75 | * @param {string} [options.fgrep] - Test filter given string.
|
76 | * @param {boolean} [options.forbidOnly] - Tests marked `only` fail the suite?
|
77 | * @param {boolean} [options.forbidPending] - Pending tests fail the suite?
|
78 | * @param {boolean} [options.fullStackTrace] - Full stacktrace upon failure?
|
79 | * @param {string[]} [options.global] - Variables expected in global scope.
|
80 | * @param {RegExp|string} [options.grep] - Test filter given regular expression.
|
81 | * @param {boolean} [options.growl] - Enable desktop notifications?
|
82 | * @param {boolean} [options.hideDiff] - Suppress diffs from failures?
|
83 | * @param {boolean} [options.ignoreLeaks] - Ignore global leaks?
|
84 | * @param {boolean} [options.invert] - Invert test filter matches?
|
85 | * @param {boolean} [options.noHighlighting] - Disable syntax highlighting?
|
86 | * @param {string} [options.reporter] - Reporter name.
|
87 | * @param {Object} [options.reporterOption] - Reporter settings object.
|
88 | * @param {number} [options.retries] - Number of times to retry failed tests.
|
89 | * @param {number} [options.slow] - Slow threshold value.
|
90 | * @param {number|string} [options.timeout] - Timeout threshold value.
|
91 | * @param {string} [options.ui] - Interface name.
|
92 | * @param {boolean} [options.color] - Color TTY output from reporter?
|
93 | * @param {boolean} [options.useInlineDiffs] - Use inline diffs?
|
94 | */
|
95 | function Mocha(options) {
|
96 | options = utils.assign({}, mocharc, options || {});
|
97 | this.files = [];
|
98 | this.options = options;
|
99 | // root suite
|
100 | this.suite = new exports.Suite('', new exports.Context(), true);
|
101 |
|
102 | if ('useColors' in options) {
|
103 | utils.deprecate(
|
104 | 'useColors is DEPRECATED and will be removed from a future version of Mocha. Instead, use the "color" option'
|
105 | );
|
106 | options.color = 'color' in options ? options.color : options.useColors;
|
107 | }
|
108 |
|
109 | // Globals are passed in as options.global, with options.globals for backward compatibility.
|
110 | options.globals = options.global || options.globals || [];
|
111 | delete options.global;
|
112 |
|
113 | this.grep(options.grep)
|
114 | .fgrep(options.fgrep)
|
115 | .ui(options.ui)
|
116 | .bail(options.bail)
|
117 | .reporter(options.reporter, options.reporterOptions)
|
118 | .useColors(options.color)
|
119 | .slow(options.slow)
|
120 | .useInlineDiffs(options.inlineDiffs)
|
121 | .globals(options.globals);
|
122 |
|
123 | if ('enableTimeouts' in options) {
|
124 | utils.deprecate(
|
125 | 'enableTimeouts is DEPRECATED and will be removed from a future version of Mocha. Instead, use "timeout: false" to disable timeouts.'
|
126 | );
|
127 | if (options.enableTimeouts === false) {
|
128 | this.timeout(0);
|
129 | }
|
130 | }
|
131 |
|
132 | // this guard exists because Suite#timeout does not consider `undefined` to be valid input
|
133 | if (typeof options.timeout !== 'undefined') {
|
134 | this.timeout(options.timeout === false ? 0 : options.timeout);
|
135 | }
|
136 |
|
137 | if ('retries' in options) {
|
138 | this.retries(options.retries);
|
139 | }
|
140 |
|
141 | if ('diff' in options) {
|
142 | this.hideDiff(!options.diff);
|
143 | }
|
144 |
|
145 | [
|
146 | 'allowUncaught',
|
147 | 'asyncOnly',
|
148 | 'checkLeaks',
|
149 | 'delay',
|
150 | 'forbidOnly',
|
151 | 'forbidPending',
|
152 | 'fullTrace',
|
153 | 'growl',
|
154 | 'invert'
|
155 | ].forEach(function(opt) {
|
156 | if (options[opt]) {
|
157 | this[opt]();
|
158 | }
|
159 | }, this);
|
160 | }
|
161 |
|
162 | /**
|
163 | * Enables or disables bailing on the first failure.
|
164 | *
|
165 | * @public
|
166 | * @see {@link https://mochajs.org/#-b---bail|CLI option}
|
167 | * @param {boolean} [bail=true] - Whether to bail on first error.
|
168 | * @returns {Mocha} this
|
169 | * @chainable
|
170 | */
|
171 | Mocha.prototype.bail = function(bail) {
|
172 | if (!arguments.length) {
|
173 | bail = true;
|
174 | }
|
175 | this.suite.bail(bail);
|
176 | return this;
|
177 | };
|
178 |
|
179 | /**
|
180 | * @summary
|
181 | * Adds `file` to be loaded for execution.
|
182 | *
|
183 | * @description
|
184 | * Useful for generic setup code that must be included within test suite.
|
185 | *
|
186 | * @public
|
187 | * @see {@link https://mochajs.org/#--file-file|CLI option}
|
188 | * @param {string} file - Pathname of file to be loaded.
|
189 | * @returns {Mocha} this
|
190 | * @chainable
|
191 | */
|
192 | Mocha.prototype.addFile = function(file) {
|
193 | this.files.push(file);
|
194 | return this;
|
195 | };
|
196 |
|
197 | /**
|
198 | * Sets reporter to `reporter`, defaults to "spec".
|
199 | *
|
200 | * @public
|
201 | * @see {@link https://mochajs.org/#-r---reporter-name|CLI option}
|
202 | * @see {@link https://mochajs.org/#reporters|Reporters}
|
203 | * @param {String|Function} reporter - Reporter name or constructor.
|
204 | * @param {Object} [reporterOptions] - Options used to configure the reporter.
|
205 | * @returns {Mocha} this
|
206 | * @chainable
|
207 | * @throws {Error} if requested reporter cannot be loaded
|
208 | * @example
|
209 | *
|
210 | * // Use XUnit reporter and direct its output to file
|
211 | * mocha.reporter('xunit', { output: '/path/to/testspec.xunit.xml' });
|
212 | */
|
213 | Mocha.prototype.reporter = function(reporter, reporterOptions) {
|
214 | if (typeof reporter === 'function') {
|
215 | this._reporter = reporter;
|
216 | } else {
|
217 | reporter = reporter || 'spec';
|
218 | var _reporter;
|
219 | // Try to load a built-in reporter.
|
220 | if (builtinReporters[reporter]) {
|
221 | _reporter = builtinReporters[reporter];
|
222 | }
|
223 | // Try to load reporters from process.cwd() and node_modules
|
224 | if (!_reporter) {
|
225 | try {
|
226 | _reporter = require(reporter);
|
227 | } catch (err) {
|
228 | if (
|
229 | err.code !== 'MODULE_NOT_FOUND' ||
|
230 | err.message.indexOf('Cannot find module') !== -1
|
231 | ) {
|
232 | // Try to load reporters from a path (absolute or relative)
|
233 | try {
|
234 | _reporter = require(path.resolve(process.cwd(), reporter));
|
235 | } catch (_err) {
|
236 | _err.code !== 'MODULE_NOT_FOUND' ||
|
237 | _err.message.indexOf('Cannot find module') !== -1
|
238 | ? console.warn(sQuote(reporter) + ' reporter not found')
|
239 | : console.warn(
|
240 | sQuote(reporter) +
|
241 | ' reporter blew up with error:\n' +
|
242 | err.stack
|
243 | );
|
244 | }
|
245 | } else {
|
246 | console.warn(
|
247 | sQuote(reporter) + ' reporter blew up with error:\n' + err.stack
|
248 | );
|
249 | }
|
250 | }
|
251 | }
|
252 | if (!_reporter) {
|
253 | throw createInvalidReporterError(
|
254 | 'invalid reporter ' + sQuote(reporter),
|
255 | reporter
|
256 | );
|
257 | }
|
258 | this._reporter = _reporter;
|
259 | }
|
260 | this.options.reporterOptions = reporterOptions;
|
261 | return this;
|
262 | };
|
263 |
|
264 | /**
|
265 | * Sets test UI `name`, defaults to "bdd".
|
266 | *
|
267 | * @public
|
268 | * @see {@link https://mochajs.org/#-u---ui-name|CLI option}
|
269 | * @see {@link https://mochajs.org/#interfaces|Interface DSLs}
|
270 | * @param {string|Function} [ui=bdd] - Interface name or class.
|
271 | * @returns {Mocha} this
|
272 | * @chainable
|
273 | * @throws {Error} if requested interface cannot be loaded
|
274 | */
|
275 | Mocha.prototype.ui = function(ui) {
|
276 | var bindInterface;
|
277 | if (typeof ui === 'function') {
|
278 | bindInterface = ui;
|
279 | } else {
|
280 | ui = ui || 'bdd';
|
281 | bindInterface = exports.interfaces[ui];
|
282 | if (!bindInterface) {
|
283 | try {
|
284 | bindInterface = require(ui);
|
285 | } catch (err) {
|
286 | throw createInvalidInterfaceError(
|
287 | 'invalid interface ' + sQuote(ui),
|
288 | ui
|
289 | );
|
290 | }
|
291 | }
|
292 | }
|
293 | bindInterface(this.suite);
|
294 |
|
295 | this.suite.on(EVENT_FILE_PRE_REQUIRE, function(context) {
|
296 | exports.afterEach = context.afterEach || context.teardown;
|
297 | exports.after = context.after || context.suiteTeardown;
|
298 | exports.beforeEach = context.beforeEach || context.setup;
|
299 | exports.before = context.before || context.suiteSetup;
|
300 | exports.describe = context.describe || context.suite;
|
301 | exports.it = context.it || context.test;
|
302 | exports.xit = context.xit || (context.test && context.test.skip);
|
303 | exports.setup = context.setup || context.beforeEach;
|
304 | exports.suiteSetup = context.suiteSetup || context.before;
|
305 | exports.suiteTeardown = context.suiteTeardown || context.after;
|
306 | exports.suite = context.suite || context.describe;
|
307 | exports.teardown = context.teardown || context.afterEach;
|
308 | exports.test = context.test || context.it;
|
309 | exports.run = context.run;
|
310 | });
|
311 |
|
312 | return this;
|
313 | };
|
314 |
|
315 | /**
|
316 | * Loads `files` prior to execution.
|
317 | *
|
318 | * @description
|
319 | * The implementation relies on Node's `require` to execute
|
320 | * the test interface functions and will be subject to its cache.
|
321 | *
|
322 | * @private
|
323 | * @see {@link Mocha#addFile}
|
324 | * @see {@link Mocha#run}
|
325 | * @see {@link Mocha#unloadFiles}
|
326 | * @param {Function} [fn] - Callback invoked upon completion.
|
327 | */
|
328 | Mocha.prototype.loadFiles = function(fn) {
|
329 | var self = this;
|
330 | var suite = this.suite;
|
331 | this.files.forEach(function(file) {
|
332 | file = path.resolve(file);
|
333 | suite.emit(EVENT_FILE_PRE_REQUIRE, global, file, self);
|
334 | suite.emit(EVENT_FILE_REQUIRE, require(file), file, self);
|
335 | suite.emit(EVENT_FILE_POST_REQUIRE, global, file, self);
|
336 | });
|
337 | fn && fn();
|
338 | };
|
339 |
|
340 | /**
|
341 | * Removes a previously loaded file from Node's `require` cache.
|
342 | *
|
343 | * @private
|
344 | * @static
|
345 | * @see {@link Mocha#unloadFiles}
|
346 | * @param {string} file - Pathname of file to be unloaded.
|
347 | */
|
348 | Mocha.unloadFile = function(file) {
|
349 | delete require.cache[require.resolve(file)];
|
350 | };
|
351 |
|
352 | /**
|
353 | * Unloads `files` from Node's `require` cache.
|
354 | *
|
355 | * @description
|
356 | * This allows files to be "freshly" reloaded, providing the ability
|
357 | * to reuse a Mocha instance programmatically.
|
358 | *
|
359 | * <strong>Intended for consumers — not used internally</strong>
|
360 | *
|
361 | * @public
|
362 | * @see {@link Mocha.unloadFile}
|
363 | * @see {@link Mocha#loadFiles}
|
364 | * @see {@link Mocha#run}
|
365 | * @returns {Mocha} this
|
366 | * @chainable
|
367 | */
|
368 | Mocha.prototype.unloadFiles = function() {
|
369 | this.files.forEach(Mocha.unloadFile);
|
370 | return this;
|
371 | };
|
372 |
|
373 | /**
|
374 | * Sets `grep` filter after escaping RegExp special characters.
|
375 | *
|
376 | * @public
|
377 | * @see {@link Mocha#grep}
|
378 | * @param {string} str - Value to be converted to a regexp.
|
379 | * @returns {Mocha} this
|
380 | * @chainable
|
381 | * @example
|
382 | *
|
383 | * // Select tests whose full title begins with `"foo"` followed by a period
|
384 | * mocha.fgrep('foo.');
|
385 | */
|
386 | Mocha.prototype.fgrep = function(str) {
|
387 | if (!str) {
|
388 | return this;
|
389 | }
|
390 | return this.grep(new RegExp(escapeRe(str)));
|
391 | };
|
392 |
|
393 | /**
|
394 | * @summary
|
395 | * Sets `grep` filter used to select specific tests for execution.
|
396 | *
|
397 | * @description
|
398 | * If `re` is a regexp-like string, it will be converted to regexp.
|
399 | * The regexp is tested against the full title of each test (i.e., the
|
400 | * name of the test preceded by titles of each its ancestral suites).
|
401 | * As such, using an <em>exact-match</em> fixed pattern against the
|
402 | * test name itself will not yield any matches.
|
403 | * <br>
|
404 | * <strong>Previous filter value will be overwritten on each call!</strong>
|
405 | *
|
406 | * @public
|
407 | * @see {@link https://mochajs.org/#-g---grep-pattern|CLI option}
|
408 | * @see {@link Mocha#fgrep}
|
409 | * @see {@link Mocha#invert}
|
410 | * @param {RegExp|String} re - Regular expression used to select tests.
|
411 | * @return {Mocha} this
|
412 | * @chainable
|
413 | * @example
|
414 | *
|
415 | * // Select tests whose full title contains `"match"`, ignoring case
|
416 | * mocha.grep(/match/i);
|
417 | * @example
|
418 | *
|
419 | * // Same as above but with regexp-like string argument
|
420 | * mocha.grep('/match/i');
|
421 | * @example
|
422 | *
|
423 | * // ## Anti-example
|
424 | * // Given embedded test `it('only-this-test')`...
|
425 | * mocha.grep('/^only-this-test$/'); // NO! Use `.only()` to do this!
|
426 | */
|
427 | Mocha.prototype.grep = function(re) {
|
428 | if (utils.isString(re)) {
|
429 | // extract args if it's regex-like, i.e: [string, pattern, flag]
|
430 | var arg = re.match(/^\/(.*)\/(g|i|)$|.*/);
|
431 | this.options.grep = new RegExp(arg[1] || arg[0], arg[2]);
|
432 | } else {
|
433 | this.options.grep = re;
|
434 | }
|
435 | return this;
|
436 | };
|
437 |
|
438 | /**
|
439 | * Inverts `grep` matches.
|
440 | *
|
441 | * @public
|
442 | * @see {@link Mocha#grep}
|
443 | * @return {Mocha} this
|
444 | * @chainable
|
445 | * @example
|
446 | *
|
447 | * // Select tests whose full title does *not* contain `"match"`, ignoring case
|
448 | * mocha.grep(/match/i).invert();
|
449 | */
|
450 | Mocha.prototype.invert = function() {
|
451 | this.options.invert = true;
|
452 | return this;
|
453 | };
|
454 |
|
455 | /**
|
456 | * Enables or disables ignoring global leaks.
|
457 | *
|
458 | * @public
|
459 | * @see {@link Mocha#checkLeaks}
|
460 | * @param {boolean} ignoreLeaks - Whether to ignore global leaks.
|
461 | * @return {Mocha} this
|
462 | * @chainable
|
463 | * @example
|
464 | *
|
465 | * // Ignore global leaks
|
466 | * mocha.ignoreLeaks(true);
|
467 | */
|
468 | Mocha.prototype.ignoreLeaks = function(ignoreLeaks) {
|
469 | this.options.ignoreLeaks = Boolean(ignoreLeaks);
|
470 | return this;
|
471 | };
|
472 |
|
473 | /**
|
474 | * Enables checking for global variables leaked while running tests.
|
475 | *
|
476 | * @public
|
477 | * @see {@link https://mochajs.org/#--check-leaks|CLI option}
|
478 | * @see {@link Mocha#ignoreLeaks}
|
479 | * @return {Mocha} this
|
480 | * @chainable
|
481 | */
|
482 | Mocha.prototype.checkLeaks = function() {
|
483 | this.options.ignoreLeaks = false;
|
484 | return this;
|
485 | };
|
486 |
|
487 | /**
|
488 | * Displays full stack trace upon test failure.
|
489 | *
|
490 | * @public
|
491 | * @return {Mocha} this
|
492 | * @chainable
|
493 | */
|
494 | Mocha.prototype.fullTrace = function() {
|
495 | this.options.fullStackTrace = true;
|
496 | return this;
|
497 | };
|
498 |
|
499 | /**
|
500 | * Enables desktop notification support if prerequisite software installed.
|
501 | *
|
502 | * @public
|
503 | * @see {@link Mocha#isGrowlCapable}
|
504 | * @see {@link Mocha#_growl}
|
505 | * @return {Mocha} this
|
506 | * @chainable
|
507 | */
|
508 | Mocha.prototype.growl = function() {
|
509 | this.options.growl = this.isGrowlCapable();
|
510 | if (!this.options.growl) {
|
511 | var detail = process.browser
|
512 | ? 'notification support not available in this browser...'
|
513 | : 'notification support prerequisites not installed...';
|
514 | console.error(detail + ' cannot enable!');
|
515 | }
|
516 | return this;
|
517 | };
|
518 |
|
519 | /**
|
520 | * @summary
|
521 | * Determines if Growl support seems likely.
|
522 | *
|
523 | * @description
|
524 | * <strong>Not available when run in browser.</strong>
|
525 | *
|
526 | * @private
|
527 | * @see {@link Growl#isCapable}
|
528 | * @see {@link Mocha#growl}
|
529 | * @return {boolean} whether Growl support can be expected
|
530 | */
|
531 | Mocha.prototype.isGrowlCapable = growl.isCapable;
|
532 |
|
533 | /**
|
534 | * Implements desktop notifications using a pseudo-reporter.
|
535 | *
|
536 | * @private
|
537 | * @see {@link Mocha#growl}
|
538 | * @see {@link Growl#notify}
|
539 | * @param {Runner} runner - Runner instance.
|
540 | */
|
541 | Mocha.prototype._growl = growl.notify;
|
542 |
|
543 | /**
|
544 | * Specifies whitelist of variable names to be expected in global scope.
|
545 | *
|
546 | * @public
|
547 | * @see {@link https://mochajs.org/#-global-variable-name|CLI option}
|
548 | * @see {@link Mocha#checkLeaks}
|
549 | * @param {String[]|String} globals - Accepted global variable name(s).
|
550 | * @return {Mocha} this
|
551 | * @chainable
|
552 | * @example
|
553 | *
|
554 | * // Specify variables to be expected in global scope
|
555 | * mocha.globals(['jQuery', 'MyLib']);
|
556 | */
|
557 | Mocha.prototype.globals = function(globals) {
|
558 | this.options.globals = this.options.globals
|
559 | .concat(globals)
|
560 | .filter(Boolean)
|
561 | .filter(function(elt, idx, arr) {
|
562 | return arr.indexOf(elt) === idx;
|
563 | });
|
564 | return this;
|
565 | };
|
566 |
|
567 | /**
|
568 | * Enables or disables TTY color output by screen-oriented reporters.
|
569 | *
|
570 | * @public
|
571 | * @param {boolean} colors - Whether to enable color output.
|
572 | * @return {Mocha} this
|
573 | * @chainable
|
574 | */
|
575 | Mocha.prototype.useColors = function(colors) {
|
576 | if (colors !== undefined) {
|
577 | this.options.useColors = colors;
|
578 | }
|
579 | return this;
|
580 | };
|
581 |
|
582 | /**
|
583 | * Determines if reporter should use inline diffs (rather than +/-)
|
584 | * in test failure output.
|
585 | *
|
586 | * @public
|
587 | * @param {boolean} inlineDiffs - Whether to use inline diffs.
|
588 | * @return {Mocha} this
|
589 | * @chainable
|
590 | */
|
591 | Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
|
592 | this.options.useInlineDiffs = inlineDiffs !== undefined && inlineDiffs;
|
593 | return this;
|
594 | };
|
595 |
|
596 | /**
|
597 | * Determines if reporter should include diffs in test failure output.
|
598 | *
|
599 | * @public
|
600 | * @param {boolean} hideDiff - Whether to hide diffs.
|
601 | * @return {Mocha} this
|
602 | * @chainable
|
603 | */
|
604 | Mocha.prototype.hideDiff = function(hideDiff) {
|
605 | this.options.hideDiff = hideDiff !== undefined && hideDiff;
|
606 | return this;
|
607 | };
|
608 |
|
609 | /**
|
610 | * @summary
|
611 | * Sets timeout threshold value.
|
612 | *
|
613 | * @description
|
614 | * A string argument can use shorthand (such as "2s") and will be converted.
|
615 | * If the value is `0`, timeouts will be disabled.
|
616 | *
|
617 | * @public
|
618 | * @see {@link https://mochajs.org/#-t---timeout-ms|CLI option}
|
619 | * @see {@link https://mochajs.org/#--no-timeouts|CLI option}
|
620 | * @see {@link https://mochajs.org/#timeouts|Timeouts}
|
621 | * @see {@link Mocha#enableTimeouts}
|
622 | * @param {number|string} msecs - Timeout threshold value.
|
623 | * @return {Mocha} this
|
624 | * @chainable
|
625 | * @example
|
626 | *
|
627 | * // Sets timeout to one second
|
628 | * mocha.timeout(1000);
|
629 | * @example
|
630 | *
|
631 | * // Same as above but using string argument
|
632 | * mocha.timeout('1s');
|
633 | */
|
634 | Mocha.prototype.timeout = function(msecs) {
|
635 | this.suite.timeout(msecs);
|
636 | return this;
|
637 | };
|
638 |
|
639 | /**
|
640 | * Sets the number of times to retry failed tests.
|
641 | *
|
642 | * @public
|
643 | * @see {@link https://mochajs.org/#retry-tests|Retry Tests}
|
644 | * @param {number} retry - Number of times to retry failed tests.
|
645 | * @return {Mocha} this
|
646 | * @chainable
|
647 | * @example
|
648 | *
|
649 | * // Allow any failed test to retry one more time
|
650 | * mocha.retries(1);
|
651 | */
|
652 | Mocha.prototype.retries = function(n) {
|
653 | this.suite.retries(n);
|
654 | return this;
|
655 | };
|
656 |
|
657 | /**
|
658 | * Sets slowness threshold value.
|
659 | *
|
660 | * @public
|
661 | * @see {@link https://mochajs.org/#-s---slow-ms|CLI option}
|
662 | * @param {number} msecs - Slowness threshold value.
|
663 | * @return {Mocha} this
|
664 | * @chainable
|
665 | * @example
|
666 | *
|
667 | * // Sets "slow" threshold to half a second
|
668 | * mocha.slow(500);
|
669 | * @example
|
670 | *
|
671 | * // Same as above but using string argument
|
672 | * mocha.slow('0.5s');
|
673 | */
|
674 | Mocha.prototype.slow = function(msecs) {
|
675 | this.suite.slow(msecs);
|
676 | return this;
|
677 | };
|
678 |
|
679 | /**
|
680 | * Enables or disables timeouts.
|
681 | *
|
682 | * @public
|
683 | * @see {@link https://mochajs.org/#-t---timeout-ms|CLI option}
|
684 | * @see {@link https://mochajs.org/#--no-timeouts|CLI option}
|
685 | * @param {boolean} enableTimeouts - Whether to enable timeouts.
|
686 | * @return {Mocha} this
|
687 | * @chainable
|
688 | */
|
689 | Mocha.prototype.enableTimeouts = function(enableTimeouts) {
|
690 | this.suite.enableTimeouts(
|
691 | arguments.length && enableTimeouts !== undefined ? enableTimeouts : true
|
692 | );
|
693 | return this;
|
694 | };
|
695 |
|
696 | /**
|
697 | * Forces all tests to either accept a `done` callback or return a promise.
|
698 | *
|
699 | * @public
|
700 | * @return {Mocha} this
|
701 | * @chainable
|
702 | */
|
703 | Mocha.prototype.asyncOnly = function() {
|
704 | this.options.asyncOnly = true;
|
705 | return this;
|
706 | };
|
707 |
|
708 | /**
|
709 | * Disables syntax highlighting (in browser).
|
710 | *
|
711 | * @public
|
712 | * @return {Mocha} this
|
713 | * @chainable
|
714 | */
|
715 | Mocha.prototype.noHighlighting = function() {
|
716 | this.options.noHighlighting = true;
|
717 | return this;
|
718 | };
|
719 |
|
720 | /**
|
721 | * Enables uncaught errors to propagate (in browser).
|
722 | *
|
723 | * @public
|
724 | * @return {Mocha} this
|
725 | * @chainable
|
726 | */
|
727 | Mocha.prototype.allowUncaught = function() {
|
728 | this.options.allowUncaught = true;
|
729 | return this;
|
730 | };
|
731 |
|
732 | /**
|
733 | * @summary
|
734 | * Delays root suite execution.
|
735 | *
|
736 | * @description
|
737 | * Used to perform asynch operations before any suites are run.
|
738 | *
|
739 | * @public
|
740 | * @see {@link https://mochajs.org/#delayed-root-suite|delayed root suite}
|
741 | * @returns {Mocha} this
|
742 | * @chainable
|
743 | */
|
744 | Mocha.prototype.delay = function delay() {
|
745 | this.options.delay = true;
|
746 | return this;
|
747 | };
|
748 |
|
749 | /**
|
750 | * Causes tests marked `only` to fail the suite.
|
751 | *
|
752 | * @public
|
753 | * @returns {Mocha} this
|
754 | * @chainable
|
755 | */
|
756 | Mocha.prototype.forbidOnly = function() {
|
757 | this.options.forbidOnly = true;
|
758 | return this;
|
759 | };
|
760 |
|
761 | /**
|
762 | * Causes pending tests and tests marked `skip` to fail the suite.
|
763 | *
|
764 | * @public
|
765 | * @returns {Mocha} this
|
766 | * @chainable
|
767 | */
|
768 | Mocha.prototype.forbidPending = function() {
|
769 | this.options.forbidPending = true;
|
770 | return this;
|
771 | };
|
772 |
|
773 | /**
|
774 | * Mocha version as specified by "package.json".
|
775 | *
|
776 | * @name Mocha#version
|
777 | * @type string
|
778 | * @readonly
|
779 | */
|
780 | Object.defineProperty(Mocha.prototype, 'version', {
|
781 | value: require('../package.json').version,
|
782 | configurable: false,
|
783 | enumerable: true,
|
784 | writable: false
|
785 | });
|
786 |
|
787 | /**
|
788 | * Callback to be invoked when test execution is complete.
|
789 | *
|
790 | * @callback DoneCB
|
791 | * @param {number} failures - Number of failures that occurred.
|
792 | */
|
793 |
|
794 | /**
|
795 | * Runs root suite and invokes `fn()` when complete.
|
796 | *
|
797 | * @description
|
798 | * To run tests multiple times (or to run tests in files that are
|
799 | * already in the `require` cache), make sure to clear them from
|
800 | * the cache first!
|
801 | *
|
802 | * @public
|
803 | * @see {@link Mocha#loadFiles}
|
804 | * @see {@link Mocha#unloadFiles}
|
805 | * @see {@link Runner#run}
|
806 | * @param {DoneCB} [fn] - Callback invoked when test execution completed.
|
807 | * @return {Runner} runner instance
|
808 | */
|
809 | Mocha.prototype.run = function(fn) {
|
810 | if (this.files.length) {
|
811 | this.loadFiles();
|
812 | }
|
813 | var suite = this.suite;
|
814 | var options = this.options;
|
815 | options.files = this.files;
|
816 | var runner = new exports.Runner(suite, options.delay);
|
817 | createStatsCollector(runner);
|
818 | var reporter = new this._reporter(runner, options);
|
819 | runner.ignoreLeaks = options.ignoreLeaks !== false;
|
820 | runner.fullStackTrace = options.fullStackTrace;
|
821 | runner.asyncOnly = options.asyncOnly;
|
822 | runner.allowUncaught = options.allowUncaught;
|
823 | runner.forbidOnly = options.forbidOnly;
|
824 | runner.forbidPending = options.forbidPending;
|
825 | if (options.grep) {
|
826 | runner.grep(options.grep, options.invert);
|
827 | }
|
828 | if (options.globals) {
|
829 | runner.globals(options.globals);
|
830 | }
|
831 | if (options.growl) {
|
832 | this._growl(runner);
|
833 | }
|
834 | if (options.useColors !== undefined) {
|
835 | exports.reporters.Base.useColors = options.useColors;
|
836 | }
|
837 | exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
|
838 | exports.reporters.Base.hideDiff = options.hideDiff;
|
839 |
|
840 | function done(failures) {
|
841 | fn = fn || utils.noop;
|
842 | if (reporter.done) {
|
843 | reporter.done(failures, fn);
|
844 | } else {
|
845 | fn(failures);
|
846 | }
|
847 | }
|
848 |
|
849 | return runner.run(done);
|
850 | };
|