Skip to content

Commit

Permalink
add createInvalidArgumentError(); see #3676 (#3677)
Browse files Browse the repository at this point in the history
- updated error code table in docs
  - all other changes in docs are from prettier
- updated `--compilers` test
- rename "not supported" error to "unsupported" error
- rename "undefined error" error to "invalid exception" error
- remove "invalid argument" factory; use "unsupported" factory
- doc fixes
- move `utils.getError` to `Runnable.getError`, since it's only used there
- remove `utils.undefinedError`; use `createInvalidExceptionError` instead.
- add more `Runner` coverage for Coveralls
- add my `unexpected-eventemitter` plugin, which helps test `EventEmitter` behavior
- fix coverage problems
  • Loading branch information
boneskull committed Feb 10, 2019
1 parent 3a7fa37 commit 186ca36
Show file tree
Hide file tree
Showing 22 changed files with 723 additions and 369 deletions.
421 changes: 211 additions & 210 deletions docs/index.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions karma.conf.js
Expand Up @@ -156,6 +156,7 @@ module.exports = config => {
require.resolve('unexpected/unexpected'),
{pattern: require.resolve('unexpected/unexpected.js.map'), included: false},
require.resolve('unexpected-sinon'),
require.resolve('unexpected-eventemitter/dist/unexpected-eventemitter.js'),
require.resolve('./test/browser-specific/setup')
);

Expand Down
6 changes: 3 additions & 3 deletions lib/cli/run.js
Expand Up @@ -8,8 +8,8 @@
*/

const Mocha = require('../mocha');
const ansi = require('ansi-colors');
const {
createUnsupportedError,
createInvalidArgumentValueError,
createMissingArgumentError
} = require('../errors');
Expand Down Expand Up @@ -268,9 +268,9 @@ exports.builder = yargs =>
}

