Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions packages/expect/src/jest-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -783,27 +783,33 @@ export function getObjectSubset(
})
}

for (const key of getObjectKeys(object)) {
if (hasPropertyInObject(subset, key)) {
// Iterate subset's keys (not object's own enumerable keys) so that
// inherited/accessor properties -- e.g. DOM element properties
// like `tagName`, which live on the prototype chain -- are still
// picked up via the `in` operator. See #6939.
for (const key of getObjectKeys(subset)) {
if (key in object) {
trimmed[key] = seenReferences.has(object[key])
? seenReferences.get(object[key])
: getObjectSubsetWithContext(seenReferences)(
object[key],
subset[key],
)
}
else {
if (!seenReferences.has(object[key])) {
stripped += 1
if (isObject(object[key])) {
stripped += getObjectKeys(object[key]).length
}

getObjectSubsetWithContext(seenReferences)(
object[key],
subset[key],
)
}

// Preserve "N properties omitted from actual" messaging by still
// counting object's own extra keys not present in subset.
for (const key of getObjectKeys(object)) {
if (!hasPropertyInObject(subset, key) && !seenReferences.has(object[key])) {
stripped += 1
if (isObject(object[key])) {
stripped += getObjectKeys(object[key]).length
}
getObjectSubsetWithContext(seenReferences)(
object[key],
subset[key],
)
}
}

Expand Down
31 changes: 31 additions & 0 deletions test/unit/test/jest-expect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,37 @@ it('toMatchObject error diff', () => {
}",
]
`)
// https://github.com/vitest-dev/vitest/issues/6939
// properties inherited via the prototype chain (e.g. DOM elements) should
// still be picked up when building the toMatchObject diff, instead of
// falling back to showing the raw object.
{
const proto = {
get tagName() {
return 'DIV'
},
}
const domLike = Object.create(proto)
domLike.id = 'root'

expect(domLike).toMatchObject({ tagName: 'DIV', id: 'root' })

expect(getError(() =>
expect(domLike).toMatchObject({ tagName: 'SPAN', id: 'root' }),
)).toMatchInlineSnapshot(`
[
"expected { id: 'root' } to match object { tagName: 'SPAN', id: 'root' }",
"- Expected
+ Received

{
"id": "root",
- "tagName": "SPAN",
+ "tagName": "DIV",
}",
]
`)
}
})

it('toHaveProperty error diff', () => {
Expand Down
Loading