Skip to content

Commit

Permalink
Fix typings of toThrowWithMessage, support unconstructable errors (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
GerkinDev committed Jul 18, 2022
1 parent 14830d5 commit 3de8098
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 3 deletions.
14 changes: 12 additions & 2 deletions src/matchers/toThrowWithMessage.js
Expand Up @@ -85,9 +85,19 @@ export function toThrowWithMessage(callbackOrPromiseReturn, type, message) {
}

const pass = predicate(error, type, message);
const messageStr = message.toString();
let expectedError;
try {
expectedError = new type(messageStr);
} catch (err) {
const name = type.name;
expectedError = new Error();
expectedError.name = name;
expectedError.message = messageStr;
}
if (pass) {
return { pass: true, message: passMessage(utils, error, new type(message)) };
return { pass: true, message: passMessage(utils, error, expectedError) };
}

return { pass: false, message: failMessage(utils, error, new type(message)) };
return { pass: false, message: failMessage(utils, error, expectedError) };
}
40 changes: 40 additions & 0 deletions test/matchers/__snapshots__/toThrowWithMessage.test.js.snap
Expand Up @@ -56,6 +56,26 @@ Thrown:
"
`;

exports[`.toThrowWithMessage Async passes with an unconstructable error given a regex message 1`] = `
"<dim>expect(</intensity><red>function</color><dim>).not.toThrowWithMessage(</intensity><green>type</color><dim>, </intensity><green>message</color><dim>)</intensity>
Expected not to throw:
<green>[UnconstructableError: /42/]</color>
Thrown:
<red>[UnconstructableError: 42]</color>
"
`;

exports[`.toThrowWithMessage Async passes with an unconstructable error given a string message 1`] = `
"<dim>expect(</intensity><red>function</color><dim>).not.toThrowWithMessage(</intensity><green>type</color><dim>, </intensity><green>message</color><dim>)</intensity>
Expected not to throw:
<green>[UnconstructableError: 42]</color>
Thrown:
<red>[UnconstructableError: 42]</color>
"
`;

exports[`.toThrowWithMessage fails when a callback function is not a function 1`] = `
"<dim>expect(</intensity><red>function</color><dim>).toThrowWithMessage(</intensity><green>type</color><dim>, </intensity><green>message</color><dim>)</intensity>
Expand Down Expand Up @@ -142,3 +162,23 @@ Thrown:
<red>[TypeError: Expected message]</color>
"
`;

exports[`.toThrowWithMessage passes with an unconstructable error given a regex message 1`] = `
"<dim>expect(</intensity><red>function</color><dim>).not.toThrowWithMessage(</intensity><green>type</color><dim>, </intensity><green>message</color><dim>)</intensity>
Expected not to throw:
<green>[UnconstructableError: /42/]</color>
Thrown:
<red>[UnconstructableError: 42]</color>
"
`;

exports[`.toThrowWithMessage passes with an unconstructable error given a string message 1`] = `
"<dim>expect(</intensity><red>function</color><dim>).not.toThrowWithMessage(</intensity><green>type</color><dim>, </intensity><green>message</color><dim>)</intensity>
Expected not to throw:
<green>[UnconstructableError: 42]</color>
Thrown:
<red>[UnconstructableError: 42]</color>
"
`;
68 changes: 68 additions & 0 deletions test/matchers/toThrowWithMessage.test.js
Expand Up @@ -4,6 +4,16 @@ const { toThrowWithMessage } = matcher;

expect.extend(matcher);

class UnconstructableError extends Error {
constructor(message) {
if (typeof message !== 'number') {
throw new TypeError('Expected number arg');
}
super(message.toString());
this.name = 'UnconstructableError';
}
}

describe('.toThrowWithMessage', () => {
test('fails when callback function is not provided', () => {
const { pass, message } = toThrowWithMessage.call({
Expand Down Expand Up @@ -137,6 +147,34 @@ describe('.toThrowWithMessage', () => {
expect(message()).toMatchSnapshot();
});

test('passes with an unconstructable error given a string message', () => {
const callback = () => {
throw new UnconstructableError(42);
};
const { pass, message } = toThrowWithMessage.call(
{ utils: { matcherHint: matcherHint, printExpected: printExpected, printReceived: printReceived } },
callback,
UnconstructableError,
'42',
);
expect(pass).toBe(true);
expect(message()).toMatchSnapshot();
});

test('passes with an unconstructable error given a regex message', () => {
const callback = () => {
throw new UnconstructableError(42);
};
const { pass, message } = toThrowWithMessage.call(
{ utils: { matcherHint: matcherHint, printExpected: printExpected, printReceived: printReceived } },
callback,
UnconstructableError,
/42/,
);
expect(pass).toBe(true);
expect(message()).toMatchSnapshot();
});

test('passes when given an Error with a string error message: end to end', () => {
expect(() => {
throw new TypeError('Expected message');
Expand Down Expand Up @@ -254,6 +292,36 @@ describe('.toThrowWithMessage', () => {
expect(message()).toMatchSnapshot();
});

test('passes with an unconstructable error given a string message', () => {
const rejectValue = new UnconstructableError(42);
const { pass, message } = toThrowWithMessage.call(
{
utils: { matcherHint: matcherHint, printExpected: printExpected, printReceived: printReceived },
promise: 'rejects',
},
rejectValue,
UnconstructableError,
'42',
);
expect(pass).toBe(true);
expect(message()).toMatchSnapshot();
});

test('passes with an unconstructable error given a regex message', () => {
const rejectValue = new UnconstructableError(42);
const { pass, message } = toThrowWithMessage.call(
{
utils: { matcherHint: matcherHint, printExpected: printExpected, printReceived: printReceived },
promise: 'rejects',
},
rejectValue,
UnconstructableError,
/42/,
);
expect(pass).toBe(true);
expect(message()).toMatchSnapshot();
});

test('passes on rejects with rejected promise when given an Error with a string error message: end to end', async () => {
await expect(Promise.reject(new SyntaxError('Expected message'))).rejects.toThrowWithMessage(
SyntaxError,
Expand Down
8 changes: 7 additions & 1 deletion types/index.d.ts
Expand Up @@ -387,7 +387,13 @@ declare namespace jest {
* @param {Function} type
* @param {String | RegExp} message
*/
toThrowWithMessage(type: (...args: unknown[]) => unknown, message: string | RegExp): R;
toThrowWithMessage(
type:
| (new (...args: any[]) => { message: string })
| (abstract new (...args: any[]) => { message: string })
| ((...args: any[]) => { message: string }),
message: string | RegExp,
): R;

/**
* Use `.toBeEmptyObject` when checking if a value is an empty `Object`.
Expand Down

0 comments on commit 3de8098

Please sign in to comment.