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(vitest): return detailed error when using toHaveReturnedWith #2163

Merged
merged 9 commits into from Oct 19, 2022
12 changes: 9 additions & 3 deletions packages/vitest/src/integrations/chai/jest-expect.ts
Expand Up @@ -589,11 +589,13 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
const spy = getSpy(this)
const spyName = spy.getMockName()
const pass = spy.mock.results.some(({ type, value: result }) => type === 'return' && jestEquals(value, result))
const returns = spy.mock.results.filter(({ type }) => type === 'return').map(({ value: result }) => result).toString()
this.assert(
pass,
`expected "${spyName}" to be successfully called with #{exp}`,
`expected "${spyName}" to not be successfully called with #{exp}`,
value,
`expected "${spyName}" to be successfully called having return #{exp} at least once`,
`expected "${spyName}" to not be successfully called having return #{exp}`,
`executions have a successful return value: ${value}`,
azaleta marked this conversation as resolved.
Show resolved Hide resolved
`executions returns: [${truncateString(returns)}]`,
)
})
def(['toHaveLastReturnedWith', 'lastReturnedWith'], function (value: any) {
Expand Down Expand Up @@ -713,3 +715,7 @@ function toString(value: any) {
return 'unknown'
}
}

function truncateString(str: string, length = 30) {
return str.length > length ? `${str.substring(0, length)}...` : str
}
58 changes: 58 additions & 0 deletions test/core/test/mocked.test.ts
@@ -1,3 +1,4 @@
import type { AssertionError } from 'assert'
import { assert, describe, expect, test, vi, vitest } from 'vitest'
// @ts-expect-error not typed module
import { value as virtualValue } from 'virtual-module'
Expand Down Expand Up @@ -134,6 +135,63 @@ test('async functions should be mocked', () => {
expect(asyncFunc()).resolves.toBe('foo')
})

describe('mocked function which fails on toReturnWith', () => {
test('zero call', () => {
const mock = vi.fn(() => 1)
try {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets' rewrite these tests with toThrow:

expect(() => expect(mock).toReturnWith(2)).toThrowErrorMatchingInlineSnapshot()

Two reasons:

  1. less code
  2. more reliable code (if first assertion won't fail, we will not make assertions inside a "catch", but the test will pass)

expect(mock).toReturnWith(2)
}
catch (e) {
const throwObj = e as AssertionError
expect(throwObj.expected).toMatchInlineSnapshot('"executions have a successful return value: 2"')
expect(throwObj.actual).toMatchInlineSnapshot('"executions returns: []"')
}
})

test('just one call', () => {
const mock = vi.fn(() => 1)
mock()
try {
expect(mock).toReturnWith(2)
}
catch (e) {
const throwObj = e as AssertionError
expect(throwObj.expected).toMatchInlineSnapshot('"executions have a successful return value: 2"')
expect(throwObj.actual).toMatchInlineSnapshot('"executions returns: [1]"')
}
})

test('multi calls', () => {
const mock = vi.fn(() => 1)
mock()
mock()
mock()
try {
expect(mock).toReturnWith(2)
}
catch (e) {
const throwObj = e as AssertionError
expect(throwObj.expected).toMatchInlineSnapshot('"executions have a successful return value: 2"')
expect(throwObj.actual).toMatchInlineSnapshot('"executions returns: [1,1,1]"')
}
})

test('all execution returns too long', () => {
const mock = vi.fn(() => 'AAAAAAAAAAAAAAAAAAAA')
mock()
mock()
mock()
try {
expect(mock).toReturnWith(2)
}
catch (e) {
const throwObj = e as AssertionError
expect(throwObj.expected).toMatchInlineSnapshot('"executions have a successful return value: 2"')
expect(throwObj.actual).toMatchInlineSnapshot('"executions returns: [AAAAAAAAAAAAAAAAAAAA,AAAAAAAAA...]"')
}
})
})

// This is here because mocking streams previously caused some problems (#1671).
test('streams', () => {
expect(exportedStream).toBeDefined()
Expand Down