diff --git a/packages/expect/src/jest-expect.ts b/packages/expect/src/jest-expect.ts index dad17d6d31d7..e483676f1062 100644 --- a/packages/expect/src/jest-expect.ts +++ b/packages/expect/src/jest-expect.ts @@ -1098,7 +1098,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => { return (...args: any[]) => { utils.flag(this, '_name', key) - const promise = obj.then( + const promise = Promise.resolve(obj).then( (value: any) => { utils.flag(this, 'object', value) return result.call(this, ...args) @@ -1111,13 +1111,17 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => { { showDiff: false }, ) as Error _error.cause = err - _error.stack = (error.stack as string).replace( - error.message, - _error.message, - ) throw _error }, - ) + ).catch((err: any) => { + if (isError(err) && error.stack) { + err.stack = error.stack.replace( + error.message, + err.message, + ) + } + throw err + }) return recordAsyncExpect( test, @@ -1166,7 +1170,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => { return (...args: any[]) => { utils.flag(this, '_name', key) - const promise = wrapper.then( + const promise = Promise.resolve(wrapper).then( (value: any) => { const _error = new AssertionError( `promise resolved "${utils.inspect( @@ -1178,17 +1182,21 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => { actual: value, }, ) as any - _error.stack = (error.stack as string).replace( - error.message, - _error.message, - ) throw _error }, (err: any) => { utils.flag(this, 'object', err) return result.call(this, ...args) }, - ) + ).catch((err: any) => { + if (isError(err) && error.stack) { + err.stack = error.stack.replace( + error.message, + err.message, + ) + } + throw err + }) return recordAsyncExpect( test, diff --git a/test/cli/test/stacktraces.test.ts b/test/cli/test/stacktraces.test.ts index 042663203c97..717fcae406e3 100644 --- a/test/cli/test/stacktraces.test.ts +++ b/test/cli/test/stacktraces.test.ts @@ -1,7 +1,7 @@ import { resolve } from 'pathe' import { glob } from 'tinyglobby' import { describe, expect, it } from 'vitest' -import { runVitest } from '../../test-utils' +import { runInlineTests, runVitest } from '../../test-utils' // To prevent the warning coming up in snapshots process.setMaxListeners(20) @@ -193,3 +193,123 @@ it('custom helper with captureStackTrace', async () => { } `) }) + +it('resolves/rejects', async () => { + const { stderr, errorTree } = await runInlineTests({ + 'repro.test.ts': ` + import { test, expect } from 'vitest' + + test('resolves: resolved promise with mismatched value', async () => { + await expect(Promise.resolve(3)).resolves.toBe(4) + }) + + test('rejects: rejected promise with mismatched value', async () => { + await expect(Promise.reject(3)).rejects.toBe(4) + }) + + test('rejects: resolves when rejection expected', async () => { + await expect(Promise.resolve(3)).rejects.toBe(4) + }) + + test('resolves: rejects when resolve expected', async () => { + await expect(Promise.reject(3)).resolves.toBe(4) + }) + `, + }) + + expect(stderr).toMatchInlineSnapshot(` + " + ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 4 ⎯⎯⎯⎯⎯⎯⎯ + + FAIL repro.test.ts > resolves: resolved promise with mismatched value + AssertionError: expected 3 to be 4 // Object.is equality + + - Expected + + Received + + - 4 + + 3 + + ❯ repro.test.ts:5:40 + 3| + 4| test('resolves: resolved promise with mismatched value', async (… + 5| await expect(Promise.resolve(3)).resolves.toBe(4) + | ^ + 6| }) + 7| + + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯ + + FAIL repro.test.ts > rejects: rejected promise with mismatched value + AssertionError: expected 3 to be 4 // Object.is equality + + - Expected + + Received + + - 4 + + 3 + + ❯ repro.test.ts:9:39 + 7| + 8| test('rejects: rejected promise with mismatched value', async ()… + 9| await expect(Promise.reject(3)).rejects.toBe(4) + | ^ + 10| }) + 11| + + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/4]⎯ + + FAIL repro.test.ts > rejects: resolves when rejection expected + AssertionError: promise resolved "3" instead of rejecting + + - Expected: + Error { + "message": "rejected promise", + } + + + Received: + 3 + + ❯ repro.test.ts:13:40 + 11| + 12| test('rejects: resolves when rejection expected', async () => { + 13| await expect(Promise.resolve(3)).rejects.toBe(4) + | ^ + 14| }) + 15| + + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/4]⎯ + + FAIL repro.test.ts > resolves: rejects when resolve expected + AssertionError: promise rejected "3" instead of resolving + ❯ repro.test.ts:17:39 + 15| + 16| test('resolves: rejects when resolve expected', async () => { + 17| await expect(Promise.reject(3)).resolves.toBe(4) + | ^ + 18| }) + 19| + + ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/4]⎯ + + " + `) + expect(errorTree()).toMatchInlineSnapshot(` + { + "repro.test.ts": { + "rejects: rejected promise with mismatched value": [ + "expected 3 to be 4 // Object.is equality", + ], + "rejects: resolves when rejection expected": [ + "promise resolved "3" instead of rejecting", + ], + "resolves: rejects when resolve expected": [ + "promise rejected "3" instead of resolving", + ], + "resolves: resolved promise with mismatched value": [ + "expected 3 to be 4 // Object.is equality", + ], + }, + } + `) +})