Skip to content

Commit

Permalink
fix(expect): fix toEqual and toMatchObject with circular referenc…
Browse files Browse the repository at this point in the history
…es (#5535)
  • Loading branch information
hi-ogawa committed Apr 17, 2024
1 parent ea3c16e commit 9e6417c
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 12 deletions.
21 changes: 11 additions & 10 deletions packages/expect/src/jest-expect.ts
Expand Up @@ -164,17 +164,18 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
const pass = jestEquals(actual, expected, [...customTesters, iterableEquality, subsetEquality])
const isNot = utils.flag(this, 'negate') as boolean
const { subset: actualSubset, stripped } = getObjectSubset(actual, expected)
const msg = utils.getMessage(
this,
[
pass,
'expected #{this} to match object #{exp}',
'expected #{this} to not match object #{exp}',
expected,
actualSubset,
],
)
if ((pass && isNot) || (!pass && !isNot)) {
const msg = utils.getMessage(
this,
[
pass,
'expected #{this} to match object #{exp}',
'expected #{this} to not match object #{exp}',
expected,
actualSubset,
false,
],
)
const message = stripped === 0 ? msg : `${msg}\n(${stripped} matching ${stripped === 1 ? 'property' : 'properties'} omitted from actual)`
throw new AssertionError(message, { showDiff: true, expected, actual: actualSubset })
}
Expand Down
4 changes: 2 additions & 2 deletions packages/expect/src/jest-utils.ts
Expand Up @@ -334,7 +334,7 @@ export function iterableEquality(a: any, b: any, customTesters: Array<Tester> =
return iterableEquality(
a,
b,
[...filteredCustomTesters],
[...customTesters],
[...aStack],
[...bStack],
)
Expand Down Expand Up @@ -452,7 +452,7 @@ export function subsetEquality(object: unknown, subset: unknown, customTesters:
return undefined

return Object.keys(subset).every((key) => {
if (isObjectWithKeys(subset[key])) {
if (typeof subset[key] === 'object') {
if (seenReferences.has(subset[key]))
return equals(object[key], subset[key], filteredCustomTesters)

Expand Down
60 changes: 60 additions & 0 deletions test/core/test/expect-circular.test.ts
@@ -0,0 +1,60 @@
import { describe, expect, test } from 'vitest'

describe('circular equality', () => {
test('object, set, map', () => {
// https://github.com/vitest-dev/vitest/issues/5533
function gen() {
const obj = {
a: new Set<any>(),
b: new Map<any, any>(),
}
obj.a.add(obj)
obj.b.set('k', obj)
return obj
}
expect(gen()).toEqual(gen())
expect(gen()).toMatchObject(gen())
})

test('object, set', () => {
function gen() {
const obj = {
a: new Set<any>(),
b: new Set<any>(),
}
obj.a.add(obj)
obj.b.add(obj)
return obj
}
expect(gen()).toEqual(gen())
expect(gen()).toMatchObject(gen())
})

test('array, set', () => {
function gen() {
const obj = [new Set<any>(), new Set<any>()]
obj[0].add(obj)
obj[1].add(obj)
return obj
}
expect(gen()).toEqual(gen())
expect(gen()).toMatchObject(gen())
})

test('object, array', () => {
// https://github.com/jestjs/jest/issues/14734
function gen() {
const a: any = {
v: 1,
}
const c1: any = {
ref: [],
}
c1.ref.push(c1)
a.ref = c1
return a
}
expect(gen()).toEqual(gen())
expect(gen()).toMatchObject(gen())
})
})

0 comments on commit 9e6417c

Please sign in to comment.