Skip to content

Commit

Permalink
test: validate more properties in expectsError
Browse files Browse the repository at this point in the history
PR-URL: #14058
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
  • Loading branch information
BridgeAR authored and refack committed Jul 19, 2017
1 parent b55ab01 commit 2a621d4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 28 deletions.
43 changes: 28 additions & 15 deletions test/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,28 +51,41 @@ Platform normalizes the `dd` command
Check if there is more than 1gb of total memory.

### expectsError([fn, ]settings[, exact])
* `fn` [&lt;Function>]
* `fn` [&lt;Function>] a function that should throw.
* `settings` [&lt;Object>]
with the following optional properties:
that must contain the `code` property plus any of the other following
properties (some properties only apply for `AssertionError`):
* `code` [&lt;String>]
expected error must have this value for its `code` property
expected error must have this value for its `code` property.
* `type` [&lt;Function>]
expected error must be an instance of `type`
* `message` [&lt;String>]
or [&lt;RegExp>]
expected error must be an instance of `type` and must be an Error subclass.
* `message` [&lt;String>] or [&lt;RegExp>]
if a string is provided for `message`, expected error must have it for its
`message` property; if a regular expression is provided for `message`, the
regular expression must match the `message` property of the expected error
regular expression must match the `message` property of the expected error.
* `name` [&lt;String>]
expected error must have this value for its `name` property.
* `generatedMessage` [&lt;String>]
(`AssertionError` only) expected error must have this value for its
`generatedMessage` property.
* `actual` &lt;any>
(`AssertionError` only) expected error must have this value for its
`actual` property.
* `expected` &lt;any>
(`AssertionError` only) expected error must have this value for its
`expected` property.
* `operator` &lt;any>
(`AssertionError` only) expected error must have this value for its
`operator` property.
* `exact` [&lt;Number>] default = 1
* return [&lt;Function>]

* return function suitable for use as a validation function passed as the second
argument to e.g. `assert.throws()`. If the returned function has not been
called exactly `exact` number of times when the test is complete, then the
test will fail.

If `fn` is provided, it will be passed to `assert.throws` as first argument.

The expected error should be [subclassed by the `internal/errors` module](https://github.com/nodejs/node/blob/master/doc/guides/using-internal-errors.md#api).
If `fn` is provided, it will be passed to `assert.throws` as first argument
and `undefined` will be returned.
Otherwise a function suitable as callback or for use as a validation function
passed as the second argument to `assert.throws()` will be returned. If the
returned function has not been called exactly `exact` number of times when the
test is complete, then the test will fail.

### expectWarning(name, expected)
* `name` [&lt;String>]
Expand Down
43 changes: 31 additions & 12 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -696,24 +696,43 @@ Object.defineProperty(exports, 'hasSmallICU', {
});

// Useful for testing expected internal/error objects
exports.expectsError = function expectsError(fn, options, exact) {
exports.expectsError = function expectsError(fn, settings, exact) {
if (typeof fn !== 'function') {
exact = options;
options = fn;
exact = settings;
settings = fn;
fn = undefined;
}
const { code, type, message } = options;
const innerFn = exports.mustCall(function(error) {
assert.strictEqual(error.code, code);
if (type !== undefined) {
assert.strictEqual(error.code, settings.code);
if ('type' in settings) {
const type = settings.type;
if (type !== Error && !Error.isPrototypeOf(type)) {
throw new TypeError('`settings.type` must inherit from `Error`');
}
assert(error instanceof type,
`${error} is not the expected type ${type}`);
`${error.name} is not instance of ${type.name}`);
}
if ('message' in settings) {
const message = settings.message;
if (typeof message === 'string') {
assert.strictEqual(error.message, message);
} else {
assert(message.test(error.message),
`${error.message} does not match ${message}`);
}
}
if (message instanceof RegExp) {
assert(message.test(error.message),
`${error.message} does not match ${message}`);
} else if (typeof message === 'string') {
assert.strictEqual(error.message, message);
if ('name' in settings) {
assert.strictEqual(error.name, settings.name);
}
if (error.constructor.name === 'AssertionError') {
['generatedMessage', 'actual', 'expected', 'operator'].forEach((key) => {
if (key in settings) {
const actual = error[key];
const expected = settings[key];
assert.strictEqual(actual, expected,
`${key}: expected ${expected}, not ${actual}`);
}
});
}
return true;
}, exact);
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-internal-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ assert.throws(() => {
}, common.expectsError({ code: 'TEST_ERROR_1', type: RangeError }));
}, common.expectsError({
code: 'ERR_ASSERTION',
message: /^.+ is not the expected type \S/
message: /^.+ is not instance of \S/
}));

assert.throws(() => {
Expand Down

0 comments on commit 2a621d4

Please sign in to comment.