diff --git a/lib/mocha.js b/lib/mocha.js index 673dbec394..1700fe9ca7 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -8,7 +8,7 @@ var escapeRe = require('escape-string-regexp'); var path = require('path'); -var reporters = require('./reporters'); +var builtinReporters = require('./reporters'); var utils = require('./utils'); exports = module.exports = Mocha; @@ -34,11 +34,10 @@ if (!process.browser) { exports.utils = utils; exports.interfaces = require('./interfaces'); /** - * - * @memberof Mocha * @public + * @memberof Mocha */ -exports.reporters = reporters; +exports.reporters = builtinReporters; exports.Runnable = require('./runnable'); exports.Context = require('./context'); /** @@ -51,34 +50,46 @@ exports.Hook = require('./hook'); exports.Test = require('./test'); /** - * Return image `name` path. + * Returns Growl image `name` path. * * @private - * @param {string} name - * @return {string} + * @param {string} name - Basename of associated Growl image. + * @return {string} Pathname to Growl image */ function image(name) { return path.join(__dirname, '..', 'assets', 'growl', name + '.png'); } /** - * Set up mocha with `options`. - * - * Options: - * - * - `ui` name "bdd", "tdd", "exports" etc - * - `reporter` reporter instance, defaults to `mocha.reporters.spec` - * - `globals` array of accepted globals - * - `timeout` timeout in milliseconds - * - `retries` number of times to retry failed tests - * - `bail` bail on the first test failure - * - `slow` milliseconds to wait before considering a test slow - * - `ignoreLeaks` ignore global leaks - * - `fullTrace` display the full stack-trace on failing - * - `grep` string or regexp to filter tests with + * Constructs a new Mocha instance with `options`. * + * @public * @class Mocha - * @param {Object} options + * @param {Object} [options] - Settings object. + * @param {boolean} [options.allowUncaught] - Propagate uncaught errors? + * @param {boolean} [options.asyncOnly] - Force `done` callback or promise? + * @param {boolean} [options.bail] - Bail after first test failure? + * @param {boolean} [options.delay] - Delay root suite execution? + * @param {boolean} [options.enableTimeouts] - Enable timeouts? + * @param {string} [options.fgrep] - Test filter given string. + * @param {boolean} [options.forbidOnly] - Tests marked `only` fail the suite? + * @param {boolean} [options.forbidPending] - Pending tests fail the suite? + * @param {boolean} [options.fullStackTrace] - Full stacktrace upon failure? + * @param {string[]} [options.globals] - Variables expected in global scope. + * @param {RegExp|string} [options.grep] - Test filter given regular expression. + * @param {boolean} [options.growl] - Enable desktop notifications? + * @param {boolean} [options.hideDiff] - Suppress diffs from failures? + * @param {boolean} [options.ignoreLeaks] - Ignore global leaks? + * @param {boolean} [options.invert] - Invert test filter matches? + * @param {boolean} [options.noHighlighting] - Disable syntax highlighting? + * @param {string} [options.reporter] - Reporter name. + * @param {Object} [options.reporterOptions] - Reporter settings object. + * @param {number} [options.retries] - Number of times to retry failed tests. + * @param {number} [options.slow] - Slow threshold value. + * @param {number|string} [options.timeout] - Timeout threshold value. + * @param {string} [options.ui] - Interface name. + * @param {boolean} [options.useColors] - Color TTY output from reporter? + * @param {boolean} [options.useInlineDiffs] - Use inline diffs? */ function Mocha(options) { options = options || {}; @@ -110,11 +121,13 @@ function Mocha(options) { } /** - * Enable or disable bailing on the first failure. + * Enables or disables bailing on the first failure. * * @public - * @api public - * @param {boolean} [bail] + * @see {@link https://mochajs.org/#-b---bail|CLI option} + * @param {boolean} [bail=true] - Whether to bail on first error. + * @returns {Mocha} this + * @chainable */ Mocha.prototype.bail = function(bail) { if (!arguments.length) { @@ -125,11 +138,17 @@ Mocha.prototype.bail = function(bail) { }; /** - * Add test `file`. + * @summary + * Adds `file` to be loaded for execution. + * + * @description + * Useful for generic setup code that must be included within test suite. * * @public - * @api public - * @param {string} file + * @see {@link https://mochajs.org/#--file-file|CLI option} + * @param {string} file - Pathname of file to be loaded. + * @returns {Mocha} this + * @chainable */ Mocha.prototype.addFile = function(file) { this.files.push(file); @@ -137,14 +156,20 @@ Mocha.prototype.addFile = function(file) { }; /** - * Set reporter to `reporter`, defaults to "spec". + * Sets reporter to `reporter`, defaults to "spec". * * @public - * @param {String|Function} reporter name or constructor - * @param {Object} reporterOptions optional options - * @api public - * @param {string|Function} reporter name or constructor - * @param {Object} reporterOptions optional options + * @see {@link https://mochajs.org/#-r---reporter-name|CLI option} + * @see {@link https://mochajs.org/#reporters|Reporters} + * @param {String|Function} reporter - Reporter name or constructor. + * @param {Object} [reporterOptions] - Options used to configure the reporter. + * @returns {Mocha} this + * @chainable + * @throws {Error} if requested reporter cannot be loaded + * @example + * + * // Use XUnit reporter and direct its output to file + * mocha.reporter('xunit', { output: '/path/to/testspec.xunit.xml' }); */ Mocha.prototype.reporter = function(reporter, reporterOptions) { if (typeof reporter === 'function') { @@ -153,8 +178,8 @@ Mocha.prototype.reporter = function(reporter, reporterOptions) { reporter = reporter || 'spec'; var _reporter; // Try to load a built-in reporter. - if (reporters[reporter]) { - _reporter = reporters[reporter]; + if (builtinReporters[reporter]) { + _reporter = builtinReporters[reporter]; } // Try to load reporters from process.cwd() and node_modules if (!_reporter) { @@ -199,10 +224,15 @@ Mocha.prototype.reporter = function(reporter, reporterOptions) { }; /** - * Set test UI `name`, defaults to "bdd". + * Sets test UI `name`, defaults to "bdd". + * * @public - * @api public - * @param {string} bdd + * @see {@link https://mochajs.org/#-u---ui-name|CLI option} + * @see {@link https://mochajs.org/#interfaces|Interface DSLs} + * @param {string} [name=bdd] - Interface name. + * @returns {Mocha} this + * @chainable + * @throws {Error} if requested interface cannot be loaded */ Mocha.prototype.ui = function(name) { name = name || 'bdd'; @@ -237,9 +267,16 @@ Mocha.prototype.ui = function(name) { }; /** - * Load registered files. + * @summary + * Loads `files` prior to execution. + * + * @description + * The implementation relies on Node's `require` to execute + * the test interface functions and will be subject to its cache. * - * @api private + * @private + * @see {@link Mocha#addFile} + * @param {Function} [fn] - Callback invoked upon completion. */ Mocha.prototype.loadFiles = function(fn) { var self = this; @@ -254,9 +291,12 @@ Mocha.prototype.loadFiles = function(fn) { }; /** - * Enable growl support. + * Implements desktop notifications using a pseudo-reporter. * - * @api private + * @private + * @see {@link Mocha#growl} + * @param {Object} runner - Runner instance. + * @param {Object} reporter - Reporter instance. */ Mocha.prototype._growl = function(runner, reporter) { var notify = require('growl'); @@ -277,26 +317,55 @@ Mocha.prototype._growl = function(runner, reporter) { }; /** - * Escape string and add it to grep as a regexp. + * Sets `grep` filter after escaping RegExp special characters. * * @public - * @api public - * @param str - * @returns {Mocha} + * @see {@link Mocha#grep} + * @param {string} str - Value to be converted to a regexp. + * @returns {Mocha} this + * @chainable + * @example + * + * // Select tests whose full title begins with `"foo"` followed by a period + * mocha.fgrep('foo.'); */ Mocha.prototype.fgrep = function(str) { return this.grep(new RegExp(escapeRe(str))); }; /** - * Add regexp to grep, if `re` is a string it is escaped. + * @summary + * Sets `grep` filter used to select specific tests for execution. + * + * @description + * If `re` is a regexp-like string, it will be converted to regexp. + * The regexp is tested against the full title of each test (i.e., the + * name of the test preceded by titles of each its ancestral suites). + * As such, using an exact-match fixed pattern against the + * test name itself will not yield any matches. + *
+ * Previous filter value will be overwritten on each call! * * @public - * @param {RegExp|String} re - * @return {Mocha} - * @api public - * @param {RegExp|string} re - * @return {Mocha} + * @see {@link https://mochajs.org/#-g---grep-pattern|CLI option} + * @see {@link Mocha#fgrep} + * @see {@link Mocha#invert} + * @param {RegExp|String} re - Regular expression used to select tests. + * @return {Mocha} this + * @chainable + * @example + * + * // Select tests whose full title contains `"match"`, ignoring case + * mocha.grep(/match/i); + * @example + * + * // Same as above but with regexp-like string argument + * mocha.grep('/match/i'); + * @example + * + * // ## Anti-example + * // Given embedded test `it('only-this-test')`... + * mocha.grep('/^only-this-test$/'); // NO! Use `.only()` to do this! */ Mocha.prototype.grep = function(re) { if (utils.isString(re)) { @@ -308,12 +377,18 @@ Mocha.prototype.grep = function(re) { } return this; }; + /** - * Invert `.grep()` matches. + * Inverts `grep` matches. * * @public - * @return {Mocha} - * @api public + * @see {@link Mocha#grep} + * @return {Mocha} this + * @chainable + * @example + * + * // Select tests whose full title does *not* contain `"match"`, ignoring case + * mocha.grep(/match/i).invert(); */ Mocha.prototype.invert = function() { this.options.invert = true; @@ -321,26 +396,31 @@ Mocha.prototype.invert = function() { }; /** - * Ignore global leaks. + * Enables or disables ignoring global leaks. * * @public - * @param {Boolean} ignore - * @return {Mocha} - * @api public - * @param {boolean} ignore - * @return {Mocha} - */ -Mocha.prototype.ignoreLeaks = function(ignore) { - this.options.ignoreLeaks = Boolean(ignore); + * @see {@link Mocha#checkLeaks} + * @param {boolean} ignoreLeaks - Whether to ignore global leaks. + * @return {Mocha} this + * @chainable + * @example + * + * // Ignore global leaks + * mocha.ignoreLeaks(true); + */ +Mocha.prototype.ignoreLeaks = function(ignoreLeaks) { + this.options.ignoreLeaks = Boolean(ignoreLeaks); return this; }; /** - * Enable global leak checking. + * Enables checking for global variables leaked while running tests. * - * @return {Mocha} - * @api public * @public + * @see {@link https://mochajs.org/#--check-leaks|CLI option} + * @see {@link Mocha#ignoreLeaks} + * @return {Mocha} this + * @chainable */ Mocha.prototype.checkLeaks = function() { this.options.ignoreLeaks = false; @@ -348,11 +428,11 @@ Mocha.prototype.checkLeaks = function() { }; /** - * Display long stack-trace on failing + * Displays full stack trace upon test failure. * - * @return {Mocha} - * @api public * @public + * @return {Mocha} this + * @chainable */ Mocha.prototype.fullTrace = function() { this.options.fullStackTrace = true; @@ -360,11 +440,12 @@ Mocha.prototype.fullTrace = function() { }; /** - * Enable growl support. + * Enables desktop notification support. * - * @return {Mocha} - * @api public * @public + * @see {@link Mocha#_growl} + * @return {Mocha} this + * @chainable */ Mocha.prototype.growl = function() { this.options.growl = true; @@ -372,14 +453,18 @@ Mocha.prototype.growl = function() { }; /** - * Ignore `globals` array or string. + * Specifies whitelist of variable names to be expected in global scope. * - * @param {Array|String} globals - * @return {Mocha} - * @api public * @public - * @param {Array|string} globals - * @return {Mocha} + * @see {@link https://mochajs.org/#--globals-names|CLI option} + * @see {@link Mocha#checkLeaks} + * @param {String[]|String} globals - Accepted global variable name(s). + * @return {Mocha} this + * @chainable + * @example + * + * // Specify variables to be expected in global scope + * mocha.globals(['jQuery', 'MyLib']); */ Mocha.prototype.globals = function(globals) { this.options.globals = (this.options.globals || []).concat(globals); @@ -387,14 +472,12 @@ Mocha.prototype.globals = function(globals) { }; /** - * Emit color output. + * Enables or disables TTY color output by screen-oriented reporters. * - * @param {Boolean} colors - * @return {Mocha} - * @api public * @public - * @param {boolean} colors - * @return {Mocha} + * @param {boolean} colors - Whether to enable color output. + * @return {Mocha} this + * @chainable */ Mocha.prototype.useColors = function(colors) { if (colors !== undefined) { @@ -404,14 +487,13 @@ Mocha.prototype.useColors = function(colors) { }; /** - * Use inline diffs rather than +/-. + * Determines if reporter should use inline diffs (rather than +/-) + * in test failure output. * - * @param {Boolean} inlineDiffs - * @return {Mocha} - * @api public * @public - * @param {boolean} inlineDiffs - * @return {Mocha} + * @param {boolean} inlineDiffs - Whether to use inline diffs. + * @return {Mocha} this + * @chainable */ Mocha.prototype.useInlineDiffs = function(inlineDiffs) { this.options.useInlineDiffs = inlineDiffs !== undefined && inlineDiffs; @@ -419,14 +501,12 @@ Mocha.prototype.useInlineDiffs = function(inlineDiffs) { }; /** - * Do not show diffs at all. + * Determines if reporter should include diffs in test failure output. * - * @param {Boolean} hideDiff - * @return {Mocha} - * @api public * @public - * @param {boolean} hideDiff - * @return {Mocha} + * @param {boolean} hideDiff - Whether to hide diffs. + * @return {Mocha} this + * @chainable */ Mocha.prototype.hideDiff = function(hideDiff) { this.options.hideDiff = hideDiff !== undefined && hideDiff; @@ -434,27 +514,47 @@ Mocha.prototype.hideDiff = function(hideDiff) { }; /** - * Set the timeout in milliseconds. + * @summary + * Sets timeout threshold value. + * + * @description + * A string argument can use shorthand (such as "2s") and will be converted. + * If the value is `0`, timeouts will be disabled. * - * @param {Number} timeout - * @return {Mocha} - * @api public * @public - * @param {number} timeout - * @return {Mocha} + * @see {@link https://mochajs.org/#-t---timeout-ms|CLI option} + * @see {@link https://mochajs.org/#--no-timeouts|CLI option} + * @see {@link https://mochajs.org/#timeouts|Timeouts} + * @see {@link Mocha#enableTimeouts} + * @param {number|string} msecs - Timeout threshold value. + * @return {Mocha} this + * @chainable + * @example + * + * // Sets timeout to one second + * mocha.timeout(1000); + * @example + * + * // Same as above but using string argument + * mocha.timeout('1s'); */ -Mocha.prototype.timeout = function(timeout) { - this.suite.timeout(timeout); +Mocha.prototype.timeout = function(msecs) { + this.suite.timeout(msecs); return this; }; /** - * Set the number of times to retry failed tests. + * Sets the number of times to retry failed tests. * - * @param {Number} retry times - * @return {Mocha} - * @api public * @public + * @see {@link https://mochajs.org/#retry-tests|Retry Tests} + * @param {number} retry - Number of times to retry failed tests. + * @return {Mocha} this + * @chainable + * @example + * + * // Allow any failed test to retry one more time + * mocha.retries(1); */ Mocha.prototype.retries = function(n) { this.suite.retries(n); @@ -462,43 +562,50 @@ Mocha.prototype.retries = function(n) { }; /** - * Set slowness threshold in milliseconds. + * Sets slowness threshold value. * - * @param {Number} slow - * @return {Mocha} - * @api public * @public - * @param {number} slow - * @return {Mocha} + * @see {@link https://mochajs.org/#-s---slow-ms|CLI option} + * @param {number} msecs - Slowness threshold value. + * @return {Mocha} this + * @chainable + * @example + * + * // Sets "slow" threshold to half a second + * mocha.slow(500); + * @example + * + * // Same as above but using string argument + * mocha.slow('0.5s'); */ -Mocha.prototype.slow = function(slow) { - this.suite.slow(slow); +Mocha.prototype.slow = function(msecs) { + this.suite.slow(msecs); return this; }; /** - * Enable timeouts. + * Enables or disables timeouts. * - * @param {Boolean} enabled - * @return {Mocha} - * @api public * @public - * @param {boolean} enabled - * @return {Mocha} + * @see {@link https://mochajs.org/#-t---timeout-ms|CLI option} + * @see {@link https://mochajs.org/#--no-timeouts|CLI option} + * @param {boolean} enableTimeouts - Whether to enable timeouts. + * @return {Mocha} this + * @chainable */ -Mocha.prototype.enableTimeouts = function(enabled) { +Mocha.prototype.enableTimeouts = function(enableTimeouts) { this.suite.enableTimeouts( - arguments.length && enabled !== undefined ? enabled : true + arguments.length && enableTimeouts !== undefined ? enableTimeouts : true ); return this; }; /** - * Makes all tests async (accepting a callback) + * Forces all tests to either accept a `done` callback or return a promise. * - * @return {Mocha} - * @api public * @public + * @return {Mocha} this + * @chainable */ Mocha.prototype.asyncOnly = function() { this.options.asyncOnly = true; @@ -506,10 +613,11 @@ Mocha.prototype.asyncOnly = function() { }; /** - * Disable syntax highlighting (in browser). + * Disables syntax highlighting (in browser). * - * @api public * @public + * @return {Mocha} this + * @chainable */ Mocha.prototype.noHighlighting = function() { this.options.noHighlighting = true; @@ -517,11 +625,11 @@ Mocha.prototype.noHighlighting = function() { }; /** - * Enable uncaught errors to propagate (in browser). + * Enables uncaught errors to propagate (in browser). * - * @return {Mocha} - * @api public * @public + * @return {Mocha} this + * @chainable */ Mocha.prototype.allowUncaught = function() { this.options.allowUncaught = true; @@ -529,8 +637,16 @@ Mocha.prototype.allowUncaught = function() { }; /** - * Delay root suite execution. - * @returns {Mocha} + * @summary + * Delays root suite execution. + * + * @description + * Used to perform asynch operations before any suites are run. + * + * @public + * @see {@link https://mochajs.org/#delayed-root-suite|delayed root suite} + * @returns {Mocha} this + * @chainable */ Mocha.prototype.delay = function delay() { this.options.delay = true; @@ -538,8 +654,11 @@ Mocha.prototype.delay = function delay() { }; /** - * Tests marked only fail the suite - * @returns {Mocha} + * Causes tests marked `only` to fail the suite. + * + * @public + * @returns {Mocha} this + * @chainable */ Mocha.prototype.forbidOnly = function() { this.options.forbidOnly = true; @@ -547,8 +666,11 @@ Mocha.prototype.forbidOnly = function() { }; /** - * Pending tests and tests marked skip fail the suite - * @returns {Mocha} + * Causes pending tests and tests marked `skip` to fail the suite. + * + * @public + * @returns {Mocha} this + * @chainable */ Mocha.prototype.forbidPending = function() { this.options.forbidPending = true; @@ -556,20 +678,26 @@ Mocha.prototype.forbidPending = function() { }; /** - * Run tests and invoke `fn()` when complete. + * Callback to be invoked when test execution is complete. + * + * @callback DoneCB + * @param {number} failures - Number of failures that occurred. + */ + +/** + * @summary + * Runs tests and invokes `fn()` when complete. * - * Note that `loadFiles` relies on Node's `require` to execute - * the test interface functions and will be subject to the - * cache - if the files are already in the `require` cache, - * they will effectively be skipped. Therefore, to run tests - * multiple times or to run tests in files that are already - * in the `require` cache, make sure to clear them from the - * cache first in whichever manner best suits your needs. + * @description + * To run tests multiple times (or to run tests in files that are + * already in the `require` cache), make sure to clear them from + * the cache first! * - * @api public * @public - * @param {Function} fn - * @return {Runner} + * @see {@link Mocha#loadFiles} + * @see {@link Runner#run} + * @param {DoneCB} [fn] - Callback invoked when test execution completed. + * @return {Runner} runner instance */ Mocha.prototype.run = function(fn) { if (this.files.length) {