Skip to content

Commit

Permalink
Implement assert.match() and assert.doesNotMatch()
Browse files Browse the repository at this point in the history
Signed-off-by: Darshan Sen <[email protected]>
  • Loading branch information
RaisinTen authored and BridgeAR committed Oct 21, 2022
1 parent bba838e commit d932a53
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 3 deletions.
53 changes: 50 additions & 3 deletions assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const { isPromise, isRegExp } = require('util/').types;
const objectAssign = Object.assign ? Object.assign : require('es6-object-assign').assign;
const objectIs = Object.is ? Object.is : require('object-is');

const RegExpPrototypeTest = require('call-bind/callBound')('RegExp.prototype.test');

const errorCache = new Map();

let isDeepEqual;
Expand Down Expand Up @@ -308,7 +310,7 @@ class Comparison {
if (actual !== undefined &&
typeof actual[key] === 'string' &&
isRegExp(obj[key]) &&
obj[key].test(actual[key])
RegExpPrototypeTest(obj[key], actual[key])
) {
this[key] = actual[key];
} else {
Expand Down Expand Up @@ -350,7 +352,7 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) {
function expectedException(actual, expected, msg, fn) {
if (typeof expected !== 'function') {
if (isRegExp(expected))
return expected.test(actual);
return RegExpPrototypeTest(expected, actual);
// assert.doesNotThrow does not accept objects.
if (arguments.length === 2) {
throw new ERR_INVALID_ARG_TYPE(
Expand Down Expand Up @@ -385,7 +387,7 @@ function expectedException(actual, expected, msg, fn) {
if (
typeof actual[key] === 'string' &&
isRegExp(expected[key]) &&
expected[key].test(actual[key])
RegExpPrototypeTest(expected[key], actual[key])
) {
return;
}
Expand Down Expand Up @@ -596,6 +598,51 @@ assert.ifError = function ifError(err) {
}
};

// Currently in sync with Node.js lib/assert.js
// https://github.com/nodejs/node/commit/2a871df3dfb8ea663ef5e1f8f62701ec51384ecb
function internalMatch(string, regexp, message, fn, fnName) {
if (!isRegExp(regexp)) {
throw new ERR_INVALID_ARG_TYPE(
'regexp', 'RegExp', regexp
);
}
const match = fnName === 'match';
if (typeof string !== 'string' ||
RegExpPrototypeTest(regexp, string) !== match) {
if (message instanceof Error) {
throw message;
}

const generatedMessage = !message;

// 'The input was expected to not match the regular expression ' +
message = message || (typeof string !== 'string' ?
'The "string" argument must be of type string. Received type ' +
`${typeof string} (${inspect(string)})` :
(match ?
'The input did not match the regular expression ' :
'The input was expected to not match the regular expression ') +
`${inspect(regexp)}. Input:\n\n${inspect(string)}\n`);
const err = new AssertionError({
actual: string,
expected: regexp,
message,
operator: fnName,
stackStartFn: fn
});
err.generatedMessage = generatedMessage;
throw err;
}
}

assert.match = function match(string, regexp, message) {
internalMatch(string, regexp, message, match, 'match');
};

assert.doesNotMatch = function doesNotMatch(string, regexp, message) {
internalMatch(string, regexp, message, doesNotMatch, 'doesNotMatch');
};

// Expose a strict only variant of assert
function strict(...args) {
innerOk(strict, args.length, ...args);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"tape": "^4.10.1"
},
"dependencies": {
"call-bind": "^1.0.2",
"es6-object-assign": "^1.1.0",
"is-nan": "^1.2.1",
"object-is": "^1.0.1",
Expand Down
1 change: 1 addition & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const testPaths = [
['test-assert-fail-deprecation.js', () => require('./test/parallel/test-assert-fail-deprecation.js')],
['test-assert-fail.js', () => require('./test/parallel/test-assert-fail.js')],
['test-assert-if-error.js', () => require('./test/parallel/test-assert-if-error.js')],
['test-assert-match.js', () => require('./test/parallel/test-assert-match.js')],
['test-assert-typedarray-deepequal.js', () => require('./test/parallel/test-assert-typedarray-deepequal.js')],
['test-assert.js', () => require('./test/parallel/test-assert.js')],
['test-assert-colors.js', () => require('./test/pseudo-tty/test-assert-colors.js')],
Expand Down
105 changes: 105 additions & 0 deletions test/parallel/test-assert-match.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Currently in sync with Node.js test/parallel/test-assert.js
// https://github.com/nodejs/node/commit/2a871df3dfb8ea663ef5e1f8f62701ec51384ecb

'use strict';

require('../common');
const assert = require('../../assert');

// Multiple assert.match() tests.
{
assert.throws(
() => assert.match(/abc/, 'string'),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "regexp" argument must be of type RegExp. Received type string'
}
);
assert.throws(
() => assert.match('string', /abc/),
{
actual: 'string',
expected: /abc/,
operator: 'match',
message: 'The input did not match the regular expression /abc/. ' +
"Input:\n\n'string'\n",
generatedMessage: true
}
);
assert.throws(
() => assert.match('string', /abc/, 'foobar'),
{
actual: 'string',
expected: /abc/,
operator: 'match',
message: 'foobar',
generatedMessage: false
}
);
const errorMessage = new RangeError('foobar');
assert.throws(
() => assert.match('string', /abc/, errorMessage),
errorMessage
);
assert.throws(
() => assert.match({ abc: 123 }, /abc/),
{
actual: { abc: 123 },
expected: /abc/,
operator: 'match',
message: 'The "string" argument must be of type string. ' +
'Received type object ({ abc: 123 })',
generatedMessage: true
}
);
assert.match('I will pass', /pass$/);
}

// Multiple assert.doesNotMatch() tests.
{
assert.throws(
() => assert.doesNotMatch(/abc/, 'string'),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "regexp" argument must be of type RegExp. Received type string'
}
);
assert.throws(
() => assert.doesNotMatch('string', /string/),
{
actual: 'string',
expected: /string/,
operator: 'doesNotMatch',
message: 'The input was expected to not match the regular expression ' +
"/string/. Input:\n\n'string'\n",
generatedMessage: true
}
);
assert.throws(
() => assert.doesNotMatch('string', /string/, 'foobar'),
{
actual: 'string',
expected: /string/,
operator: 'doesNotMatch',
message: 'foobar',
generatedMessage: false
}
);
const errorMessage = new RangeError('foobar');
assert.throws(
() => assert.doesNotMatch('string', /string/, errorMessage),
errorMessage
);
assert.throws(
() => assert.doesNotMatch({ abc: 123 }, /abc/),
{
actual: { abc: 123 },
expected: /abc/,
operator: 'doesNotMatch',
message: 'The "string" argument must be of type string. ' +
'Received type object ({ abc: 123 })',
generatedMessage: true
}
);
assert.doesNotMatch('I will pass', /different$/);
}

0 comments on commit d932a53

Please sign in to comment.