Skip to content

Commit

Permalink
Recurse proto chain in hasPropertyInObject
Browse files Browse the repository at this point in the history
This way we can catch the actual props of the object
without catching those in Object.prototype
  • Loading branch information
souldzin committed Aug 21, 2020
1 parent a8e7e67 commit 3467338
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
19 changes: 19 additions & 0 deletions packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap
Expand Up @@ -3988,6 +3988,18 @@ exports[`toMatchObject() {pass: false} expect({"a": "b"}).toMatchObject({"c": "d
<d> }</>
`;

exports[`toMatchObject() {pass: false} expect({"a": "b"}).toMatchObject({"toString": Any<Function>}) 1`] = `
<d>expect(</><r>received</><d>).</>toMatchObject<d>(</><g>expected</><d>)</>

<g>- Expected - 0</>
<r>+ Received + 1</>

<d> Object {</>
<r>+ "a": "b",</>
<d> "toString": Any<Function>,</>
<d> }</>
`;

exports[`toMatchObject() {pass: false} expect({"a": [{"a": "a", "b": "b"}]}).toMatchObject({"a": [{"a": "c"}]}) 1`] = `
<d>expect(</><r>received</><d>).</>toMatchObject<d>(</><g>expected</><d>)</>

Expand Down Expand Up @@ -4246,6 +4258,13 @@ Expected: not <g>{"t": {"x": {"r": "r"}}}</>
Received: <r>{"a": "b", "t": {"x": {"r": "r"}, "z": "z"}}</>
`;

exports[`toMatchObject() {pass: true} expect({"a": "b", "toString": [Function toString]}).toMatchObject({"toString": Any<Function>}) 1`] = `
<d>expect(</><r>received</><d>).</>not<d>.</>toMatchObject<d>(</><g>expected</><d>)</>

Expected: not <g>{"toString": Any<Function>}</>
Received: <r>{"a": "b", "toString": [Function toString]}</>
`;

exports[`toMatchObject() {pass: true} expect({"a": "b"}).toMatchObject({"a": "b"}) 1`] = `
<d>expect(</><r>received</><d>).</>not<d>.</>toMatchObject<d>(</><g>expected</><d>)</>

Expand Down
2 changes: 2 additions & 0 deletions packages/expect/src/__tests__/matchers.test.js
Expand Up @@ -2103,6 +2103,7 @@ describe('toMatchObject()', () => {
// these keys a little smarter before reporting accurately.
[new Sub(), {a: undefined, b: 'b', c: 'c'}],
[withDefineProperty(new Sub(), 'd', 4), {d: 4}],
[{a: 'b', toString() {}}, {toString: jestExpect.any(Function)}],
]);

testToMatchSnapshots([
Expand Down Expand Up @@ -2150,6 +2151,7 @@ describe('toMatchObject()', () => {
{a: 'b', c: 'd', [Symbol.for('jest')]: 'jest'},
{a: 'c', [Symbol.for('jest')]: expect.any(String)},
],
[{a: 'b'}, {toString: jestExpect.any(Function)}],
]);

[
Expand Down
15 changes: 13 additions & 2 deletions packages/expect/src/utils.ts
Expand Up @@ -21,8 +21,19 @@ type GetPath = {
value?: unknown;
};

const hasPropertyInObject = (object: object, key: string) =>
typeof object === 'object' && key in object;
const hasPropertyInObject = (object: object, key: string) => {
const shouldTerminate =
!object || typeof object !== 'object' || object === Object.prototype;

if (shouldTerminate) {
return false;
}

return (
Object.prototype.hasOwnProperty.call(object, key) ||
hasPropertyInObject(Object.getPrototypeOf(object), key)
);
};

// Return whether object instance inherits getter from its class.
const hasGetterFromConstructor = (object: object, key: string) => {
Expand Down

0 comments on commit 3467338

Please sign in to comment.