Support message testing function in throws & throwsAsync assertions

This commit is contained in:
il3ven 2022-05-16 14:13:44 +05:30 committed by GitHub
parent f5caa8fb82
commit e387cba63c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 103 additions and 7 deletions

View file

@ -172,7 +172,10 @@ Assert that an error is thrown. `fn` must be a function which should throw. The
* `instanceOf`: a constructor, the thrown error must be an instance of
* `is`: the thrown error must be strictly equal to `expectation.is`
* `message`: either a string, which is compared against the thrown error's message, or a regular expression, which is matched against this message
* `message`: the following types are valid:
* *string* - it is compared against the thrown error's message
* *regular expression* - it is matched against this message
* *function* - it is passed the thrown error message and must return a boolean for whether the assertion passed
* `name`: the expected `.name` value of the thrown error
* `code`: the expected `.code` value of the thrown error
@ -204,7 +207,10 @@ The thrown value *must* be an error. It is returned so you can run more assertio
* `instanceOf`: a constructor, the thrown error must be an instance of
* `is`: the thrown error must be strictly equal to `expectation.is`
* `message`: either a string, which is compared against the thrown error's message, or a regular expression, which is matched against this message
* `message`: the following types are valid:
* *string* - it is compared against the thrown error's message
* *regular expression* - it is matched against this message
* *function* - it is passed the thrown error message and must return a boolean for whether the assertion passed
* `name`: the expected `.name` value of the thrown error
* `code`: the expected `.code` value of the thrown error

View file

@ -106,10 +106,15 @@ function validateExpectations(assertion, expectations, numberArgs) { // eslint-d
});
}
if (hasOwnProperty(expectations, 'message') && typeof expectations.message !== 'string' && !(expectations.message instanceof RegExp)) {
if (
hasOwnProperty(expectations, 'message')
&& typeof expectations.message !== 'string'
&& !(expectations.message instanceof RegExp)
&& !(typeof expectations.message === 'function')
) {
throw new AssertionError({
assertion,
message: `The \`message\` property of the second argument to \`t.${assertion}()\` must be a string or regular expression`,
message: `The \`message\` property of the second argument to \`t.${assertion}()\` must be a string, regular expression or a function`,
values: [formatWithLabel('Called with:', expectations)],
});
}
@ -230,6 +235,19 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
});
}
if (typeof expectations.message === 'function' && expectations.message(actual.message) === false) {
throw new AssertionError({
assertion,
message,
savedError,
actualStack,
values: [
formatWithLabel(`${prefix} unexpected exception:`, actual),
formatWithLabel('Expected message to return true:', expectations.message),
],
});
}
if (typeof expectations.code !== 'undefined' && actual.code !== expectations.code) {
throw new AssertionError({
assertion,

View file

@ -899,6 +899,78 @@ test('.throws()', gather(t => {
formatted: /null/,
}],
});
// Fails because the string in the message is incorrect
failsWith(
t,
() =>
assertions.throws(
() => {
throw new Error('error');
},
{message: 'my error'},
),
{
assertion: 'throws',
message: '',
values: [
{label: 'Function threw unexpected exception:', formatted: /error/},
{label: 'Expected message to equal:', formatted: /my error/},
],
},
);
passes(t, () => assertions.throws(() => {
throw new Error('error');
}, {message: 'error'}));
// Fails because the regular expression in the message is incorrect
failsWith(
t,
() =>
assertions.throws(
() => {
throw new Error('error');
},
{message: /my error/},
),
{
assertion: 'throws',
message: '',
values: [
{label: 'Function threw unexpected exception:', formatted: /error/},
{label: 'Expected message to match:', formatted: /my error/},
],
},
);
passes(t, () => assertions.throws(() => {
throw new Error('error');
}, {message: /error/}));
// Fails because the function in the message returns false
failsWith(
t,
() =>
assertions.throws(
() => {
throw new Error('error');
},
{message: () => false},
),
{
assertion: 'throws',
message: '',
values: [
{label: 'Function threw unexpected exception:', formatted: /error/},
{label: 'Expected message to return true:', formatted: /Function/},
],
},
);
passes(t, () => assertions.throws(() => {
throw new Error('error');
}, {message: () => true}));
}));
test('.throws() returns the thrown error', t => {
@ -1066,7 +1138,7 @@ test('.throws() fails if passed a bad expectation', t => {
failsWith(t, () => assertions.throws(() => {}, {message: null}), {
assertion: 'throws',
message: 'The `message` property of the second argument to `t.throws()` must be a string or regular expression',
message: 'The `message` property of the second argument to `t.throws()` must be a string, regular expression or a function',
values: [{label: 'Called with:', formatted: /message: null/}],
});
@ -1136,7 +1208,7 @@ test('.throwsAsync() fails if passed a bad expectation', t => {
failsWith(t, () => assertions.throwsAsync(() => {}, {message: null}), {
assertion: 'throwsAsync',
message: 'The `message` property of the second argument to `t.throwsAsync()` must be a string or regular expression',
message: 'The `message` property of the second argument to `t.throwsAsync()` must be a string, regular expression or a function',
values: [{label: 'Called with:', formatted: /message: null/}],
}, {expectBoolean: false});

View file

@ -12,7 +12,7 @@ export type ThrowsExpectation = {
is?: Error;
/** The thrown error must have a message that equals the given string, or matches the regular expression. */
message?: string | RegExp;
message?: string | RegExp | ((message: string) => boolean);
/** The thrown error must have a name that equals the given string. */
name?: string;