if (argv.compilers) {
throw createInvalidArgumentValueError(
throw createUnsupportedError(
`--compilers is DEPRECATED and no longer supported.
See ${ansi.cyan('https://git.io/vdcSr')} for migration information.`
See https://git.io/vdcSr for migration information.`
);
}

Expand Down
30 changes: 16 additions & 14 deletions lib/errors.js
Expand Up @@ -7,7 +7,7 @@
*/

/**
* Creates an error object used when no files to be tested could be found using specified pattern.
* Creates an error object to be thrown when no files to be tested could be found using specified pattern.
*
* @public
* @param {string} message - Error message to be displayed.
Expand All @@ -22,7 +22,7 @@ function createNoFilesMatchPatternError(message, pattern) {
}

/**
* Creates an error object used when the reporter specified in the options was not found.
* Creates an error object to be thrown when the reporter specified in the options was not found.
*
* @public
* @param {string} message - Error message to be displayed.
Expand All @@ -37,7 +37,7 @@ function createInvalidReporterError(message, reporter) {
}

/**
* Creates an error object used when the interface specified in the options was not found.
* Creates an error object to be thrown when the interface specified in the options was not found.
*
* @public
* @param {string} message - Error message to be displayed.
Expand All @@ -52,20 +52,20 @@ function createInvalidInterfaceError(message, ui) {
}

/**
* Creates an error object used when the type of output specified was not supported.
* Creates an error object to be thrown when a behavior, option, or parameter is unsupported.
*
* @public
* @param {string} message - Error message to be displayed.
* @returns {Error} instance detailing the error condition
*/
function createNotSupportedError(message) {
function createUnsupportedError(message) {
var err = new Error(message);
err.code = 'ERR_MOCHA_NOT_SUPPORTED';
err.code = 'ERR_MOCHA_UNSUPPORTED';
return err;
}

/**
* Creates an error object used when an argument is missing.
* Creates an error object to be thrown when an argument is missing.
*
* @public
* @param {string} message - Error message to be displayed.
Expand All @@ -78,7 +78,7 @@ function createMissingArgumentError(message, argument, expected) {
}

/**
* Creates an error object used when an argument did not use the supported type
* Creates an error object to be thrown when an argument did not use the supported type
*
* @public
* @param {string} message - Error message to be displayed.
Expand All @@ -96,7 +96,7 @@ function createInvalidArgumentTypeError(message, argument, expected) {
}

/**
* Creates an error object used when an argument did not use the supported value
* Creates an error object to be thrown when an argument did not use the supported value
*
* @public
* @param {string} message - Error message to be displayed.
Expand All @@ -115,25 +115,27 @@ function createInvalidArgumentValueError(message, argument, value, reason) {
}

/**
* Creates an error object used when an error was thrown but no details were specified.
* Creates an error object to be thrown when an exception was caught, but the `Error` is falsy or undefined.
*
* @public
* @param {string} message - Error message to be displayed.
* @returns {Error} instance detailing the error condition
*/
function createUndefinedError(message) {
function createInvalidExceptionError(message, value) {
var err = new Error(message);
err.code = 'ERR_MOCHA_UNDEFINED_ERROR';
err.code = 'ERR_MOCHA_INVALID_EXCEPTION';
err.valueType = typeof value;
err.value = value;
return err;
}

module.exports = {
createInvalidArgumentTypeError: createInvalidArgumentTypeError,
createInvalidArgumentValueError: createInvalidArgumentValueError,
createInvalidExceptionError: createInvalidExceptionError,
createInvalidInterfaceError: createInvalidInterfaceError,
createInvalidReporterError: createInvalidReporterError,
createMissingArgumentError: createMissingArgumentError,
createNoFilesMatchPatternError: createNoFilesMatchPatternError,
createNotSupportedError: createNotSupportedError,
createUndefinedError: createUndefinedError
createUnsupportedError: createUnsupportedError
};
4 changes: 2 additions & 2 deletions lib/reporters/xunit.js
Expand Up @@ -12,6 +12,7 @@ var fs = require('fs');
var mkdirp = require('mkdirp');
var path = require('path');
var errors = require('../errors');
var createUnsupportedError = errors.createUnsupportedError;
var constants = require('../runner').constants;
var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
Expand All @@ -20,7 +21,6 @@ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
var STATE_FAILED = require('../runnable').constants.STATE_FAILED;
var inherits = utils.inherits;
var escape = utils.escape;
var createNotSupportedError = errors.createNotSupportedError;

/**
* Save timer references to avoid Sinon interfering (see GH-237).
Expand Down Expand Up @@ -58,7 +58,7 @@ function XUnit(runner, options) {
if (options && options.reporterOptions) {
if (options.reporterOptions.output) {
if (!fs.createWriteStream) {
throw createNotSupportedError('file output not supported in browser');
throw createUnsupportedError('file output not supported in browser');
}

mkdirp.sync(path.dirname(options.reporterOptions.output));
Expand Down
25 changes: 22 additions & 3 deletions lib/runnable.js
Expand Up @@ -5,6 +5,8 @@ var Pending = require('./pending');
var debug = require('debug')('mocha:runnable');
var milliseconds = require('ms');
var utils = require('./utils');
var createInvalidExceptionError = require('./errors')
.createInvalidExceptionError;

/**
* Save timer references to avoid Sinon interfering (see GH-237).
Expand Down Expand Up @@ -355,7 +357,7 @@ Runnable.prototype.run = function(fn) {
callFnAsync(this.fn);
} catch (err) {
emitted = true;
done(utils.getError(err));
done(Runnable.toValueOrError(err));
}
return;
}
Expand All @@ -378,7 +380,7 @@ Runnable.prototype.run = function(fn) {
}
} catch (err) {
emitted = true;
done(utils.getError(err));
done(Runnable.toValueOrError(err));
}

function callFn(fn) {
Expand Down Expand Up @@ -462,7 +464,8 @@ var constants = utils.defineConstants(
* @static
* @alias constants
* @enum {string}
*/ {
*/
{
/**
* Value of `state` prop when a `Runnable` has failed
*/
Expand All @@ -474,4 +477,20 @@ var constants = utils.defineConstants(
}
);

/**
* Given `value`, return identity if truthy, otherwise create an "invalid exception" error and return that.
* @param {*} [value] - Value to return, if present
* @returns {*|Error} `value`, otherwise an `Error`
* @private
*/
Runnable.toValueOrError = function(value) {
return (
value ||
createInvalidExceptionError(
'Runnable failed with falsy or undefined exception. Please throw an Error instead.',
value
)
);
};

Runnable.constants = constants;
21 changes: 9 additions & 12 deletions lib/runner.js
Expand Up @@ -17,7 +17,8 @@ var STATE_PASSED = Runnable.constants.STATE_PASSED;
var stackFilter = utils.stackTraceFilter();
var stringify = utils.stringify;
var type = utils.type;
var undefinedError = utils.undefinedError;
var createInvalidExceptionError = require('./errors')
.createInvalidExceptionError;

/**
* Non-enumerable globals.
Expand Down Expand Up @@ -771,18 +772,13 @@ Runner.prototype.runSuite = function(suite, fn) {
*/
Runner.prototype.uncaught = function(err) {
if (err) {
debug(
'uncaught exception %s',
err ===
function() {
return this;
}.call(err)
? err.message || err
: err
);
debug('uncaught exception %O', err);
} else {
debug('uncaught undefined exception');
err = undefinedError();
debug('uncaught undefined/falsy exception');
err = createInvalidExceptionError(
'Caught falsy/undefined exception which would otherwise be uncaught. No stack trace found; try a debugger',
err
);
}

if (!isError(err)) {
Expand Down Expand Up @@ -827,6 +823,7 @@ Runner.prototype.uncaught = function(err) {
this.hookUp(HOOK_TYPE_AFTER_EACH, this.next);
return;
}
debug(runnable);

// recover from hooks
var errSuite = this.suite;
Expand Down
24 changes: 0 additions & 24 deletions lib/utils.js
Expand Up @@ -18,7 +18,6 @@ var he = require('he');
var errors = require('./errors');
var createNoFilesMatchPatternError = errors.createNoFilesMatchPatternError;
var createMissingArgumentError = errors.createMissingArgumentError;
var createUndefinedError = errors.createUndefinedError;

/**
* Ignored directories.
Expand Down Expand Up @@ -580,29 +579,6 @@ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) {
return files;
};

/**
* Generate an undefined error with a message warning the user.
*
* @return {Error}
*/

exports.undefinedError = function() {
return createUndefinedError(
'Caught undefined error, did you throw without specifying what?'
);
};

/**
* Generate an undefined error if `err` is not defined.
*
* @param {Error} err
* @return {Error}
*/

exports.getError = function(err) {
return err || exports.undefinedError();
};

/**
* process.emitWarning or a polyfill
* @see https://nodejs.org/api/process.html#process_process_emitwarning_warning_options
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package-scripts.js
Expand Up @@ -115,7 +115,7 @@ module.exports = {
integration: {
script: test(
'integration',
'--timeout 10000 --slow 3750 "test/integration/*.spec.js"'
'--timeout 10000 --slow 3750 "test/integration/**/*.spec.js"'
),
description: 'Run Node.js integration tests',
hiddenFromHelp: true
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -560,6 +560,7 @@
"through2": "^3.0.0",
"to-vfile": "^5.0.2",
"unexpected": "^10.39.2",
"unexpected-eventemitter": "^1.1.3",
"unexpected-sinon": "^10.10.1",
"uslug": "^1.0.4",
"watchify": "^3.7.0"
Expand Down
3 changes: 2 additions & 1 deletion test/browser-specific/setup.js
Expand Up @@ -4,4 +4,5 @@ process.stdout = require('browser-stdout')();

global.expect = global.weknowhow.expect
.clone()
.use(global.weknowhow.unexpectedSinon);
.use(global.weknowhow.unexpectedSinon)
.use(global.unexpectedEventEmitter);
11 changes: 10 additions & 1 deletion test/integration/helpers.js
Expand Up @@ -174,7 +174,16 @@ module.exports = {
*/
resolveFixturePath: resolveFixturePath,

toJSONRunResult: toJSONRunResult
toJSONRunResult: toJSONRunResult,

/**
* Given a regexp-like string, escape it so it can be used with the `RegExp` constructor
* @param {string} str - string to be escaped
* @returns {string} Escaped string
*/
escapeRegExp: function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
};

/**
Expand Down
16 changes: 0 additions & 16 deletions test/integration/options.spec.js

This file was deleted.

0 comments on commit 186ca36

Please sign in to comment.