Repository: jestjs/jest (TypeScript)

Issue:
isEqual() on iterable ignores other properties
<!-- Love Jest? Please consider supporting our collective: 👉  https://opencollective.com/jest/donate -->

## 🐛 Bug Report

Testing iterable objects with isEqual() ignores other properties on the iterable

## To Reproduce

```js
let next = () => ({ value: undefined, done: true });
test('iterable', () => {
    expect({ 
        [Symbol.iterator]: () => ({ next }), 
        data: ['foo'] 
    }).toEqual({ 
        [Symbol.iterator]: () => ({ next }), 
        data: [] 
    })
});
```

Same behaviour when using the iterator of data property:

```js
let data = ['foo'], data2 = [];
test('foo', () => {
    expect({ 
        [Symbol.iterator]: data[Symbol.iterator], 
        data
    }).toEqual({ 
        [Symbol.iterator]: data2[Symbol.iterator], 
        data: data2
    })
});
```
both result in
```
PASS  test/foo.test.js
  ✓ foo (6ms)
```

## Expected behavior

Other properties are evaluated when object is iterable. Like when removing the iterators from above code:

```
 FAIL  test/foo.test.js
  ✕ foo (14ms)

  ● foo

    expect(received).toEqual(expected)

    Difference:

    - Expected
    + Received

      Object {
    -   "data": Array [],
    +   "data": Array [
    +     "foo",
    +   ],
      }
```

## Link to repl or repo (highly encouraged)

https://repl.it/repls/CaringPrimarySupport

## Run `npx envinfo --preset jest`

Paste the results here:

```bash
npx: installed 1 in 1.537s

  System:
    OS: Linux 4.4 Ubuntu 16.04.1 LTS (Xenial Xerus)
    CPU: (8) x64 Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
  Binaries:
    Node: 8.9.1 - /usr/bin/node
    npm: 6.4.1 - /usr/bin/npm
  npmPackages:
    jest: ^24.7.1 => 24.7.1

```



Hints:
This reproduces for me, and it's a bug with our custom `iterableEquality`. With `Array`s, it works.
I'll send a PR 

Patch:
diff --git a/packages/expect-utils/src/utils.ts b/packages/expect-utils/src/utils.ts
--- a/packages/expect-utils/src/utils.ts
+++ b/packages/expect-utils/src/utils.ts
@@ -254,6 +254,12 @@ export const iterableEquality = (
     return false;
   }
 
+  const aEntries = Object.entries(a);
+  const bEntries = Object.entries(b);
+  if (!equals(aEntries, bEntries)) {
+    return false;
+  }
+
   // Remove the first value from the stack of traversed values.
   aStack.pop();
   bStack.pop();


Test patch:
diff --git a/packages/expect-utils/src/__tests__/utils.test.ts b/packages/expect-utils/src/__tests__/utils.test.ts
--- a/packages/expect-utils/src/__tests__/utils.test.ts
+++ b/packages/expect-utils/src/__tests__/utils.test.ts
@@ -422,6 +422,49 @@ describe('iterableEquality', () => {
     ).toBe(false);
   });
 
+  test('returns true when given iterator within equal objects', () => {
+    const a = {
+      [Symbol.iterator]: () => ({next: () => ({done: true})}),
+      a: [],
+    };
+    const b = {
+      [Symbol.iterator]: () => ({next: () => ({done: true})}),
+      a: [],
+    };
+
+    expect(iterableEquality(a, b)).toBe(true);
+  });
+
+  test('returns false when given iterator within inequal objects', () => {
+    const a = {
+      [Symbol.iterator]: () => ({next: () => ({done: true})}),
+      a: [1],
+    };
+    const b = {
+      [Symbol.iterator]: () => ({next: () => ({done: true})}),
+      a: [],
+    };
+
+    expect(iterableEquality(a, b)).toBe(false);
+  });
+
+  test('returns false when given iterator within inequal nested objects', () => {
+    const a = {
+      [Symbol.iterator]: () => ({next: () => ({done: true})}),
+      a: {
+        b: [1],
+      },
+    };
+    const b = {
+      [Symbol.iterator]: () => ({next: () => ({done: true})}),
+      a: {
+        b: [],
+      },
+    };
+
+    expect(iterableEquality(a, b)).toBe(false);
+  });
+
   test('returns true when given circular Set shape', () => {
     const a1 = new Set();
     const a2 = new Set();