Skip to content

Commit 186ca36

Browse files
authored
add createInvalidArgumentError(); see #3676 (#3677)
- 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
1 parent 3a7fa37 commit 186ca36

22 files changed

+723
-369
lines changed

docs/index.md

+211-210
Large diffs are not rendered by default.

karma.conf.js

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ module.exports = config => {
156156
require.resolve('unexpected/unexpected'),
157157
{pattern: require.resolve('unexpected/unexpected.js.map'), included: false},
158158
require.resolve('unexpected-sinon'),
159+
require.resolve('unexpected-eventemitter/dist/unexpected-eventemitter.js'),
159160
require.resolve('./test/browser-specific/setup')
160161
);
161162

lib/cli/run.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
*/
99

1010
const Mocha = require('../mocha');
11-
const ansi = require('ansi-colors');
1211
const {
12+
createUnsupportedError,
1313
createInvalidArgumentValueError,
1414
createMissingArgumentError
1515
} = require('../errors');
@@ -268,9 +268,9 @@ exports.builder = yargs =>
268268
}
269269

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

lib/errors.js

+16-14
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

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

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

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

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

6767
/**
68-
* Creates an error object used when an argument is missing.
68+
* Creates an error object to be thrown when an argument is missing.
6969
*
7070
* @public
7171
* @param {string} message - Error message to be displayed.
@@ -78,7 +78,7 @@ function createMissingArgumentError(message, argument, expected) {
7878
}
7979

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

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

117117
/**
118-
* Creates an error object used when an error was thrown but no details were specified.
118+
* Creates an error object to be thrown when an exception was caught, but the `Error` is falsy or undefined.
119119
*
120120
* @public
121121
* @param {string} message - Error message to be displayed.
122122
* @returns {Error} instance detailing the error condition
123123
*/
124-
function createUndefinedError(message) {
124+
function createInvalidExceptionError(message, value) {
125125
var err = new Error(message);
126-
err.code = 'ERR_MOCHA_UNDEFINED_ERROR';
126+
err.code = 'ERR_MOCHA_INVALID_EXCEPTION';
127+
err.valueType = typeof value;
128+
err.value = value;
127129
return err;
128130
}
129131

130132
module.exports = {
131133
createInvalidArgumentTypeError: createInvalidArgumentTypeError,
132134
createInvalidArgumentValueError: createInvalidArgumentValueError,
135+
createInvalidExceptionError: createInvalidExceptionError,
133136
createInvalidInterfaceError: createInvalidInterfaceError,
134137
createInvalidReporterError: createInvalidReporterError,
135138
createMissingArgumentError: createMissingArgumentError,
136139
createNoFilesMatchPatternError: createNoFilesMatchPatternError,
137-
createNotSupportedError: createNotSupportedError,
138-
createUndefinedError: createUndefinedError
140+
createUnsupportedError: createUnsupportedError
139141
};

lib/reporters/xunit.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var fs = require('fs');
1212
var mkdirp = require('mkdirp');
1313
var path = require('path');
1414
var errors = require('../errors');
15+
var createUnsupportedError = errors.createUnsupportedError;
1516
var constants = require('../runner').constants;
1617
var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
1718
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
@@ -20,7 +21,6 @@ var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
2021
var STATE_FAILED = require('../runnable').constants.STATE_FAILED;
2122
var inherits = utils.inherits;
2223
var escape = utils.escape;
23-
var createNotSupportedError = errors.createNotSupportedError;
2424

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

6464
mkdirp.sync(path.dirname(options.reporterOptions.output));

lib/runnable.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ var Pending = require('./pending');
55
var debug = require('debug')('mocha:runnable');
66
var milliseconds = require('ms');
77
var utils = require('./utils');
8+
var createInvalidExceptionError = require('./errors')
9+
.createInvalidExceptionError;
810

911
/**
1012
* Save timer references to avoid Sinon interfering (see GH-237).
@@ -355,7 +357,7 @@ Runnable.prototype.run = function(fn) {
355357
callFnAsync(this.fn);
356358
} catch (err) {
357359
emitted = true;
358-
done(utils.getError(err));
360+
done(Runnable.toValueOrError(err));
359361
}
360362
return;
361363
}
@@ -378,7 +380,7 @@ Runnable.prototype.run = function(fn) {
378380
}
379381
} catch (err) {
380382
emitted = true;
381-
done(utils.getError(err));
383+
done(Runnable.toValueOrError(err));
382384
}
383385

384386
function callFn(fn) {
@@ -462,7 +464,8 @@ var constants = utils.defineConstants(
462464
* @static
463465
* @alias constants
464466
* @enum {string}
465-
*/ {
467+
*/
468+
{
466469
/**
467470
* Value of `state` prop when a `Runnable` has failed
468471
*/
@@ -474,4 +477,20 @@ var constants = utils.defineConstants(
474477
}
475478
);
476479

480+
/**
481+
* Given `value`, return identity if truthy, otherwise create an "invalid exception" error and return that.
482+
* @param {*} [value] - Value to return, if present
483+
* @returns {*|Error} `value`, otherwise an `Error`
484+
* @private
485+
*/
486+
Runnable.toValueOrError = function(value) {
487+
return (
488+
value ||
489+
createInvalidExceptionError(
490+
'Runnable failed with falsy or undefined exception. Please throw an Error instead.',
491+
value
492+
)
493+
);
494+
};
495+
477496
Runnable.constants = constants;

lib/runner.js

+9-12
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ var STATE_PASSED = Runnable.constants.STATE_PASSED;
1717
var stackFilter = utils.stackTraceFilter();
1818
var stringify = utils.stringify;
1919
var type = utils.type;
20-
var undefinedError = utils.undefinedError;
20+
var createInvalidExceptionError = require('./errors')
21+
.createInvalidExceptionError;
2122

2223
/**
2324
* Non-enumerable globals.
@@ -771,18 +772,13 @@ Runner.prototype.runSuite = function(suite, fn) {
771772
*/
772773
Runner.prototype.uncaught = function(err) {
773774
if (err) {
774-
debug(
775-
'uncaught exception %s',
776-
err ===
777-
function() {
778-
return this;
779-
}.call(err)
780-
? err.message || err
781-
: err
782-
);
775+
debug('uncaught exception %O', err);
783776
} else {
784-
debug('uncaught undefined exception');
785-
err = undefinedError();
777+
debug('uncaught undefined/falsy exception');
778+
err = createInvalidExceptionError(
779+
'Caught falsy/undefined exception which would otherwise be uncaught. No stack trace found; try a debugger',
780+
err
781+
);
786782
}
787783

788784
if (!isError(err)) {
@@ -827,6 +823,7 @@ Runner.prototype.uncaught = function(err) {
827823
this.hookUp(HOOK_TYPE_AFTER_EACH, this.next);
828824
return;
829825
}
826+
debug(runnable);
830827

831828
// recover from hooks
832829
var errSuite = this.suite;

lib/utils.js

-24
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ var he = require('he');
1818
var errors = require('./errors');
1919
var createNoFilesMatchPatternError = errors.createNoFilesMatchPatternError;
2020
var createMissingArgumentError = errors.createMissingArgumentError;
21-
var createUndefinedError = errors.createUndefinedError;
2221

2322
/**
2423
* Ignored directories.
@@ -580,29 +579,6 @@ exports.lookupFiles = function lookupFiles(filepath, extensions, recursive) {
580579
return files;
581580
};
582581

583-
/**
584-
* Generate an undefined error with a message warning the user.
585-
*
586-
* @return {Error}
587-
*/
588-
589-
exports.undefinedError = function() {
590-
return createUndefinedError(
591-
'Caught undefined error, did you throw without specifying what?'
592-
);
593-
};
594-
595-
/**
596-
* Generate an undefined error if `err` is not defined.
597-
*
598-
* @param {Error} err
599-
* @return {Error}
600-
*/
601-
602-
exports.getError = function(err) {
603-
return err || exports.undefinedError();
604-
};
605-
606582
/**
607583
* process.emitWarning or a polyfill
608584
* @see https://nodejs.org/api/process.html#process_process_emitwarning_warning_options

package-lock.json

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-scripts.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ module.exports = {
115115
integration: {
116116
script: test(
117117
'integration',
118-
'--timeout 10000 --slow 3750 "test/integration/*.spec.js"'
118+
'--timeout 10000 --slow 3750 "test/integration/**/*.spec.js"'
119119
),
120120
description: 'Run Node.js integration tests',
121121
hiddenFromHelp: true

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@
560560
"through2": "^3.0.0",
561561
"to-vfile": "^5.0.2",
562562
"unexpected": "^10.39.2",
563+
"unexpected-eventemitter": "^1.1.3",
563564
"unexpected-sinon": "^10.10.1",
564565
"uslug": "^1.0.4",
565566
"watchify": "^3.7.0"

test/browser-specific/setup.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ process.stdout = require('browser-stdout')();
44

55
global.expect = global.weknowhow.expect
66
.clone()
7-
.use(global.weknowhow.unexpectedSinon);
7+
.use(global.weknowhow.unexpectedSinon)
8+
.use(global.unexpectedEventEmitter);

test/integration/helpers.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,16 @@ module.exports = {
174174
*/
175175
resolveFixturePath: resolveFixturePath,
176176

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

180189
/**

test/integration/options.spec.js

-16
This file was deleted.

0 commit comments

Comments
 (0)