assert: accept regular expressions to validate

This makes sure regular expressions on validation objects validate
against strings when used with `assert.throws` and `assert.rejects`.

PR-URL: https://github.com/nodejs/node/pull/20485
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
Ruben Bridgewater 2018-05-02 19:26:32 +02:00
parent 81b99da96e
commit cf7be86cd9
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
3 changed files with 88 additions and 11 deletions

View File

@ -1070,18 +1070,26 @@ changes:
Expects the function `block` to throw an error.
If specified, `error` can be a [`Class`][], [`RegExp`][], a validation function,
an object where each property will be tested for, or an instance of error where
each property will be tested for including the non-enumerable `message` and
`name` properties.
a validation object where each property will be tested for strict deep equality,
or an instance of error where each property will be tested for strict deep
equality including the non-enumerable `message` and `name` properties. When
using an object, it is also possible to use a regular expression, when
validating against a string property. See below for examples.
If specified, `message` will be the message provided by the `AssertionError` if
the block fails to throw.
Custom error object / error instance:
Custom validation object / error instance:
```js
const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
nested: true,
baz: 'text'
};
err.reg = /abc/i;
assert.throws(
() => {
@ -1089,8 +1097,38 @@ assert.throws(
},
{
name: 'TypeError',
message: 'Wrong value'
// Note that only properties on the error object will be tested!
message: 'Wrong value',
info: {
nested: true,
baz: 'text'
}
// Note that only properties on the validation object will be tested for.
// Using nested objects requires all properties to be present. Otherwise
// the validation is going to fail.
}
);
// Using regular expressions to validate error properties:
assert.throws(
() => {
throw err;
},
{
// The `name` and `message` properties are strings and using regular
// expressions on those will match against the string. If they fail, an
// error is thrown.
name: /^TypeError$/,
message: /Wrong/,
foo: 'bar',
info: {
nested: true,
// It is not possible to use regular expressions for nested properties!
baz: 'text'
},
// The `reg` property contains a regular expression and only if the
// validation object contains an identical regular expression, it is going
// to pass.
reg: /abc/i
}
);

View File

@ -35,7 +35,7 @@ const {
}
} = require('internal/errors');
const { openSync, closeSync, readSync } = require('fs');
const { inspect, types: { isPromise } } = require('util');
const { inspect, types: { isPromise, isRegExp } } = require('util');
const { EOL } = require('os');
const { NativeModule } = require('internal/bootstrap/loaders');
@ -362,10 +362,18 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
};
class Comparison {
constructor(obj, keys) {
constructor(obj, keys, actual) {
for (const key of keys) {
if (key in obj)
this[key] = obj[key];
if (key in obj) {
if (actual !== undefined &&
typeof actual[key] === 'string' &&
isRegExp(obj[key]) &&
obj[key].test(actual[key])) {
this[key] = actual[key];
} else {
this[key] = obj[key];
}
}
}
}
}
@ -375,7 +383,7 @@ function compareExceptionKey(actual, expected, key, message, keys) {
if (!message) {
// Create placeholder objects to create a nice output.
const a = new Comparison(actual, keys);
const b = new Comparison(expected, keys);
const b = new Comparison(expected, keys, actual);
const tmpLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 0;
@ -415,6 +423,11 @@ function expectedException(actual, expected, msg) {
keys.push('name', 'message');
}
for (const key of keys) {
if (typeof actual[key] === 'string' &&
isRegExp(expected[key]) &&
expected[key].test(actual[key])) {
continue;
}
compareExceptionKey(actual, expected, key, msg, keys);
}
return true;

View File

@ -914,3 +914,29 @@ assert.throws(
}
);
}
assert.throws(
() => { throw new TypeError('foobar'); },
{
message: /foo/,
name: /^TypeError$/
}
);
assert.throws(
() => assert.throws(
() => { throw new TypeError('foobar'); },
{
message: /fooa/,
name: /^TypeError$/
}
),
{
message: `${start}\n${actExp}\n\n` +
' Comparison {\n' +
"- message: 'foobar',\n" +
'+ message: /fooa/,\n' +
" name: 'TypeError'\n" +
' }'
}
);