diff --git a/packages/jest-jasmine2/src/__tests__/iterators-test.js b/packages/jest-jasmine2/src/__tests__/iterators-test.js new file mode 100644 index 000000000000..35ce86ad1337 --- /dev/null +++ b/packages/jest-jasmine2/src/__tests__/iterators-test.js @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @emails oncall+jsinfra + */ +'use strict'; + +describe('iterators', () => { + + it('works for arrays', () => { + const mixedArray = [1, {}, []]; + + expect(mixedArray).toEqual(mixedArray); + expect([1, 2, 3]).toEqual([1, 2, 3]); + expect([1]).not.toEqual([2]); + expect([1, 2, 3]).not.toEqual([1, 2]); + expect([1, 2, 3]).not.toEqual([1, 2, 3, 4]); + }); + + it('works for custom iterables', () => { + const iterable = { + 0: 'a', + 1: 'b', + 2: 'c', + length: 3, + [Symbol.iterator]: Array.prototype[Symbol.iterator], + }; + const expectedIterable = { + 0: 'a', + 1: 'b', + 2: 'c', + length: 3, + [Symbol.iterator]: Array.prototype[Symbol.iterator], + }; + expect(iterable).toEqual(expectedIterable); + expect(iterable).not.toEqual(['a', 'b']); + expect(iterable).not.toEqual(['a', 'b', 'c']); + expect(iterable).not.toEqual(['a', 'b', 'c', 'd']); + }); + + it('works for Sets', () => { + const numbers = [1, 2, 3, 4]; + const setOfNumbers = new Set(numbers); + expect(setOfNumbers).not.toEqual(new Set()); + expect(setOfNumbers).not.toBe(numbers); + expect(setOfNumbers).not.toEqual([1, 2]); + expect(setOfNumbers).not.toEqual([1, 2, 3]); + expect(setOfNumbers).toEqual(new Set(numbers)); + + const nestedSets = new Set([new Set([1, 2])]); + expect(nestedSets).not.toEqual(new Set([new Set([1, 4])])); + expect(nestedSets).toEqual(new Set([new Set([1, 2])])); + }); + + it('works for Maps', () => { + const keyValuePairs = [['key1', 'value1'], ['key2', 'value2']]; + const smallerKeyValuePairs = [['key1', 'value1']]; + const biggerKeyValuePairs = [ + ['key1', 'value1'], ['key2', 'value2'], ['key3', 'value3'], + ]; + const map = new Map(keyValuePairs); + expect(map).not.toEqual(smallerKeyValuePairs); + expect(map).not.toEqual(new Map(smallerKeyValuePairs)); + expect(map).not.toEqual(biggerKeyValuePairs); + expect(map).not.toEqual(new Map(biggerKeyValuePairs)); + expect(map).not.toEqual(keyValuePairs); + expect(map).not.toBe(keyValuePairs); + expect(map).toEqual(new Map(keyValuePairs)); + }); + +}); diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 2241994f9393..956ae7f430ea 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -69,7 +69,46 @@ function jasmine2(config, environment, moduleLoader, testPath) { moduleLoader.requireModule(null, config.setupTestFrameworkScriptFile); } }); + + const hasIterator = object => !!(object != null && object[Symbol.iterator]); + const iterableEquality = (a, b) => { + if ( + typeof a !== 'object' || + typeof b !== 'object' || + Array.isArray(a) || + Array.isArray(b) || + !hasIterator(a) || + !hasIterator(b) + ) { + return undefined; + } + if (a.constructor !== b.constructor) { + return false; + } + const bIterator = b[Symbol.iterator](); + + for (const aValue of a) { + const nextB = bIterator.next(); + if ( + nextB.done || + !jasmine.matchersUtil.equals( + aValue, + nextB.value, + [iterableEquality] + ) + ) { + return false; + } + } + if (!bIterator.next().done) { + return false; + } + return true; + }; + env.beforeEach(() => { + jasmine.addCustomEqualityTester(iterableEquality); + jasmine.addMatchers({ toBeCalled: () => ({ compare: (actual, expected) => {