Skip to content

Commit

Permalink
Share more logic between object equality and arrays (#11061)
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz authored Apr 23, 2021
1 parent 040a50b commit a28f14a
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 55 deletions.
29 changes: 29 additions & 0 deletions packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,21 @@ Expected: <g>/abc/g</>
Received: <r>/abc/gsy</>
`;

exports[`.toEqual() {pass: false} expect([, , 1, ]).toEqual([, , 2, ]) 1`] = `
<d>expect(</><r>received</><d>).</>toEqual<d>(</><g>expected</><d>) // deep equality</>

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

<d> Array [</>
<d> undefined,</>
<d> undefined,</>
<g>- 2,</>
<r>+ 1,</>
<d> undefined,</>
<d> ]</>
`;

exports[`.toEqual() {pass: false} expect([]).toEqual([]) 1`] = `
<d>expect(</><r>received</><d>).</>toEqual<d>(</><g>expected</><d>) // deep equality</>

Expand Down Expand Up @@ -2731,6 +2746,20 @@ Expected: not <g>StringMatching /bc/</>
Received: <r>"abcd"</>
`;

exports[`.toEqual() {pass: true} expect([, , 1, , ]).not.toEqual([, , 1, undefined, ]) 1`] = `
<d>expect(</><r>received</><d>).</>not<d>.</>toEqual<d>(</><g>expected</><d>) // deep equality</>

Expected: not <g>[, , 1, undefined, ]</>
Received: <r>[, , 1, , ]</>
`;

exports[`.toEqual() {pass: true} expect([, , 1, ]).not.toEqual([, , 1, ]) 1`] = `
<d>expect(</><r>received</><d>).</>not<d>.</>toEqual<d>(</><g>expected</><d>) // deep equality</>

Expected: not <g>[, , 1, ]</>

`;

exports[`.toEqual() {pass: true} expect([1, 2, 3]).not.toEqual(ArrayContaining [2, 3]) 1`] = `
<d>expect(</><r>received</><d>).</>not<d>.</>toEqual<d>(</><g>expected</><d>) // deep equality</>

Expand Down
23 changes: 23 additions & 0 deletions packages/expect/src/__tests__/matchers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,11 @@ describe('.toStrictEqual()', () => {
expect([{a: [{a: undefined}]}]).not.toStrictEqual([{a: [{}]}]);
});

it('does not consider holes as undefined in sparse arrays', () => {
// eslint-disable-next-line no-sparse-arrays
expect([, , , 1, , ,]).not.toStrictEqual([, , , 1, undefined, ,]);
});

it('passes when comparing same type', () => {
expect({
test: new TestClassA(1, 2),
Expand Down Expand Up @@ -598,6 +603,12 @@ describe('.toEqual()', () => {
[Symbol.for('bar')]: 1,
},
],
[
// eslint-disable-next-line no-sparse-arrays
[, , 1, ,],
// eslint-disable-next-line no-sparse-arrays
[, , 2, ,],
],
[
Object.assign([], {4294967295: 1}),
Object.assign([], {4294967295: 2}), // issue 11056
Expand Down Expand Up @@ -812,6 +823,18 @@ describe('.toEqual()', () => {
[Symbol.for('bar')]: 2,
},
],
[
// eslint-disable-next-line no-sparse-arrays
[, , 1, ,],
// eslint-disable-next-line no-sparse-arrays
[, , 1, ,],
],
[
// eslint-disable-next-line no-sparse-arrays
[, , 1, , ,],
// eslint-disable-next-line no-sparse-arrays
[, , 1, undefined, ,], // same length but hole replaced by undefined
],
].forEach(([a, b]) => {
test(`{pass: true} expect(${stringify(a)}).not.toEqual(${stringify(
b,
Expand Down
72 changes: 17 additions & 55 deletions packages/expect/src/jasmineUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,30 +147,19 @@ function eq(
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
var size = 0;
// Recursively compare objects and arrays.
// Compare array lengths to determine if a deep comparison is necessary.
if (className == '[object Array]') {
size = a.length;
if (size !== b.length) {
return false;
}

while (size--) {
result = eq(a[size], b[size], aStack, bStack, customTesters, hasKey);
if (!result) {
return false;
}
}
if (className == '[object Array]' && a.length !== b.length) {
return false;
}

// Deep compare objects.
var aKeys = keys(a, className == '[object Array]', hasKey),
var aKeys = keys(a, hasKey),
key;
size = aKeys.length;
var size = aKeys.length;

// Ensure that both objects contain the same number of properties before comparing deep equality.
if (keys(b, className == '[object Array]', hasKey).length !== size) {
if (keys(b, hasKey).length !== size) {
return false;
}

Expand All @@ -193,47 +182,20 @@ function eq(
return result;
}

function keys(
obj: object,
isArray: boolean,
hasKey: (obj: object, key: string) => boolean,
) {
var allKeys = (function(o) {
var keys = [];
for (var key in o) {
if (hasKey(o, key)) {
keys.push(key);
}
function keys(obj: object, hasKey: (obj: object, key: string) => boolean) {
var keys = [];
for (var key in obj) {
if (hasKey(obj, key)) {
keys.push(key);
}
return keys.concat(
(Object.getOwnPropertySymbols(o) as Array<any>).filter(
symbol =>
(Object.getOwnPropertyDescriptor(o, symbol) as PropertyDescriptor)
.enumerable,
),
);
})(obj);

if (!isArray) {
return allKeys;
}

var extraKeys = [];
if (allKeys.length === 0) {
return allKeys;
}

for (var x = 0; x < allKeys.length; x++) {
if (
typeof allKeys[x] === 'symbol' ||
!allKeys[x].match(/^[0-9]+$/) ||
Number(allKeys[x]) >= 4294967295
) {
extraKeys.push(allKeys[x]);
}
}

return extraKeys;
return keys.concat(
(Object.getOwnPropertySymbols(obj) as Array<any>).filter(
symbol =>
(Object.getOwnPropertyDescriptor(obj, symbol) as PropertyDescriptor)
.enumerable,
),
);
}

function hasDefinedKey(obj: any, key: string) {
Expand Down

0 comments on commit a28f14a

Please sign in to comment.