Skip to content

Commit

Permalink
Change expect.not.objectContaining() to match documentation (#10708)
Browse files Browse the repository at this point in the history
  • Loading branch information
ninevra authored Nov 5, 2020
1 parent 786d227 commit c732ed9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
39 changes: 37 additions & 2 deletions packages/expect/src/__tests__/asymmetricMatchers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,30 +225,65 @@ 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);
});
});

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();
});
Expand Down
33 changes: 10 additions & 23 deletions packages/expect/src/asymmetricMatchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/

import {equals, fnNameFor, hasProperty, isA, isUndefined} from './jasmineUtils';
import {emptyObject} from './utils';

export class AsymmetricMatcher<T> {
protected sample: T;
Expand Down Expand Up @@ -162,31 +161,19 @@ class ObjectContaining extends AsymmetricMatcher<Record<string, unknown>> {
);
}

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() {
Expand Down

0 comments on commit c732ed9

Please sign in to comment.