Skip to content

Commit a5ee31b

Browse files
BridgeARtargos
authored andcommitted
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: #20485 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
1 parent 08097cc commit a5ee31b

3 files changed

Lines changed: 88 additions & 11 deletions

File tree

‎doc/api/assert.md‎

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,27 +1070,65 @@ changes:
10701070
Expects the function `block` to throw an error.
10711071

10721072
If specified, `error` can be a [`Class`][], [`RegExp`][], a validation function,
1073-
an object where each property will be tested for, or an instance of error where
1074-
each property will be tested for including the non-enumerable `message` and
1075-
`name` properties.
1073+
a validation object where each property will be tested for strict deep equality,
1074+
or an instance of error where each property will be tested for strict deep
1075+
equality including the non-enumerable `message` and `name` properties. When
1076+
using an object, it is also possible to use a regular expression, when
1077+
validating against a string property. See below for examples.
10761078

10771079
If specified, `message` will be the message provided by the `AssertionError` if
10781080
the block fails to throw.
10791081

1080-
Custom error object / error instance:
1082+
Custom validation object / error instance:
10811083

10821084
```js
10831085
consterr=newTypeError('Wrong value');
10841086
err.code=404;
1087+
err.foo='bar';
1088+
err.info= {
1089+
nested:true,
1090+
baz:'text'
1091+
};
1092+
err.reg=/abc/i;
10851093

10861094
assert.throws(
10871095
() => {
10881096
throw err;
10891097
},
10901098
{
10911099
name:'TypeError',
1092-
message:'Wrong value'
1093-
// Note that only properties on the error object will be tested!
1100+
message:'Wrong value',
1101+
info: {
1102+
nested:true,
1103+
baz:'text'
1104+
}
1105+
// Note that only properties on the validation object will be tested for.
1106+
// Using nested objects requires all properties to be present. Otherwise
1107+
// the validation is going to fail.
1108+
}
1109+
);
1110+
1111+
// Using regular expressions to validate error properties:
1112+
assert.throws(
1113+
() => {
1114+
throw err;
1115+
},
1116+
{
1117+
// The `name` and `message` properties are strings and using regular
1118+
// expressions on those will match against the string. If they fail, an
1119+
// error is thrown.
1120+
name:/^TypeError$/,
1121+
message:/Wrong/,
1122+
foo:'bar',
1123+
info: {
1124+
nested:true,
1125+
// It is not possible to use regular expressions for nested properties!
1126+
baz:'text'
1127+
},
1128+
// The `reg` property contains a regular expression and only if the
1129+
// validation object contains an identical regular expression, it is going
1130+
// to pass.
1131+
reg:/abc/i
10941132
}
10951133
);
10961134

‎lib/assert.js‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const {
3535
}
3636
}=require('internal/errors');
3737
const{ openSync, closeSync, readSync }=require('fs');
38-
const{ inspect,types: { isPromise }}=require('util');
38+
const{ inspect,types: { isPromise, isRegExp}}=require('util');
3939
const{EOL}=require('os');
4040
const{ NativeModule }=require('internal/bootstrap/loaders');
4141

@@ -362,10 +362,18 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
362362
};
363363

364364
classComparison{
365-
constructor(obj,keys){
365+
constructor(obj,keys,actual){
366366
for(constkeyofkeys){
367-
if(keyinobj)
368-
this[key]=obj[key];
367+
if(keyinobj){
368+
if(actual!==undefined&&
369+
typeofactual[key]==='string'&&
370+
isRegExp(obj[key])&&
371+
obj[key].test(actual[key])){
372+
this[key]=actual[key];
373+
}else{
374+
this[key]=obj[key];
375+
}
376+
}
369377
}
370378
}
371379
}
@@ -375,7 +383,7 @@ function compareExceptionKey(actual, expected, key, message, keys) {
375383
if(!message){
376384
// Create placeholder objects to create a nice output.
377385
consta=newComparison(actual,keys);
378-
constb=newComparison(expected,keys);
386+
constb=newComparison(expected,keys,actual);
379387

380388
consttmpLimit=Error.stackTraceLimit;
381389
Error.stackTraceLimit=0;
@@ -415,6 +423,11 @@ function expectedException(actual, expected, msg) {
415423
keys.push('name','message');
416424
}
417425
for(constkeyofkeys){
426+
if(typeofactual[key]==='string'&&
427+
isRegExp(expected[key])&&
428+
expected[key].test(actual[key])){
429+
continue;
430+
}
418431
compareExceptionKey(actual,expected,key,msg,keys);
419432
}
420433
returntrue;

‎test/parallel/test-assert.js‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,3 +914,29 @@ assert.throws(
914914
}
915915
);
916916
}
917+
918+
assert.throws(
919+
()=>{thrownewTypeError('foobar');},
920+
{
921+
message: /foo/,
922+
name: /^TypeError$/
923+
}
924+
);
925+
926+
assert.throws(
927+
()=>assert.throws(
928+
()=>{thrownewTypeError('foobar');},
929+
{
930+
message: /fooa/,
931+
name: /^TypeError$/
932+
}
933+
),
934+
{
935+
message: `${start}\n${actExp}\n\n`+
936+
' Comparison {\n'+
937+
"- message: 'foobar',\n"+
938+
'+ message: /fooa/,\n'+
939+
" name: 'TypeError'\n"+
940+
' }'
941+
}
942+
);

0 commit comments

Comments
 (0)