From ec8e2f8b5e5dcb6857f52784b30047099d9b9eae Mon Sep 17 00:00:00 2001 From: Juerg B <44573692+juergba@users.noreply.github.com> Date: Sun, 3 Nov 2019 10:13:46 +0100 Subject: [PATCH] Mocha constructor: improve browser setup (#4070) --- lib/mocha.js | 162 +++++++++++++++++++++++++------------ test/unit/mocha.spec.js | 171 ++++++++++++++++++++++++++++++++++------ 2 files changed, 261 insertions(+), 72 deletions(-) diff --git a/lib/mocha.js b/lib/mocha.js index 839a523111..d306f995cd 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -100,11 +100,9 @@ function Mocha(options) { this.grep(options.grep) .fgrep(options.fgrep) .ui(options.ui) - .bail(options.bail) .reporter(options.reporter, options.reporterOption) .slow(options.slow) - .useInlineDiffs(options.inlineDiffs) - .globals(options.global); + .global(options.global); // this guard exists because Suite#timeout does not consider `undefined` to be valid input if (typeof options.timeout !== 'undefined') { @@ -118,12 +116,16 @@ function Mocha(options) { [ 'allowUncaught', 'asyncOnly', + 'bail', 'checkLeaks', + 'color', 'delay', + 'diff', 'forbidOnly', 'forbidPending', 'fullTrace', 'growl', + 'inlineDiffs', 'invert' ].forEach(function(opt) { if (options[opt]) { @@ -136,16 +138,13 @@ function Mocha(options) { * Enables or disables bailing on the first failure. * * @public - * @see {@link /#-bail-b|CLI option} + * @see [CLI option](../#-bail-b) * @param {boolean} [bail=true] - Whether to bail on first error. * @returns {Mocha} this * @chainable */ Mocha.prototype.bail = function(bail) { - if (!arguments.length) { - bail = true; - } - this.suite.bail(bail); + this.suite.bail(bail !== false); return this; }; @@ -157,7 +156,7 @@ Mocha.prototype.bail = function(bail) { * Useful for generic setup code that must be included within test suite. * * @public - * @see {@link /#-file-filedirectoryglob|CLI option} + * @see [CLI option](../#-file-filedirectoryglob) * @param {string} file - Pathname of file to be loaded. * @returns {Mocha} this * @chainable @@ -171,8 +170,8 @@ Mocha.prototype.addFile = function(file) { * Sets reporter to `reporter`, defaults to "spec". * * @public - * @see {@link /#-reporter-name-r-name|CLI option} - * @see {@link /#reporters|Reporters} + * @see [CLI option](../#-reporter-name-r-name) + * @see [Reporters](../#reporters) * @param {String|Function} reporter - Reporter name or constructor. * @param {Object} [reporterOptions] - Options used to configure the reporter. * @returns {Mocha} this @@ -240,8 +239,8 @@ Mocha.prototype.reporter = function(reporter, reporterOptions) { * Sets test UI `name`, defaults to "bdd". * * @public - * @see {@link /#-ui-name-u-name|CLI option} - * @see {@link /#interfaces|Interface DSLs} + * @see [CLI option](../#-ui-name-u-name) + * @see [Interface DSLs](../#interfaces) * @param {string|Function} [ui=bdd] - Interface name or class. * @returns {Mocha} this * @chainable @@ -334,8 +333,6 @@ Mocha.unloadFile = function(file) { * Intended for consumers — not used internally * * @public - * @see {@link Mocha.unloadFile} - * @see {@link Mocha#loadFiles} * @see {@link Mocha#run} * @returns {Mocha} this * @chainable @@ -379,7 +376,7 @@ Mocha.prototype.fgrep = function(str) { * Previous filter value will be overwritten on each call! * * @public - * @see {@link /#grep-regexp-g-regexp|CLI option} + * @see [CLI option](../#-grep-regexp-g-regexp) * @see {@link Mocha#fgrep} * @see {@link Mocha#invert} * @param {RegExp|String} re - Regular expression used to select tests. @@ -430,32 +427,32 @@ Mocha.prototype.invert = function() { /** * Enables or disables ignoring global leaks. * + * @deprecated since v7.0.0 * @public * @see {@link Mocha#checkLeaks} * @param {boolean} [ignoreLeaks=false] - Whether to ignore global leaks. * @return {Mocha} this * @chainable - * @example - * - * // Ignore global leaks - * mocha.ignoreLeaks(true); */ Mocha.prototype.ignoreLeaks = function(ignoreLeaks) { + utils.deprecate( + '"ignoreLeaks()" is DEPRECATED, please use "checkLeaks()" instead.' + ); this.options.checkLeaks = !ignoreLeaks; return this; }; /** - * Enables checking for global variables leaked while running tests. + * Enables or disables checking for global variables leaked while running tests. * * @public - * @see {@link /#-check-leaks|CLI option} - * @see {@link Mocha#ignoreLeaks} + * @see [CLI option](../#-check-leaks) + * @param {boolean} [checkLeaks=true] - Whether to check for global variable leaks. * @return {Mocha} this * @chainable */ -Mocha.prototype.checkLeaks = function() { - this.options.checkLeaks = true; +Mocha.prototype.checkLeaks = function(checkLeaks) { + this.options.checkLeaks = checkLeaks !== false; return this; }; @@ -463,11 +460,13 @@ Mocha.prototype.checkLeaks = function() { * Displays full stack trace upon test failure. * * @public + * @see [CLI option](../#-full-trace) + * @param {boolean} [fullTrace=true] - Whether to print full stacktrace upon failure. * @return {Mocha} this * @chainable */ -Mocha.prototype.fullTrace = function() { - this.options.fullTrace = true; +Mocha.prototype.fullTrace = function(fullTrace) { + this.options.fullTrace = fullTrace !== false; return this; }; @@ -475,8 +474,7 @@ Mocha.prototype.fullTrace = function() { * Enables desktop notification support if prerequisite software installed. * * @public - * @see {@link Mocha#isGrowlCapable} - * @see {@link Mocha#_growl} + * @see [CLI option](../#-growl-g) * @return {Mocha} this * @chainable */ @@ -519,68 +517,124 @@ Mocha.prototype._growl = growl.notify; * Specifies whitelist of variable names to be expected in global scope. * * @public - * @see {@link /#-global-variable-name|CLI option} + * @see [CLI option](../#-global-variable-name) * @see {@link Mocha#checkLeaks} - * @param {String[]|String} globals - Accepted global variable name(s). + * @param {String[]|String} global - Accepted global variable name(s). * @return {Mocha} this * @chainable * @example * * // Specify variables to be expected in global scope - * mocha.globals(['jQuery', 'MyLib']); + * mocha.global(['jQuery', 'MyLib']); */ -Mocha.prototype.globals = function(globals) { +Mocha.prototype.global = function(global) { this.options.global = (this.options.global || []) - .concat(globals) + .concat(global) .filter(Boolean) .filter(function(elt, idx, arr) { return arr.indexOf(elt) === idx; }); return this; }; +// for backwards compability, 'globals' is an alias of 'global' +Mocha.prototype.globals = Mocha.prototype.global; /** * Enables or disables TTY color output by screen-oriented reporters. * + * @deprecated since v7.0.0 * @public + * @see {@link Mocha#color} * @param {boolean} colors - Whether to enable color output. * @return {Mocha} this * @chainable */ Mocha.prototype.useColors = function(colors) { + utils.deprecate('"useColors()" is DEPRECATED, please use "color()" instead.'); if (colors !== undefined) { this.options.color = colors; } return this; }; +/** + * Enables or disables TTY color output by screen-oriented reporters. + * + * @public + * @see [CLI option](../#-color-c-colors) + * @param {boolean} [color=true] - Whether to enable color output. + * @return {Mocha} this + * @chainable + */ +Mocha.prototype.color = function(color) { + this.options.color = color !== false; + return this; +}; + /** * Determines if reporter should use inline diffs (rather than +/-) * in test failure output. * + * @deprecated since v7.0.0 * @public + * @see {@link Mocha#inlineDiffs} * @param {boolean} [inlineDiffs=false] - Whether to use inline diffs. * @return {Mocha} this * @chainable */ Mocha.prototype.useInlineDiffs = function(inlineDiffs) { + utils.deprecate( + '"useInlineDiffs()" is DEPRECATED, please use "inlineDiffs()" instead.' + ); this.options.inlineDiffs = inlineDiffs !== undefined && inlineDiffs; return this; }; +/** + * Enables or disables reporter to use inline diffs (rather than +/-) + * in test failure output. + * + * @public + * @see [CLI option](../#-inline-diffs) + * @param {boolean} [inlineDiffs=true] - Whether to use inline diffs. + * @return {Mocha} this + * @chainable + */ +Mocha.prototype.inlineDiffs = function(inlineDiffs) { + this.options.inlineDiffs = inlineDiffs !== false; + return this; +}; + /** * Determines if reporter should include diffs in test failure output. * + * @deprecated since v7.0.0 * @public + * @see {@link Mocha#diff} * @param {boolean} [hideDiff=false] - Whether to hide diffs. * @return {Mocha} this * @chainable */ Mocha.prototype.hideDiff = function(hideDiff) { + utils.deprecate('"hideDiff()" is DEPRECATED, please use "diff()" instead.'); this.options.diff = !(hideDiff === true); return this; }; +/** + * Enables or disables reporter to include diff in test failure output. + * + * @public + * @see [CLI option](../#-diff) + * @param {boolean} [diff=true] - Whether to show diff on failure. + * @return {Mocha} this + * @chainable + */ +Mocha.prototype.diff = function(diff) { + this.options.diff = diff !== false; + return this; +}; + /** * @summary * Sets timeout threshold value. @@ -590,8 +644,8 @@ Mocha.prototype.hideDiff = function(hideDiff) { * If the value is `0`, timeouts will be disabled. * * @public - * @see {@link /#-timeout-ms-t-ms|CLI option} - * @see {@link /#timeouts|Timeouts} + * @see [CLI option](../#-timeout-ms-t-ms) + * @see [Timeouts](../#timeouts) * @see {@link Mocha#enableTimeouts} * @param {number|string} msecs - Timeout threshold value. * @return {Mocha} this @@ -614,7 +668,8 @@ Mocha.prototype.timeout = function(msecs) { * Sets the number of times to retry failed tests. * * @public - * @see {@link /#retry-tests|Retry Tests} + * @see [CLI option](../#-retries-n) + * @see [Retry Tests](../#retry-tests) * @param {number} retry - Number of times to retry failed tests. * @return {Mocha} this * @chainable @@ -632,7 +687,7 @@ Mocha.prototype.retries = function(n) { * Sets slowness threshold value. * * @public - * @see {@link /#-slow-ms-s-ms|CLI option} + * @see [CLI option](../#-slow-ms-s-ms) * @param {number} msecs - Slowness threshold value. * @return {Mocha} this * @chainable @@ -654,7 +709,7 @@ Mocha.prototype.slow = function(msecs) { * Enables or disables timeouts. * * @public - * @see {@link /#-timeout-ms-t-ms|CLI option} + * @see [CLI option](../#-timeout-ms-t-ms) * @param {boolean} enableTimeouts - Whether to enable timeouts. * @return {Mocha} this * @chainable @@ -670,11 +725,13 @@ Mocha.prototype.enableTimeouts = function(enableTimeouts) { * Forces all tests to either accept a `done` callback or return a promise. * * @public + * @see [CLI option](../#-async-only-a) + * @param {boolean} [asyncOnly=true] - Wether to force `done` callback or promise. * @return {Mocha} this * @chainable */ -Mocha.prototype.asyncOnly = function() { - this.options.asyncOnly = true; +Mocha.prototype.asyncOnly = function(asyncOnly) { + this.options.asyncOnly = asyncOnly !== false; return this; }; @@ -691,14 +748,16 @@ Mocha.prototype.noHighlighting = function() { }; /** - * Enables uncaught errors to propagate (in browser). + * Enables or disables uncaught errors to propagate. * * @public + * @see [CLI option](../#-allow-uncaught) + * @param {boolean} [allowUncaught=true] - Whether to propagate uncaught errors. * @return {Mocha} this * @chainable */ -Mocha.prototype.allowUncaught = function() { - this.options.allowUncaught = true; +Mocha.prototype.allowUncaught = function(allowUncaught) { + this.options.allowUncaught = allowUncaught !== false; return this; }; @@ -710,7 +769,7 @@ Mocha.prototype.allowUncaught = function() { * Used to perform asynch operations before any suites are run. * * @public - * @see {@link /#delayed-root-suite|delayed root suite} + * @see [delayed root suite](../#delayed-root-suite) * @returns {Mocha} this * @chainable */ @@ -723,11 +782,13 @@ Mocha.prototype.delay = function delay() { * Causes tests marked `only` to fail the suite. * * @public + * @see [CLI option](../#-forbid-only) + * @param {boolean} [forbidOnly=true] - Whether tests marked `only` fail the suite. * @returns {Mocha} this * @chainable */ -Mocha.prototype.forbidOnly = function() { - this.options.forbidOnly = true; +Mocha.prototype.forbidOnly = function(forbidOnly) { + this.options.forbidOnly = forbidOnly !== false; return this; }; @@ -735,11 +796,13 @@ Mocha.prototype.forbidOnly = function() { * Causes pending tests and tests marked `skip` to fail the suite. * * @public + * @see [CLI option](../#-forbid-pending) + * @param {boolean} [forbidPending=true] - Whether pending tests fail the suite. * @returns {Mocha} this * @chainable */ -Mocha.prototype.forbidPending = function() { - this.options.forbidPending = true; +Mocha.prototype.forbidPending = function(forbidPending) { + this.options.forbidPending = forbidPending !== false; return this; }; @@ -773,7 +836,6 @@ Object.defineProperty(Mocha.prototype, 'version', { * the cache first! * * @public - * @see {@link Mocha#loadFiles} * @see {@link Mocha#unloadFiles} * @see {@link Runner#run} * @param {DoneCB} [fn] - Callback invoked when test execution completed. diff --git a/test/unit/mocha.spec.js b/test/unit/mocha.spec.js index 648853feab..71d804814c 100644 --- a/test/unit/mocha.spec.js +++ b/test/unit/mocha.spec.js @@ -19,8 +19,7 @@ describe('Mocha', function() { describe('constructor', function() { beforeEach(function() { sandbox.stub(Mocha.prototype, 'timeout').returnsThis(); - sandbox.stub(Mocha.prototype, 'globals').returnsThis(); - sandbox.stub(Mocha.prototype, 'useInlineDiffs').returnsThis(); + sandbox.stub(Mocha.prototype, 'global').returnsThis(); }); describe('when "options.timeout" is `undefined`', function() { @@ -42,24 +41,14 @@ describe('Mocha', function() { }); describe('when "options.global" is provided', function() { - it('should pass "options.global" to #globals()', function() { + it('should pass "options.global" to #global()', function() { // eslint-disable-next-line no-new new Mocha({global: ['singular']}); - expect(Mocha.prototype.globals, 'to have a call satisfying', [ + expect(Mocha.prototype.global, 'to have a call satisfying', [ ['singular'] ]).and('was called once'); }); }); - - describe('when "options.inlineDiffs" is `undefined`', function() { - it('should set inlineDiffs to `true`', function() { - // eslint-disable-next-line no-new - new Mocha({inlineDiffs: true}); - expect(Mocha.prototype.useInlineDiffs, 'to have a call satisfying', [ - true - ]).and('was called once'); - }); - }); }); describe('#allowUncaught()', function() { @@ -69,12 +58,37 @@ describe('Mocha', function() { expect(mocha.options, 'to have property', 'allowUncaught', true); }); + it('should set the allowUncaught option to false', function() { + var mocha = new Mocha(opts); + mocha.allowUncaught(false); + expect(mocha.options, 'to have property', 'allowUncaught', false); + }); + it('should be chainable', function() { var mocha = new Mocha(opts); expect(mocha.allowUncaught(), 'to be', mocha); }); }); + describe('#asyncOnly()', function() { + it('should set the asyncOnly option to true', function() { + var mocha = new Mocha(opts); + mocha.asyncOnly(); + expect(mocha.options, 'to have property', 'asyncOnly', true); + }); + + it('should set the asyncOnly option to false', function() { + var mocha = new Mocha(opts); + mocha.asyncOnly(false); + expect(mocha.options, 'to have property', 'asyncOnly', false); + }); + + it('should be chainable', function() { + var mocha = new Mocha(opts); + expect(mocha.asyncOnly(), 'to be', mocha); + }); + }); + describe('#bail()', function() { it('should set the suite._bail to true if there is no arguments', function() { var mocha = new Mocha(opts); @@ -82,6 +96,12 @@ describe('Mocha', function() { expect(mocha.suite._bail, 'to be', true); }); + it('should set the suite._bail to false', function() { + var mocha = new Mocha(opts); + mocha.bail(false); + expect(mocha.suite._bail, 'to be', false); + }); + it('should be chainable', function() { var mocha = new Mocha(opts); expect(mocha.bail(), 'to be', mocha); @@ -95,12 +115,37 @@ describe('Mocha', function() { expect(mocha.options, 'to have property', 'checkLeaks', true); }); + it('should set the checkLeaks option to false', function() { + var mocha = new Mocha(opts); + mocha.checkLeaks(false); + expect(mocha.options, 'to have property', 'checkLeaks', false); + }); + it('should be chainable', function() { var mocha = new Mocha(opts); expect(mocha.checkLeaks(), 'to be', mocha); }); }); + describe('#color()', function() { + it('should set the color option to true', function() { + var mocha = new Mocha(opts); + mocha.color(); + expect(mocha.options, 'to have property', 'color', true); + }); + + it('should set the color option to false', function() { + var mocha = new Mocha(opts); + mocha.color(false); + expect(mocha.options, 'to have property', 'color', false); + }); + + it('should be chainable', function() { + var mocha = new Mocha(opts); + expect(mocha.color(), 'to be', mocha); + }); + }); + describe('#delay()', function() { it('should set the delay option to true', function() { var mocha = new Mocha(opts); @@ -127,6 +172,63 @@ describe('Mocha', function() { }); }); + describe('#diff()', function() { + it('should set the diff option to true', function() { + var mocha = new Mocha(opts); + mocha.diff(); + expect(mocha.options, 'to have property', 'diff', true); + }); + + it('should set the diff option to false', function() { + var mocha = new Mocha(opts); + mocha.diff(false); + expect(mocha.options, 'to have property', 'diff', false); + }); + + it('should be chainable', function() { + var mocha = new Mocha(opts); + expect(mocha.diff(), 'to be', mocha); + }); + }); + + describe('#forbidOnly()', function() { + it('should set the forbidOnly option to true', function() { + var mocha = new Mocha(opts); + mocha.forbidOnly(); + expect(mocha.options, 'to have property', 'forbidOnly', true); + }); + + it('should set the forbidOnly option to false', function() { + var mocha = new Mocha(opts); + mocha.forbidOnly(false); + expect(mocha.options, 'to have property', 'forbidOnly', false); + }); + + it('should be chainable', function() { + var mocha = new Mocha(opts); + expect(mocha.forbidOnly(), 'to be', mocha); + }); + }); + + describe('#forbidPending()', function() { + it('should set the forbidPending option to true', function() { + var mocha = new Mocha(opts); + mocha.forbidPending(); + expect(mocha.options, 'to have property', 'forbidPending', true); + }); + + it('should set the forbidPending option to false', function() { + var mocha = new Mocha(opts); + mocha.forbidPending(false); + expect(mocha.options, 'to have property', 'forbidPending', false); + }); + + it('should be chainable', function() { + var mocha = new Mocha(opts); + expect(mocha.forbidPending(), 'to be', mocha); + }); + }); + describe('#fullTrace()', function() { it('should set the fullTrace option to true', function() { var mocha = new Mocha(opts); @@ -134,13 +236,19 @@ describe('Mocha', function() { expect(mocha.options, 'to have property', 'fullTrace', true); }); + it('should set the fullTrace option to false', function() { + var mocha = new Mocha(opts); + mocha.fullTrace(false); + expect(mocha.options, 'to have property', 'fullTrace', false); + }); + it('should be chainable', function() { var mocha = new Mocha(opts); expect(mocha.fullTrace(), 'to be', mocha); }); }); - describe('#globals()', function() { + describe('#global()', function() { it('should be an empty array initially', function() { var mocha = new Mocha(); expect(mocha.options.global, 'to be empty'); @@ -148,19 +256,19 @@ describe('Mocha', function() { it('should be chainable', function() { var mocha = new Mocha(opts); - expect(mocha.globals(), 'to be', mocha); + expect(mocha.global(), 'to be', mocha); }); describe('when argument is invalid', function() { it('should not modify the whitelist when given empty string', function() { var mocha = new Mocha(opts); - mocha.globals(''); + mocha.global(''); expect(mocha.options.global, 'to be empty'); }); it('should not modify the whitelist when given empty array', function() { var mocha = new Mocha(opts); - mocha.globals([]); + mocha.global([]); expect(mocha.options.global, 'to be empty'); }); }); @@ -172,7 +280,7 @@ describe('Mocha', function() { it('should add string to the whitelist', function() { var mocha = new Mocha(opts); - mocha.globals(elem); + mocha.global(elem); expect(mocha.options.global, 'to contain', elem); expect(mocha.options.global, 'to have length', 1); }); @@ -180,15 +288,15 @@ describe('Mocha', function() { it('should add contents of string array to the whitelist', function() { var mocha = new Mocha(opts); var elems = [elem, elem2]; - mocha.globals(elems); + mocha.global(elems); expect(mocha.options.global, 'to contain', elem, elem2); expect(mocha.options.global, 'to have length', elems.length); }); it('should not have duplicates', function() { - var mocha = new Mocha({globals: [elem, elem2]}); + var mocha = new Mocha({global: [elem, elem2]}); var elems = [elem, elem2, elem3]; - mocha.globals(elems); + mocha.global(elems); expect(mocha.options.global, 'to contain', elem, elem2, elem3); expect(mocha.options.global, 'to have length', elems.length); }); @@ -274,6 +382,25 @@ describe('Mocha', function() { }); }); + describe('#inlineDiffs()', function() { + it('should set the inlineDiffs option to true', function() { + var mocha = new Mocha(opts); + mocha.inlineDiffs(); + expect(mocha.options, 'to have property', 'inlineDiffs', true); + }); + + it('should set the inlineDiffs option to false', function() { + var mocha = new Mocha(opts); + mocha.inlineDiffs(false); + expect(mocha.options, 'to have property', 'inlineDiffs', false); + }); + + it('should be chainable', function() { + var mocha = new Mocha(opts); + expect(mocha.inlineDiffs(), 'to be', mocha); + }); + }); + describe('#invert()', function() { it('should set the invert option to true', function() { var mocha = new Mocha(opts);