Skip to content

Commit

Permalink
fix(expect): fix toHaveProperty assertion error diff (vitest-dev#4734)
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa authored and LorenzoBloedow committed Dec 19, 2023
1 parent 35b4be9 commit 6a2394c
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
5 changes: 3 additions & 2 deletions packages/expect/src/jest-expect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
if (Array.isArray(args[0]))
args[0] = args[0].map(key => String(key).replace(/([.[\]])/g, '\\$1')).join('.')

const actual = this._obj
const actual = this._obj as any
const [propertyName, expected] = args
const getValue = () => {
const hasOwn = Object.prototype.hasOwnProperty.call(actual, propertyName)
Expand All @@ -347,7 +347,8 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
pass,
`expected #{this} to have property "${propertyName}"${valueString}`,
`expected #{this} to not have property "${propertyName}"${valueString}`,
actual,
expected,
exists ? value : undefined,
)
})
def('toBeCloseTo', function (received: number, precision = 2) {
Expand Down
92 changes: 92 additions & 0 deletions test/core/test/jest-expect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -903,4 +903,96 @@ it('correctly prints diff with asymmetric matchers', () => {
}
})

it('toHaveProperty error diff', () => {
setupColors(getDefaultColors())

// make it easy for dev who trims trailing whitespace on IDE
function trim(s: string): string {
return s.replaceAll(/ *$/gm, '')
}

function getError(f: () => unknown) {
try {
f()
return expect.unreachable()
}
catch (error) {
const processed = processError(error)
return [processed.message, trim(processed.diff)]
}
}

// non match value
expect(getError(() => expect({ name: 'foo' }).toHaveProperty('name', 'bar'))).toMatchInlineSnapshot(`
[
"expected { name: 'foo' } to have property "name" with value 'bar'",
"- Expected
+ Received
- bar
+ foo",
]
`)

// non match key
expect(getError(() => expect({ noName: 'foo' }).toHaveProperty('name', 'bar'))).toMatchInlineSnapshot(`
[
"expected { noName: 'foo' } to have property "name" with value 'bar'",
"- Expected:
"bar"
+ Received:
undefined",
]
`)

// non match value (with asymmetric matcher)
expect(getError(() => expect({ name: 'foo' }).toHaveProperty('name', expect.any(Number)))).toMatchInlineSnapshot(`
[
"expected { name: 'foo' } to have property "name" with value Any{ …(3) }",
"- Expected:
Any<Number>
+ Received:
"foo"",
]
`)

// non match key (with asymmetric matcher)
expect(getError(() => expect({ noName: 'foo' }).toHaveProperty('name', expect.any(Number)))).toMatchInlineSnapshot(`
[
"expected { noName: 'foo' } to have property "name" with value Any{ …(3) }",
"- Expected:
Any<Number>
+ Received:
undefined",
]
`)

// non match value (deep key)
expect(getError(() => expect({ parent: { name: 'foo' } }).toHaveProperty('parent.name', 'bar'))).toMatchInlineSnapshot(`
[
"expected { parent: { name: 'foo' } } to have property "parent.name" with value 'bar'",
"- Expected
+ Received
- bar
+ foo",
]
`)

// non match key (deep key)
expect(getError(() => expect({ parent: { noName: 'foo' } }).toHaveProperty('parent.name', 'bar'))).toMatchInlineSnapshot(`
[
"expected { parent: { noName: 'foo' } } to have property "parent.name" with value 'bar'",
"- Expected:
"bar"
+ Received:
undefined",
]
`)
})

it('timeout', () => new Promise(resolve => setTimeout(resolve, 500)))

0 comments on commit 6a2394c

Please sign in to comment.