Skip to content

Commit 9753fdc

Browse files
fix(objectContaining): Fixed a bug where ObjectContaining matched with non-object values. (#15463)
1 parent 1aeb8eb commit 9753fdc

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999
- `[jest-util]` Always load `mjs` files with `import` ([#15447](https://github.com/jestjs/jest/pull/15447))
100100
- `[jest-worker]` Properly handle a circular reference error when worker tries to send an assertion fails where either the expected or actual value is circular ([#15191](https://github.com/jestjs/jest/pull/15191))
101101
- `[jest-worker]` Properly handle a BigInt when worker tries to send an assertion fails where either the expected or actual value is BigInt ([#15191](https://github.com/jestjs/jest/pull/15191))
102+
- `[expect]` Resolve issue where `ObjectContaining` matched non-object values. ([#15463])(https://github.com/jestjs/jest/pull/15463).
103+
- Adds a `conditional/check` to ensure the argument passed to `expect` is an object.
104+
- Add unit tests for new `ObjectContaining` behavior.
105+
- Remove `invalid/wrong` test case assertions for `ObjectContaining`.
102106

103107
### Performance
104108

packages/expect/src/__tests__/asymmetricMatchers.test.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ test('ArrayNotContaining throws for non-arrays', () => {
184184
test('ObjectContaining matches', () => {
185185
const foo = Symbol('foo');
186186
for (const test of [
187-
objectContaining({}).asymmetricMatch('jest'),
188187
objectContaining({foo: 'foo'}).asymmetricMatch({foo: 'foo', jest: 'jest'}),
189188
objectContaining({foo: undefined}).asymmetricMatch({foo: undefined}),
190189
objectContaining({first: objectContaining({second: {}})}).asymmetricMatch({
@@ -247,6 +246,18 @@ test('ObjectContaining throws for non-objects', () => {
247246
);
248247
});
249248

249+
test('ObjectContaining does not match when non-objects are passed to the expect function as arguments', () => {
250+
for (const test of [
251+
objectContaining({}).asymmetricMatch('jest'),
252+
objectContaining({}).asymmetricMatch(10),
253+
objectContaining({}).asymmetricMatch(false),
254+
objectContaining({}).asymmetricMatch(undefined),
255+
objectContaining({}).asymmetricMatch([]),
256+
]) {
257+
jestExpect(test).toEqual(false);
258+
}
259+
});
260+
250261
test('ObjectContaining does not mutate the sample', () => {
251262
const sample = {foo: {bar: {}}};
252263
const sample_json = JSON.stringify(sample);
@@ -259,8 +270,6 @@ test('ObjectNotContaining matches', () => {
259270
const foo = Symbol('foo');
260271
const bar = Symbol('bar');
261272
for (const test of [
262-
objectContaining({}).asymmetricMatch(null),
263-
objectContaining({}).asymmetricMatch(undefined),
264273
objectNotContaining({[foo]: 'foo'}).asymmetricMatch({[bar]: 'bar'}),
265274
objectNotContaining({foo: 'foo'}).asymmetricMatch({bar: 'bar'}),
266275
objectNotContaining({foo: 'foo'}).asymmetricMatch({foo: 'foox'}),

packages/expect/src/asymmetricMatchers.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,22 @@ class ObjectContaining extends AsymmetricMatcher<
233233
}
234234

235235
asymmetricMatch(other: any) {
236+
// Ensures that the argument passed to the objectContaining method is an object
236237
if (typeof this.sample !== 'object') {
237238
throw new TypeError(
238239
`You must provide an object to ${this.toString()}, not '${typeof this
239240
.sample}'.`,
240241
);
241242
}
242243

244+
// Ensures that the argument passed to the expect function is an object
245+
// This is necessary to avoid matching of non-object values
246+
// Arrays are a special type of object, but having a valid match with a standard object
247+
// does not make sense, hence we do a simple array check
248+
if (typeof other !== 'object' || Array.isArray(other)) {
249+
return false;
250+
}
251+
243252
let result = true;
244253

245254
const matcherContext = this.getMatcherContext();

0 commit comments

Comments
 (0)