UNPKG

22.9 kBJavaScriptView Raw
1'use strict';
2
3/*!
4 * mocha
5 * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
6 * MIT Licensed
7 */
8
9var escapeRe = require('escape-string-regexp');
10var path = require('path');
11var builtinReporters = require('./reporters');
12var growl = require('./growl');
13var utils = require('./utils');
14var mocharc = require('./mocharc.json');
15var errors = require('./errors');
16var Suite = require('./suite');
17var createStatsCollector = require('./stats-collector');
18var createInvalidReporterError = errors.createInvalidReporterError;
19var createInvalidInterfaceError = errors.createInvalidInterfaceError;
20var EVENT_FILE_PRE_REQUIRE = Suite.constants.EVENT_FILE_PRE_REQUIRE;
21var EVENT_FILE_POST_REQUIRE = Suite.constants.EVENT_FILE_POST_REQUIRE;
22var EVENT_FILE_REQUIRE = Suite.constants.EVENT_FILE_REQUIRE;
23var sQuote = utils.sQuote;
24
25exports = module.exports = Mocha;
26
27/**
28 * To require local UIs and reporters when running in node.
29 */
30
31if (!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 */
45exports.utils = utils;
46exports.interfaces = require('./interfaces');
47/**
48 * @public
49 * @memberof Mocha
50 */
51exports.reporters = builtinReporters;
52exports.Runnable = require('./runnable');
53exports.Context = require('./context');
54/**
55 *
56 * @memberof Mocha
57 */
58exports.Runner = require('./runner');
59exports.Suite = Suite;
60exports.Hook = require('./hook');
61exports.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 */
95function 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 */
171Mocha.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 */
192Mocha.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 */
213Mocha.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 */
275Mocha.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 */
328Mocha.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 */
348Mocha.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 &mdash; 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 */
368Mocha.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 */
386Mocha.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 */
427Mocha.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 */
450Mocha.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 */
468Mocha.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 */
482Mocha.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 */
494Mocha.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 */
508Mocha.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 */
531Mocha.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 */
541Mocha.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 */
557Mocha.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 */
575Mocha.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 */
591Mocha.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 */
604Mocha.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 */
634Mocha.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 */
652Mocha.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 */
674Mocha.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 */
689Mocha.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 */
703Mocha.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 */
715Mocha.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 */
727Mocha.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 */
744Mocha.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 */
756Mocha.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 */
768Mocha.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 */
780Object.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 */
809Mocha.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};