Skip to content

Commit 480be1a

Browse files
authored
fix(core): Fix objectContaining expect utility to have more compatibility to jest's one (#8241)
1 parent a0f9ae3 commit 480be1a

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

packages/expect/src/jest-asymmetric-matchers.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export class Anything extends AsymmetricMatcher<void> {
108108
}
109109

110110
export class ObjectContaining extends AsymmetricMatcher<
111-
Record<string, unknown>
111+
Record<string | symbol | number, unknown>
112112
> {
113113
constructor(sample: Record<string, unknown>, inverse = false) {
114114
super(sample, inverse)
@@ -126,18 +126,27 @@ export class ObjectContaining extends AsymmetricMatcher<
126126
return obj.constructor.prototype
127127
}
128128

129-
hasProperty(obj: object | null, property: string): boolean {
129+
hasProperty(obj: object | null, property: string | symbol): boolean {
130130
if (!obj) {
131131
return false
132132
}
133133

134-
if (Object.prototype.hasOwnProperty.call(obj, property)) {
134+
if (Object.hasOwn(obj, property)) {
135135
return true
136136
}
137137

138138
return this.hasProperty(this.getPrototype(obj), property)
139139
}
140140

141+
getProperties(obj: object): (string | symbol)[] {
142+
return [
143+
...Object.keys(obj),
144+
...Object.getOwnPropertySymbols(obj).filter(
145+
s => Object.getOwnPropertyDescriptor(obj, s)?.enumerable,
146+
),
147+
]
148+
}
149+
141150
asymmetricMatch(other: any): boolean {
142151
if (typeof this.sample !== 'object') {
143152
throw new TypeError(
@@ -149,14 +158,21 @@ export class ObjectContaining extends AsymmetricMatcher<
149158
let result = true
150159

151160
const matcherContext = this.getMatcherContext()
152-
for (const property in this.sample) {
161+
const properties = this.getProperties(this.sample)
162+
for (const property of properties) {
153163
if (
154164
!this.hasProperty(other, property)
155-
|| !equals(
156-
this.sample[property],
157-
other[property],
158-
matcherContext.customTesters,
159-
)
165+
) {
166+
result = false
167+
break
168+
}
169+
const value = Object.getOwnPropertyDescriptor(this.sample, property)?.value ?? this.sample[property]
170+
const otherValue = Object.getOwnPropertyDescriptor(other, property)?.value ?? other[property]
171+
if (!equals(
172+
value,
173+
otherValue,
174+
matcherContext.customTesters,
175+
)
160176
) {
161177
result = false
162178
break

test/core/test/jest-expect.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ describe('jest-expect', () => {
147147
expect(undefined).not.toEqual(expect.anything())
148148
expect({ a: 0, b: 0 }).toEqual(expect.objectContaining({ a: 0 }))
149149
expect({ a: 0, b: 0 }).not.toEqual(expect.objectContaining({ z: 0 }))
150+
// objectContaining with symbol key
151+
const symbolForObjectContaining = Symbol('symbolForObjectContaining')
152+
expect({ [symbolForObjectContaining]: 0 }).toEqual(expect.objectContaining({ [symbolForObjectContaining]: 0 }))
153+
expect({ [symbolForObjectContaining]: 0 }).not.toEqual(expect.objectContaining({ [symbolForObjectContaining]: 1 }))
150154
expect(0).toEqual(expect.any(Number))
151155
expect('string').toEqual(expect.any(String))
152156
expect('string').not.toEqual(expect.any(Number))

0 commit comments

Comments
 (0)