Skip to content

Commit d932a53

Browse files
RaisinTenBridgeAR
authored andcommitted
Implement assert.match() and assert.doesNotMatch()
Signed-off-by: Darshan Sen <[email protected]>
1 parent bba838e commit d932a53

File tree

4 files changed

+157
-3
lines changed

4 files changed

+157
-3
lines changed

assert.js

+50-3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ const { isPromise, isRegExp } = require('util/').types;
3737
const objectAssign = Object.assign ? Object.assign : require('es6-object-assign').assign;
3838
const objectIs = Object.is ? Object.is : require('object-is');
3939

40+
const RegExpPrototypeTest = require('call-bind/callBound')('RegExp.prototype.test');
41+
4042
const errorCache = new Map();
4143

4244
let isDeepEqual;
@@ -308,7 +310,7 @@ class Comparison {
308310
if (actual !== undefined &&
309311
typeof actual[key] === 'string' &&
310312
isRegExp(obj[key]) &&
311-
obj[key].test(actual[key])
313+
RegExpPrototypeTest(obj[key], actual[key])
312314
) {
313315
this[key] = actual[key];
314316
} else {
@@ -350,7 +352,7 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) {
350352
function expectedException(actual, expected, msg, fn) {
351353
if (typeof expected !== 'function') {
352354
if (isRegExp(expected))
353-
return expected.test(actual);
355+
return RegExpPrototypeTest(expected, actual);
354356
// assert.doesNotThrow does not accept objects.
355357
if (arguments.length === 2) {
356358
throw new ERR_INVALID_ARG_TYPE(
@@ -385,7 +387,7 @@ function expectedException(actual, expected, msg, fn) {
385387
if (
386388
typeof actual[key] === 'string' &&
387389
isRegExp(expected[key]) &&
388-
expected[key].test(actual[key])
390+
RegExpPrototypeTest(expected[key], actual[key])
389391
) {
390392
return;
391393
}
@@ -596,6 +598,51 @@ assert.ifError = function ifError(err) {
596598
}
597599
};
598600

601+
// Currently in sync with Node.js lib/assert.js
602+
// https://github.com/nodejs/node/commit/2a871df3dfb8ea663ef5e1f8f62701ec51384ecb
603+
function internalMatch(string, regexp, message, fn, fnName) {
604+
if (!isRegExp(regexp)) {
605+
throw new ERR_INVALID_ARG_TYPE(
606+
'regexp', 'RegExp', regexp
607+
);
608+
}
609+
const match = fnName === 'match';
610+
if (typeof string !== 'string' ||
611+
RegExpPrototypeTest(regexp, string) !== match) {
612+
if (message instanceof Error) {
613+
throw message;
614+
}
615+
616+
const generatedMessage = !message;
617+
618+
// 'The input was expected to not match the regular expression ' +
619+
message = message || (typeof string !== 'string' ?
620+
'The "string" argument must be of type string. Received type ' +
621+
`${typeof string} (${inspect(string)})` :
622+
(match ?
623+
'The input did not match the regular expression ' :
624+
'The input was expected to not match the regular expression ') +
625+
`${inspect(regexp)}. Input:\n\n${inspect(string)}\n`);
626+
const err = new AssertionError({
627+
actual: string,
628+
expected: regexp,
629+
message,
630+
operator: fnName,
631+
stackStartFn: fn
632+
});
633+
err.generatedMessage = generatedMessage;
634+
throw err;
635+
}
636+
}
637+
638+
assert.match = function match(string, regexp, message) {
639+
internalMatch(string, regexp, message, match, 'match');
640+
};
641+
642+
assert.doesNotMatch = function doesNotMatch(string, regexp, message) {
643+
internalMatch(string, regexp, message, doesNotMatch, 'doesNotMatch');
644+
};
645+
599646
// Expose a strict only variant of assert
600647
function strict(...args) {
601648
innerOk(strict, args.length, ...args);

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"tape": "^4.10.1"
3838
},
3939
"dependencies": {
40+
"call-bind": "^1.0.2",
4041
"es6-object-assign": "^1.1.0",
4142
"is-nan": "^1.2.1",
4243
"object-is": "^1.0.1",

test.js

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const testPaths = [
1313
['test-assert-fail-deprecation.js', () => require('./test/parallel/test-assert-fail-deprecation.js')],
1414
['test-assert-fail.js', () => require('./test/parallel/test-assert-fail.js')],
1515
['test-assert-if-error.js', () => require('./test/parallel/test-assert-if-error.js')],
16+
['test-assert-match.js', () => require('./test/parallel/test-assert-match.js')],
1617
['test-assert-typedarray-deepequal.js', () => require('./test/parallel/test-assert-typedarray-deepequal.js')],
1718
['test-assert.js', () => require('./test/parallel/test-assert.js')],
1819
['test-assert-colors.js', () => require('./test/pseudo-tty/test-assert-colors.js')],

test/parallel/test-assert-match.js

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Currently in sync with Node.js test/parallel/test-assert.js
2+
// https://github.com/nodejs/node/commit/2a871df3dfb8ea663ef5e1f8f62701ec51384ecb
3+
4+
'use strict';
5+
6+
require('../common');
7+
const assert = require('../../assert');
8+
9+
// Multiple assert.match() tests.
10+
{
11+
assert.throws(
12+
() => assert.match(/abc/, 'string'),
13+
{
14+
code: 'ERR_INVALID_ARG_TYPE',
15+
message: 'The "regexp" argument must be of type RegExp. Received type string'
16+
}
17+
);
18+
assert.throws(
19+
() => assert.match('string', /abc/),
20+
{
21+
actual: 'string',
22+
expected: /abc/,
23+
operator: 'match',
24+
message: 'The input did not match the regular expression /abc/. ' +
25+
"Input:\n\n'string'\n",
26+
generatedMessage: true
27+
}
28+
);
29+
assert.throws(
30+
() => assert.match('string', /abc/, 'foobar'),
31+
{
32+
actual: 'string',
33+
expected: /abc/,
34+
operator: 'match',
35+
message: 'foobar',
36+
generatedMessage: false
37+
}
38+
);
39+
const errorMessage = new RangeError('foobar');
40+
assert.throws(
41+
() => assert.match('string', /abc/, errorMessage),
42+
errorMessage
43+
);
44+
assert.throws(
45+
() => assert.match({ abc: 123 }, /abc/),
46+
{
47+
actual: { abc: 123 },
48+
expected: /abc/,
49+
operator: 'match',
50+
message: 'The "string" argument must be of type string. ' +
51+
'Received type object ({ abc: 123 })',
52+
generatedMessage: true
53+
}
54+
);
55+
assert.match('I will pass', /pass$/);
56+
}
57+
58+
// Multiple assert.doesNotMatch() tests.
59+
{
60+
assert.throws(
61+
() => assert.doesNotMatch(/abc/, 'string'),
62+
{
63+
code: 'ERR_INVALID_ARG_TYPE',
64+
message: 'The "regexp" argument must be of type RegExp. Received type string'
65+
}
66+
);
67+
assert.throws(
68+
() => assert.doesNotMatch('string', /string/),
69+
{
70+
actual: 'string',
71+
expected: /string/,
72+
operator: 'doesNotMatch',
73+
message: 'The input was expected to not match the regular expression ' +
74+
"/string/. Input:\n\n'string'\n",
75+
generatedMessage: true
76+
}
77+
);
78+
assert.throws(
79+
() => assert.doesNotMatch('string', /string/, 'foobar'),
80+
{
81+
actual: 'string',
82+
expected: /string/,
83+
operator: 'doesNotMatch',
84+
message: 'foobar',
85+
generatedMessage: false
86+
}
87+
);
88+
const errorMessage = new RangeError('foobar');
89+
assert.throws(
90+
() => assert.doesNotMatch('string', /string/, errorMessage),
91+
errorMessage
92+
);
93+
assert.throws(
94+
() => assert.doesNotMatch({ abc: 123 }, /abc/),
95+
{
96+
actual: { abc: 123 },
97+
expected: /abc/,
98+
operator: 'doesNotMatch',
99+
message: 'The "string" argument must be of type string. ' +
100+
'Received type object ({ abc: 123 })',
101+
generatedMessage: true
102+
}
103+
);
104+
assert.doesNotMatch('I will pass', /different$/);
105+
}

0 commit comments

Comments
 (0)