From a4d69e16a5ddaf3f8feb610c9348b8116b4f1741 Mon Sep 17 00:00:00 2001 From: ninevra Date: Sun, 25 Oct 2020 21:31:42 -0700 Subject: [PATCH 1/3] Test that ObjectNotContaining is as documented Asserts that ObjectNotContaining matches values which do not contain _all_ of the sample's properties. Asserts that ObjectNotContaining matches iff ObjectContaining does not match. --- .../src/__tests__/asymmetricMatchers.test.ts | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/expect/src/__tests__/asymmetricMatchers.test.ts b/packages/expect/src/__tests__/asymmetricMatchers.test.ts index 6e1886b65409..ec48bc73a624 100644 --- a/packages/expect/src/__tests__/asymmetricMatchers.test.ts +++ b/packages/expect/src/__tests__/asymmetricMatchers.test.ts @@ -225,10 +225,21 @@ test('ObjectContaining does not mutate the sample', () => { test('ObjectNotContaining matches', () => { [ - objectNotContaining({}).asymmetricMatch('jest'), objectNotContaining({foo: 'foo'}).asymmetricMatch({bar: 'bar'}), objectNotContaining({foo: 'foo'}).asymmetricMatch({foo: 'foox'}), objectNotContaining({foo: undefined}).asymmetricMatch({}), + objectNotContaining({ + first: objectNotContaining({second: {}}), + }).asymmetricMatch({first: {second: {}}}), + objectNotContaining({first: {second: {}, third: {}}}).asymmetricMatch({ + first: {second: {}}, + }), + objectNotContaining({first: {second: {}}}).asymmetricMatch({ + first: {second: {}, third: {}}, + }), + objectNotContaining({foo: 'foo', jest: 'jest'}).asymmetricMatch({ + foo: 'foo', + }), ].forEach(test => { jestExpect(test).toEqual(true); }); @@ -236,19 +247,43 @@ test('ObjectNotContaining matches', () => { test('ObjectNotContaining does not match', () => { [ + objectNotContaining({}).asymmetricMatch('jest'), objectNotContaining({foo: 'foo'}).asymmetricMatch({ foo: 'foo', jest: 'jest', }), objectNotContaining({foo: undefined}).asymmetricMatch({foo: undefined}), + objectNotContaining({first: {second: {}}}).asymmetricMatch({ + first: {second: {}}, + }), objectNotContaining({ - first: objectNotContaining({second: {}}), + first: objectContaining({second: {}}), }).asymmetricMatch({first: {second: {}}}), + objectNotContaining({}).asymmetricMatch(null), + objectNotContaining({}).asymmetricMatch({}), ].forEach(test => { jestExpect(test).toEqual(false); }); }); +test('ObjectNotContaining inverts ObjectContaining', () => { + [ + [{}, null], + [{foo: 'foo'}, {foo: 'foo', jest: 'jest'}], + [{foo: 'foo', jest: 'jest'}, {foo: 'foo'}], + [{foo: undefined}, {foo: undefined}], + [{foo: undefined}, {}], + [{first: {second: {}}}, {first: {second: {}}}], + [{first: objectContaining({second: {}})}, {first: {second: {}}}], + [{first: objectNotContaining({second: {}})}, {first: {second: {}}}], + [{}, {foo: undefined}], + ].forEach(([sample, received]) => { + jestExpect(objectNotContaining(sample).asymmetricMatch(received)).toEqual( + !objectContaining(sample).asymmetricMatch(received), + ); + }); +}); + test('ObjectNotContaining throws for non-objects', () => { jestExpect(() => objectNotContaining(1337).asymmetricMatch()).toThrow(); }); From e8b007bce7d5dfcf3adef83a693cd45d82bf854a Mon Sep 17 00:00:00 2001 From: ninevra Date: Sun, 25 Oct 2020 21:32:36 -0700 Subject: [PATCH 2/3] Match ObjectNotContaining documentation --- packages/expect/src/asymmetricMatchers.ts | 33 +++++++---------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/packages/expect/src/asymmetricMatchers.ts b/packages/expect/src/asymmetricMatchers.ts index b20f3052ca97..c906f247e742 100644 --- a/packages/expect/src/asymmetricMatchers.ts +++ b/packages/expect/src/asymmetricMatchers.ts @@ -7,7 +7,6 @@ */ import {equals, fnNameFor, hasProperty, isA, isUndefined} from './jasmineUtils'; -import {emptyObject} from './utils'; export class AsymmetricMatcher { protected sample: T; @@ -162,31 +161,19 @@ class ObjectContaining extends AsymmetricMatcher> { ); } - if (this.inverse) { - for (const property in this.sample) { - if ( - hasProperty(other, property) && - equals(this.sample[property], other[property]) && - !emptyObject(this.sample[property]) && - !emptyObject(other[property]) - ) { - return false; - } - } + let result = true; - return true; - } else { - for (const property in this.sample) { - if ( - !hasProperty(other, property) || - !equals(this.sample[property], other[property]) - ) { - return false; - } + for (const property in this.sample) { + if ( + !hasProperty(other, property) || + !equals(this.sample[property], other[property]) + ) { + result = false; + break; } - - return true; } + + return this.inverse ? !result : result; } toString() { From 708e68ee49cf70a643fed4d67a4a889b4baa01e3 Mon Sep 17 00:00:00 2001 From: ninevra Date: Sun, 25 Oct 2020 22:25:09 -0700 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 130cfdad2da8..1deaa173c2f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixes +- `[expect]` [**BREAKING**] Revise `expect.not.objectContaining()` to be the inverse of `expect.objectContaining()`, as documented. ([#10708](https://github.com/facebook/jest/pull/10708)) - `[jest-resolve]` Replace read-pkg-up with escalade package ([#10781](https://github.com/facebook/jest/pull/10781)) - `[jest-runtime]` [**BREAKING**] Do not inject `global` variable into module wrapper ([#10644](https://github.com/facebook/jest/pull/10644)) - `[jest-runtime]` [**BREAKING**] remove long-deprecated `jest.addMatchers`, `jest.resetModuleRegistry`, and `jest.runTimersToTime` ([#9853](https://github.com/facebook/jest/pull/9853))