-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for #6138: toEqual deep compare set values and map keys #6150
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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]])], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above it might be worth testing against a Map of Maps [
new Map([[[1], new Map([[[1], 'one']])]]),
new Map([[[1], new Map([[[1], 'two']])]]),
] |
||
[ | ||
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() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the look of this 😄 I know the current approach is to use the How about something like: ...
} else if (isA('Set', a) || isImmutableUnorderedSet(a)) {
const arrayA = [...a];
return [...b].every(item => a.has(item) || contains(arrayA, item));
} else if (isA('Map', a) || isImmutableUnorderedKeyed(a)) {
const arrayA = [...a];
return [...b].every(
([name, item]) =>
(a.has(name) && equals(item, a.get(name), [iterableEquality])) ||
contains(arrayA, [name, item]),
);
} With a contains function of: const contains = (list, value) => {
return list.findIndex(item => equals(item, value, [iterableEquality])) > -1;
}; I'm not sure if there is any perf difference of the two implementations. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems a bit more convoluted to me, but admittedly I am not very familiar with That being said, I don't think the From your example, the following is a bit more readable to me: const contains = (list, value) => {
const index = list.findIndex(item => equals(item, value, [iterableEquality]));
return index > -1;
};
...
} else if (isA('Set', a) || isImmutableUnorderedSet(a)) {
return [...b].every(item => {
if (a.has(item)) {
return true;
}
return contains([...a], item);
});
} else if (isA('Map', a) || isImmutableUnorderedKeyed(a)) {
return [...b].every(([name, item]) => {
if (a.has(name) && equals(item, a.get(name), [iterableEquality])) {
return true;
}
return contains([...a], [name, item]);
});
}
... I don't have a big opinion either way. Just let me know whatever changes I should make. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think its fine to leave it as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! Also, thanks for the code review. Appreciate it! |
||
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) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth adding a Set of Sets in these tests i.e.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! Added requested tests for both
Map
andSet
for.toEqual
andnot.toEqual
.