From 600130a379685f329e41947039d831afd2658043 Mon Sep 17 00:00:00 2001 From: Chris Blossom Date: Mon, 7 May 2018 11:33:14 -0700 Subject: [PATCH] Fix for #6138: Deep compare set values and map keys --- CHANGELOG.md | 2 + .../__snapshots__/matchers.test.js.snap | 201 ++++++++++++++++++ .../expect/src/__tests__/matchers.test.js | 38 ++++ packages/expect/src/utils.js | 34 ++- 4 files changed, 271 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c7acc04eb1e..2f88fddfdada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -150,6 +150,8 @@ configuration ([#5976](https://github.com/facebook/jest/pull/5976)) * `[website]` Fix website docs ([#5853](https://github.com/facebook/jest/pull/5853)) +* `[expect]` Fix isEqual Set and Map to compare object values and keys + regardless of order ([#6150](https://github.com/facebook/jest/pull/6150)) ### Chore & Maintenance diff --git a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap index 711f01c60f77..5dd69d14b74e 100644 --- a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap @@ -2295,6 +2295,88 @@ Difference: }" `; +exports[`.toEqual() {pass: false} expect(Map {["v"] => 1}).toEqual(Map {["v"] => 2}) 1`] = ` +"expect(received).toEqual(expected) + +Expected value to equal: + Map {[\\"v\\"] => 2} +Received: + Map {[\\"v\\"] => 1} + +Difference: + +- Expected ++ Received + + Map { + Array [ + \\"v\\", +- ] => 2, ++ ] => 1, + }" +`; + +exports[`.toEqual() {pass: false} expect(Map {[1] => "one", [2] => "two", [3] => "three", [3] => "four"}).not.toEqual(Map {[3] => "three", [3] => "four", [2] => "two", [1] => "one"}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Map {[3] => \\"three\\", [3] => \\"four\\", [2] => \\"two\\", [1] => \\"one\\"} +Received: + Map {[1] => \\"one\\", [2] => \\"two\\", [3] => \\"three\\", [3] => \\"four\\"}" +`; + +exports[`.toEqual() {pass: false} expect(Map {[1] => "one", [2] => "two"}).not.toEqual(Map {[2] => "two", [1] => "one"}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Map {[2] => \\"two\\", [1] => \\"one\\"} +Received: + Map {[1] => \\"one\\", [2] => \\"two\\"}" +`; + +exports[`.toEqual() {pass: false} expect(Map {[1] => Map {[1] => "one"}, [2] => Map {[2] => "two"}}).not.toEqual(Map {[2] => Map {[2] => "two"}, [1] => Map {[1] => "one"}}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Map {[2] => Map {[2] => \\"two\\"}, [1] => Map {[1] => \\"one\\"}} +Received: + Map {[1] => Map {[1] => \\"one\\"}, [2] => Map {[2] => \\"two\\"}}" +`; + +exports[`.toEqual() {pass: false} expect(Map {[1] => Map {[1] => "one"}}).toEqual(Map {[1] => Map {[1] => "two"}}) 1`] = ` +"expect(received).toEqual(expected) + +Expected value to equal: + Map {[1] => Map {[1] => \\"two\\"}} +Received: + Map {[1] => Map {[1] => \\"one\\"}} + +Difference: + +- Expected ++ Received + +@@ -2,8 +2,8 @@ + Array [ + 1, + ] => Map { + Array [ + 1, +- ] => \\"two\\", ++ ] => \\"one\\", + }, + }" +`; + +exports[`.toEqual() {pass: false} expect(Map {{"a": 1} => "one", {"b": 2} => "two"}).not.toEqual(Map {{"b": 2} => "two", {"a": 1} => "one"}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Map {{\\"b\\": 2} => \\"two\\", {\\"a\\": 1} => \\"one\\"} +Received: + Map {{\\"a\\": 1} => \\"one\\", {\\"b\\": 2} => \\"two\\"}" +`; + exports[`.toEqual() {pass: false} expect(Map {}).not.toEqual(Map {}) 1`] = ` "expect(received).not.toEqual(expected) @@ -2354,6 +2436,92 @@ Difference: }" `; +exports[`.toEqual() {pass: false} expect(Map {1 => ["one"], 2 => ["two"]}).not.toEqual(Map {2 => ["two"], 1 => ["one"]}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Map {2 => [\\"two\\"], 1 => [\\"one\\"]} +Received: + Map {1 => [\\"one\\"], 2 => [\\"two\\"]}" +`; + +exports[`.toEqual() {pass: false} expect(Set {[1], [2], [3], [3]}).not.toEqual(Set {[3], [3], [2], [1]}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Set {[3], [3], [2], [1]} +Received: + Set {[1], [2], [3], [3]}" +`; + +exports[`.toEqual() {pass: false} expect(Set {[1], [2]}).not.toEqual(Set {[2], [1]}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Set {[2], [1]} +Received: + Set {[1], [2]}" +`; + +exports[`.toEqual() {pass: false} expect(Set {[1], [2]}).toEqual(Set {[1], [2], [2]}) 1`] = ` +"expect(received).toEqual(expected) + +Expected value to equal: + Set {[1], [2], [2]} +Received: + Set {[1], [2]} + +Difference: + +- Expected ++ Received + +@@ -3,9 +3,6 @@ + 1, + ], + Array [ + 2, + ], +- Array [ +- 2, +- ], + }" +`; + +exports[`.toEqual() {pass: false} expect(Set {[1], [2]}).toEqual(Set {[1], [2], [3]}) 1`] = ` +"expect(received).toEqual(expected) + +Expected value to equal: + Set {[1], [2], [3]} +Received: + Set {[1], [2]} + +Difference: + +- Expected ++ Received + +@@ -3,9 +3,6 @@ + 1, + ], + Array [ + 2, + ], +- Array [ +- 3, +- ], + }" +`; + +exports[`.toEqual() {pass: false} expect(Set {{"a": 1}, {"b": 2}}).not.toEqual(Set {{"b": 2}, {"a": 1}}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Set {{\\"b\\": 2}, {\\"a\\": 1}} +Received: + Set {{\\"a\\": 1}, {\\"b\\": 2}}" +`; + exports[`.toEqual() {pass: false} expect(Set {}).not.toEqual(Set {}) 1`] = ` "expect(received).not.toEqual(expected) @@ -2421,6 +2589,39 @@ Difference: }" `; +exports[`.toEqual() {pass: false} expect(Set {Set {[1]}, Set {[2]}}).not.toEqual(Set {Set {[2]}, Set {[1]}}) 1`] = ` +"expect(received).not.toEqual(expected) + +Expected value to not equal: + Set {Set {[2]}, Set {[1]}} +Received: + Set {Set {[1]}, Set {[2]}}" +`; + +exports[`.toEqual() {pass: false} expect(Set {Set {1}, Set {2}}).toEqual(Set {Set {1}, Set {3}}) 1`] = ` +"expect(received).toEqual(expected) + +Expected value to equal: + Set {Set {1}, Set {3}} +Received: + Set {Set {1}, Set {2}} + +Difference: + +- Expected ++ Received + + Set { + Set { + 1, + }, + Set { +- 3, ++ 2, + }, + }" +`; + exports[`.toEqual() {pass: false} expect(false).toEqual(ObjectContaining {"a": 2}) 1`] = ` "expect(received).toEqual(expected) diff --git a/packages/expect/src/__tests__/matchers.test.js b/packages/expect/src/__tests__/matchers.test.js index 2e9c8a300e2b..2b2d142f85f5 100644 --- a/packages/expect/src/__tests__/matchers.test.js +++ b/packages/expect/src/__tests__/matchers.test.js @@ -247,12 +247,23 @@ describe('.toEqual()', () => { [new Map(), new Set()], [new Set([1, 2]), new Set()], [new Set([1, 2]), new Set([1, 2, 3])], + [new Set([[1], [2]]), new Set([[1], [2], [3]])], + [new Set([[1], [2]]), new Set([[1], [2], [2]])], + [ + new Set([new Set([1]), new Set([2])]), + new Set([new Set([1]), new Set([3])]), + ], [Immutable.Set([1, 2]), Immutable.Set()], [Immutable.Set([1, 2]), Immutable.Set([1, 2, 3])], [Immutable.OrderedSet([1, 2]), Immutable.OrderedSet([2, 1])], [new Map([[1, 'one'], [2, 'two']]), new Map([[1, 'one']])], [new Map([['a', 0]]), new Map([['b', 0]])], [new Map([['v', 1]]), new Map([['v', 2]])], + [new Map([[['v'], 1]]), new Map([[['v'], 2]])], + [ + new Map([[[1], new Map([[[1], 'one']])]]), + new Map([[[1], new Map([[[1], 'two']])]]), + ], [Immutable.Map({a: 0}), Immutable.Map({b: 0})], [Immutable.Map({v: 1}), Immutable.Map({v: 2})], [ @@ -304,6 +315,13 @@ describe('.toEqual()', () => { [new Set(), new Set()], [new Set([1, 2]), new Set([1, 2])], [new Set([1, 2]), new Set([2, 1])], + [new Set([[1], [2]]), new Set([[2], [1]])], + [ + new Set([new Set([[1]]), new Set([[2]])]), + new Set([new Set([[2]]), new Set([[1]])]), + ], + [new Set([[1], [2], [3], [3]]), new Set([[3], [3], [2], [1]])], + [new Set([{a: 1}, {b: 2}]), new Set([{b: 2}, {a: 1}])], [Immutable.Set(), Immutable.Set()], [Immutable.Set([1, 2]), Immutable.Set([1, 2])], [Immutable.Set([1, 2]), Immutable.Set([2, 1])], @@ -312,6 +330,26 @@ describe('.toEqual()', () => { [new Map(), new Map()], [new Map([[1, 'one'], [2, 'two']]), new Map([[1, 'one'], [2, 'two']])], [new Map([[1, 'one'], [2, 'two']]), new Map([[2, 'two'], [1, 'one']])], + [ + new Map([[[1], 'one'], [[2], 'two'], [[3], 'three'], [[3], 'four']]), + new Map([[[3], 'three'], [[3], 'four'], [[2], 'two'], [[1], 'one']]), + ], + [ + new Map([[[1], new Map([[[1], 'one']])], [[2], new Map([[[2], 'two']])]]), + new Map([[[2], new Map([[[2], 'two']])], [[1], new Map([[[1], 'one']])]]), + ], + [ + new Map([[[1], 'one'], [[2], 'two']]), + new Map([[[2], 'two'], [[1], 'one']]), + ], + [ + new Map([[{a: 1}, 'one'], [{b: 2}, 'two']]), + new Map([[{b: 2}, 'two'], [{a: 1}, 'one']]), + ], + [ + new Map([[1, ['one']], [2, ['two']]]), + new Map([[2, ['two']], [1, ['one']]]), + ], [Immutable.Map(), Immutable.Map()], [ Immutable.Map() diff --git a/packages/expect/src/utils.js b/packages/expect/src/utils.js index a6cc277952e6..0d8c38cfa787 100644 --- a/packages/expect/src/utils.js +++ b/packages/expect/src/utils.js @@ -128,8 +128,18 @@ export const iterableEquality = (a: any, b: any) => { let allFound = true; for (const aValue of a) { if (!b.has(aValue)) { - allFound = false; - break; + let has = false; + for (const bValue of b) { + const isEqual = equals(aValue, bValue, [iterableEquality]); + if (isEqual === true) { + has = true; + } + } + + if (has === false) { + allFound = false; + break; + } } } if (allFound) { @@ -142,8 +152,24 @@ export const iterableEquality = (a: any, b: any) => { !b.has(aEntry[0]) || !equals(aEntry[1], b.get(aEntry[0]), [iterableEquality]) ) { - allFound = false; - break; + let has = false; + for (const bEntry of b) { + const matchedKey = equals(aEntry[0], bEntry[0], [iterableEquality]); + + let matchedValue = false; + if (matchedKey === true) { + matchedValue = equals(aEntry[1], bEntry[1], [iterableEquality]); + } + + if (matchedValue === true) { + has = true; + } + } + + if (has === false) { + allFound = false; + break; + } } } if (allFound) {