Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix error if toMatchInlineSnapshot is called on resolves/rejects #773

Merged
merged 1 commit into from Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/vitest/src/integrations/chai/jest-expect.ts
Expand Up @@ -491,8 +491,9 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
)
})

utils.addProperty(chai.Assertion.prototype, 'resolves', function(this: any) {
utils.addProperty(chai.Assertion.prototype, 'resolves', function __VITEST_RESOLVES__(this: any) {
utils.flag(this, 'promise', 'resolves')
utils.flag(this, 'error', new Error('resolves'))
const obj = utils.flag(this, 'object')
const proxy: any = new Proxy(this, {
get: (target, key, receiver) => {
Expand All @@ -518,8 +519,9 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
return proxy
})

utils.addProperty(chai.Assertion.prototype, 'rejects', function(this: any) {
utils.addProperty(chai.Assertion.prototype, 'rejects', function __VITEST_REJECTS__(this: any) {
utils.flag(this, 'promise', 'rejects')
utils.flag(this, 'error', new Error('rejects'))
const obj = utils.flag(this, 'object')
const wrapper = typeof obj === 'function' ? obj() : obj // for jest compat
const proxy: any = new Proxy(this, {
Expand Down
6 changes: 4 additions & 2 deletions packages/vitest/src/integrations/snapshot/chai.ts
Expand Up @@ -44,14 +44,15 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
'toMatchInlineSnapshot',
function __VITEST_INLINE_SNAPSHOT__(this: Record<string, unknown>, properties?: object, inlineSnapshot?: string, message?: string) {
const expected = utils.flag(this, 'object')
const error = utils.flag(this, 'error')
if (typeof properties === 'string') {
message = inlineSnapshot
inlineSnapshot = properties
properties = undefined
}
if (inlineSnapshot)
inlineSnapshot = stripSnapshotIndentation(inlineSnapshot)
getSnapshotClient().assert(expected, message, true, properties, inlineSnapshot)
getSnapshotClient().assert(expected, message, true, properties, inlineSnapshot, error)
},
)
utils.addMethod(
Expand All @@ -67,7 +68,8 @@ export const SnapshotPlugin: ChaiPlugin = (chai, utils) => {
'toThrowErrorMatchingInlineSnapshot',
function __VITEST_INLINE_SNAPSHOT__(this: Record<string, unknown>, inlineSnapshot: string, message: string) {
const expected = utils.flag(this, 'object')
getSnapshotClient().assert(getErrorString(expected), message, true, undefined, inlineSnapshot)
const error = utils.flag(this, 'error')
getSnapshotClient().assert(getErrorString(expected), message, true, undefined, inlineSnapshot, error)
},
)
}
3 changes: 2 additions & 1 deletion packages/vitest/src/integrations/snapshot/client.ts
Expand Up @@ -43,7 +43,7 @@ export class SnapshotClient {
this.test = undefined
}

assert(received: unknown, message?: string, isInline = false, properties?: object, inlineSnapshot?: string): void {
assert(received: unknown, message?: string, isInline = false, properties?: object, inlineSnapshot?: string, error?: Error): void {
if (!this.test)
throw new Error('Snapshot cannot be used outside of test')

Expand Down Expand Up @@ -73,6 +73,7 @@ export class SnapshotClient {
testName,
received,
isInline,
error,
inlineSnapshot,
})

Expand Down
19 changes: 14 additions & 5 deletions packages/vitest/src/integrations/snapshot/port/state.ts
Expand Up @@ -9,7 +9,7 @@ import fs from 'fs'
import type { Config } from '@jest/types'
// import { getStackTraceLines, getTopFrame } from 'jest-message-util'
import type { OptionsReceived as PrettyFormatOptions } from 'pretty-format'
import type { SnapshotData, SnapshotMatchOptions, SnapshotStateOptions } from '../../../types'
import type { ParsedStack, SnapshotData, SnapshotMatchOptions, SnapshotStateOptions } from '../../../types'
import { slash } from '../../../utils'
import { parseStacktrace } from '../../../utils/source-map'
import type { InlineSnapshot } from './inlineSnapshot'
Expand Down Expand Up @@ -87,6 +87,18 @@ export default class SnapshotState {
})
}

private _getInlineSnapshotStack(stacks: ParsedStack[]) {
// if called inside resolves/rejects, stacktrace is different
const promiseIndex = stacks.findIndex(i => i.method.match(/__VITEST_(RESOLVES|REJECTS)__/))
if (promiseIndex !== -1)
return stacks[promiseIndex + 3]

// inline snapshot function is called __VITEST_INLINE_SNAPSHOT__
// in integrations/snapshot/chai.ts
const stackIndex = stacks.findIndex(i => i.method.includes('__VITEST_INLINE_SNAPSHOT__'))
return stackIndex !== -1 ? stacks[stackIndex + 2] : null
}

private _addSnapshot(
key: string,
receivedSerialized: string,
Expand All @@ -97,10 +109,7 @@ export default class SnapshotState {
const error = options.error || new Error('Unknown error')
const stacks = parseStacktrace(error, true)
stacks.forEach(i => i.file = slash(i.file))
// inline snapshot function is called __VITEST_INLINE_SNAPSHOT__
// in integrations/snapshot/chai.ts
const stackIndex = stacks.findIndex(i => i.method.includes('__VITEST_INLINE_SNAPSHOT__'))
const stack = stackIndex !== -1 ? stacks[stackIndex + 2] : null
const stack = this._getInlineSnapshotStack(stacks)
if (!stack) {
throw new Error(
`Vitest: Couldn't infer stack frame for inline snapshot.\n${JSON.stringify(stacks)}`,
Expand Down
12 changes: 12 additions & 0 deletions test/core/test/snapshot-inline.test.ts
Expand Up @@ -106,3 +106,15 @@ test('literal tag', () => {
"
`)
})

test('resolves', async() => {
const getText = async() => 'text'
await expect(getText()).resolves.toMatchInlineSnapshot('"text"')
})

test('rejects', async() => {
const getText = async() => {
throw new Error('error')
}
await expect(getText()).rejects.toMatchInlineSnapshot('[Error: error]')
})