···779779780780## toThrowError
781781782782-- **Type:** `(received: any) => Awaitable<void>`
782782+- **Type:** `(expected?: any) => Awaitable<void>`
783783784784- **Alias:** `toThrow`
785785···789789790790- `RegExp`: error message matches the pattern
791791- `string`: error message includes the substring
792792-- `Error`, `AsymmetricMatcher`: compare with a received object similar to `toEqual(received)`
792792+- any other value: compare with thrown value using deep equality (similar to `toEqual`)
793793794794:::tip
795795You must wrap the code in a function, otherwise the error will not be caught, and test will fail.
···845845846846test('throws on pineapples', async () => {
847847 await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty')
848848+})
849849+```
850850+:::
851851+852852+:::tip
853853+You can also test non-Error values that are thrown:
854854+855855+```ts
856856+test('throws non-Error values', () => {
857857+ expect(() => { throw 42 }).toThrowError(42)
858858+ expect(() => { throw { message: 'error' } }).toThrowError({ message: 'error' })
848859})
849860```
850861:::
+12-3
packages/expect/src/jest-expect.ts
···1616 arrayBufferEquality,
1717 generateToBeMessage,
1818 getObjectSubset,
1919+ isError,
1920 iterableEquality,
2021 equals as jestEquals,
2122 sparseArrayEquality,
···808809 )
809810 }
810811811811- if (expected instanceof Error) {
812812+ if (isError(expected)) {
812813 const equal = jestEquals(thrown, expected, [
813814 ...customTesters,
814815 iterableEquality,
···837838 )
838839 }
839840840840- throw new Error(
841841- `"toThrow" expects string, RegExp, function, Error instance or asymmetric matcher, got "${typeof expected}"`,
841841+ const equal = jestEquals(thrown, expected, [
842842+ ...customTesters,
843843+ iterableEquality,
844844+ ])
845845+ return this.assert(
846846+ equal,
847847+ 'expected a thrown value to equal #{exp}',
848848+ 'expected a thrown value not to equal #{exp}',
849849+ expected,
850850+ thrown,
842851 )
843852 },
844853 )
+18-3
packages/expect/src/jest-utils.ts
···8686 }
8787}
88888989+// https://github.com/jestjs/jest/blob/905bcbced3d40cdf7aadc4cdf6fb731c4bb3dbe3/packages/expect-utils/src/utils.ts#L509
9090+export function isError(value: unknown): value is Error {
9191+ if (typeof Error.isError === 'function') {
9292+ return Error.isError(value)
9393+ }
9494+ switch (Object.prototype.toString.call(value)) {
9595+ case '[object Error]':
9696+ case '[object Exception]':
9797+ case '[object DOMException]':
9898+ return true
9999+ default:
100100+ return value instanceof Error
101101+ }
102102+};
103103+89104// Equality function lovingly adapted from isEqual in
90105// [Underscore](http://underscorejs.org)
91106function eq(
···204219 return false
205220 }
206221207207- if (a instanceof Error && b instanceof Error) {
222222+ if (isError(a) && isError(b)) {
208223 try {
209224 return isErrorEqual(a, b, aStack, bStack, customTesters, hasKey)
210225 }
···257272 // - Error names, messages, causes, and errors are always compared, even if these are not enumerable properties. errors is also compared.
258273259274 let result = (
260260- Object.getPrototypeOf(a) === Object.getPrototypeOf(b)
275275+ Object.prototype.toString.call(a) === Object.prototype.toString.call(b)
261276 && a.name === b.name
262277 && a.message === b.message
263278 )
···581596function isObjectWithKeys(a: any) {
582597 return (
583598 isObject(a)
584584- && !(a instanceof Error)
599599+ && !isError(a)
585600 && !Array.isArray(a)
586601 && !(a instanceof Date)
587602 && !(a instanceof Set)
+4-3
packages/expect/src/types.ts
···8899import type { Test } from '@vitest/runner'
1010import type { MockInstance } from '@vitest/spy'
1111-import type { Constructable } from '@vitest/utils'
1211import type { Formatter } from 'tinyrainbow'
1312import type { AsymmetricMatcher } from './jest-asymmetric-matchers'
1413import type { diff, getMatcherUtils, stringify } from './jest-matcher-utils'
···535534 * @example
536535 * expect(() => functionWithError()).toThrow('Error message');
537536 * expect(() => parseJSON('invalid')).toThrow(SyntaxError);
537537+ * expect(() => { throw 42 }).toThrow(42);
538538 */
539539- toThrow: (expected?: string | Constructable | RegExp | Error) => void
539539+ toThrow: (expected?: any) => void
540540541541 /**
542542 * Used to test that a function throws when it is called.
···546546 * @example
547547 * expect(() => functionWithError()).toThrowError('Error message');
548548 * expect(() => parseJSON('invalid')).toThrowError(SyntaxError);
549549+ * expect(() => { throw 42 }).toThrowError(42);
549550 */
550550- toThrowError: (expected?: string | Constructable | RegExp | Error) => void
551551+ toThrowError: (expected?: any) => void
551552552553 /**
553554 * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time