mirror of https://github.com/nodejs/node.git
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:
parent
81b99da96e
commit
cf7be86cd9
|
@ -1070,18 +1070,26 @@ changes:
|
||||||
Expects the function `block` to throw an error.
|
Expects the function `block` to throw an error.
|
||||||
|
|
||||||
If specified, `error` can be a [`Class`][], [`RegExp`][], a validation function,
|
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
|
a validation object where each property will be tested for strict deep equality,
|
||||||
each property will be tested for including the non-enumerable `message` and
|
or an instance of error where each property will be tested for strict deep
|
||||||
`name` properties.
|
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
|
If specified, `message` will be the message provided by the `AssertionError` if
|
||||||
the block fails to throw.
|
the block fails to throw.
|
||||||
|
|
||||||
Custom error object / error instance:
|
Custom validation object / error instance:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const err = new TypeError('Wrong value');
|
const err = new TypeError('Wrong value');
|
||||||
err.code = 404;
|
err.code = 404;
|
||||||
|
err.foo = 'bar';
|
||||||
|
err.info = {
|
||||||
|
nested: true,
|
||||||
|
baz: 'text'
|
||||||
|
};
|
||||||
|
err.reg = /abc/i;
|
||||||
|
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => {
|
() => {
|
||||||
|
@ -1089,8 +1097,38 @@ assert.throws(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'TypeError',
|
name: 'TypeError',
|
||||||
message: 'Wrong value'
|
message: 'Wrong value',
|
||||||
// Note that only properties on the error object will be tested!
|
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
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ const {
|
||||||
}
|
}
|
||||||
} = require('internal/errors');
|
} = require('internal/errors');
|
||||||
const { openSync, closeSync, readSync } = require('fs');
|
const { openSync, closeSync, readSync } = require('fs');
|
||||||
const { inspect, types: { isPromise } } = require('util');
|
const { inspect, types: { isPromise, isRegExp } } = require('util');
|
||||||
const { EOL } = require('os');
|
const { EOL } = require('os');
|
||||||
const { NativeModule } = require('internal/bootstrap/loaders');
|
const { NativeModule } = require('internal/bootstrap/loaders');
|
||||||
|
|
||||||
|
@ -362,10 +362,18 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Comparison {
|
class Comparison {
|
||||||
constructor(obj, keys) {
|
constructor(obj, keys, actual) {
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
if (key in obj)
|
if (key in obj) {
|
||||||
this[key] = obj[key];
|
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) {
|
if (!message) {
|
||||||
// Create placeholder objects to create a nice output.
|
// Create placeholder objects to create a nice output.
|
||||||
const a = new Comparison(actual, keys);
|
const a = new Comparison(actual, keys);
|
||||||
const b = new Comparison(expected, keys);
|
const b = new Comparison(expected, keys, actual);
|
||||||
|
|
||||||
const tmpLimit = Error.stackTraceLimit;
|
const tmpLimit = Error.stackTraceLimit;
|
||||||
Error.stackTraceLimit = 0;
|
Error.stackTraceLimit = 0;
|
||||||
|
@ -415,6 +423,11 @@ function expectedException(actual, expected, msg) {
|
||||||
keys.push('name', 'message');
|
keys.push('name', 'message');
|
||||||
}
|
}
|
||||||
for (const key of keys) {
|
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);
|
compareExceptionKey(actual, expected, key, msg, keys);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -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" +
|
||||||
|
' }'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
Loading…
Reference in New Issue