From 486a64658f17b8fca4798b3a2661b6cd6df88317 Mon Sep 17 00:00:00 2001 From: Volonterio Riccardo Date: Fri, 12 Jan 2018 12:18:35 +0100 Subject: [PATCH] Added complete support for Set also for IE11. Fixes 1355 --- spec/core/PrettyPrintSpec.js | 15 ++++-- spec/core/matchers/matchersUtilSpec.js | 75 +++++++++++++++++++++----- spec/core/matchers/toEqualSpec.js | 56 ++++++++++++------- spec/helpers/checkForSet.js | 26 +++++++-- src/core/PrettyPrinter.js | 15 ++++-- src/core/base.js | 4 ++ src/core/matchers/matchersUtil.js | 41 +++++++------- 7 files changed, 169 insertions(+), 63 deletions(-) diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index 2edb8894..32b9d99b 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -16,8 +16,11 @@ describe("jasmineUnderTest.pp", function () { describe('stringify sets', function() { it("should stringify sets properly", function() { - jasmine.getEnv().requireFunctioningSets(); - expect(jasmineUnderTest.pp(new Set([1, 2]))).toEqual("Set( 1, 2 )"); + jasmine.getEnv().requireFunctioningSets(); + var set = new Set(); + set.add(1); + set.add(2); + expect(jasmineUnderTest.pp(set)).toEqual("Set( 1, 2 )"); }); it("should truncate sets with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() { @@ -25,8 +28,12 @@ describe("jasmineUnderTest.pp", function () { var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH; try { - jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2; - expect(jasmineUnderTest.pp(new Set(["a", "b", "c"]))).toEqual("Set( 'a', 'b', ... )"); + jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2; + var set = new Set(); + set.add('a'); + set.add('b'); + set.add('c'); + expect(jasmineUnderTest.pp(set)).toEqual("Set( 'a', 'b', ... )"); } finally { jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize; } diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index b47f4772..5a40e665 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -396,45 +396,94 @@ describe("matchersUtil", function() { it("passes when comparing identical sets", function() { jasmine.getEnv().requireFunctioningSets(); - var setA = new Set([6, 5]); + + var setA = new Set(); + setA.add(6); + setA.add(5); var setB = new Set(); setB.add(6); setB.add(5); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(true); }); it("passes when comparing identical sets with different insertion order and simple elements", function() { jasmine.getEnv().requireFunctioningSets(); - var setA = new Set([3, 6]); - var setB = new Set([6, 3]); + + var setA = new Set(); + setA.add(3); + setA.add(6); + var setB = new Set(); + setB.add(6); + setB.add(3); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(true); }); it("passes when comparing identical sets with different insertion order and complex elements 1", function() { - jasmine.getEnv().requireFunctioningMaps(); - var setA = new Set([new Set([['a', 3], [6, 1]]), new Set([['y', 3], [6, 1]])]); - var setB = new Set([new Set([[6, 1], ['a', 3]]), new Set([[6, 1], ['y', 3]])]); + jasmine.getEnv().requireFunctioningSets(); + + var setA1 = new Set(); + setA1.add(['a',3]); + setA1.add([6,1]); + var setA2 = new Set(); + setA1.add(['y',3]); + setA1.add([6,1]); + var setA = new Set(); + setA.add(setA1); + setA.add(setA2); + + + var setB1 = new Set(); + setB1.add([6,1]); + setB1.add(['a',3]); + var setB2 = new Set(); + setB1.add([6,1]); + setB1.add(['y',3]); + var setB = new Set(); + setB.add(setB1); + setB.add(setB2); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(true); }); it("passes when comparing identical sets with different insertion order and complex elements 2", function() { - jasmine.getEnv().requireFunctioningMaps(); - var setA = new Set([[[1,2], [3,4]], [[5,6], [7,8]]]); - var setB = new Set([[[5,6], [7,8]], [[1,2], [3,4]]]); + jasmine.getEnv().requireFunctioningSets(); + + var setA = new Set(); + setA.add([[1,2], [3,4]]); + setA.add([[5,6], [7,8]]); + var setB = new Set(); + setB.add([[5,6], [7,8]]); + setB.add([[1,2], [3,4]]); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(true); }); it("fails for sets with different elements", function() { jasmine.getEnv().requireFunctioningSets(); - var setA = new Set([6, 3, 5]); - var setB = new Set([6, 4, 5]); + var setA = new Set(); + setA.add(6); + setA.add(3); + setA.add(5); + var setB = new Set(); + setB.add(6); + setB.add(4); + setB.add(5); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(false); }); it("fails for sets of different size", function() { jasmine.getEnv().requireFunctioningSets(); - var setA = new Set([6, 3]); - var setB = new Set([6, 4, 5]); + var setA = new Set(); + setA.add(6); + setA.add(3); + var setB = new Set(); + setB.add(6); + setB.add(4); + setB.add(5); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(false); }); diff --git a/spec/core/matchers/toEqualSpec.js b/spec/core/matchers/toEqualSpec.js index 0dc50dd8..d186025b 100644 --- a/spec/core/matchers/toEqualSpec.js +++ b/spec/core/matchers/toEqualSpec.js @@ -374,9 +374,11 @@ describe("toEqual", function() { it("reports mismatches between Sets", function() { jasmine.getEnv().requireFunctioningSets(); - var actual = new Set([1]), - expected = new Set([2]), - message = 'Expected Set( 1 ) to equal Set( 2 ).'; + var actual = new Set(); + actual.add(1); + var expected = new Set(); + expected.add(2); + var message = 'Expected Set( 1 ) to equal Set( 2 ).'; expect(compareEquals(actual, expected).message).toEqual(message); }); @@ -384,9 +386,11 @@ describe("toEqual", function() { it("reports deep mismatches within Sets", function() { jasmine.getEnv().requireFunctioningSets(); - var actual = new Set([{x: 1}]), - expected = new Set([{x: 2}]), - message = 'Expected Set( Object({ x: 1 }) ) to equal Set( Object({ x: 2 }) ).'; + var actual = new Set(); + actual.add({x: 1}); + var expected = new Set(); + expected.add({x: 2}); + var message = 'Expected Set( Object({ x: 1 }) ) to equal Set( Object({ x: 2 }) ).'; expect(compareEquals(actual, expected).message).toEqual(message); }); @@ -394,9 +398,14 @@ describe("toEqual", function() { it("reports mismatches between Sets nested in objects", function() { jasmine.getEnv().requireFunctioningSets(); - var actual = {sets: [new Set([1])]}, - expected = {sets: [new Set([2])]}, - message = "Expected $.sets[0] = Set( 1 ) to equal Set( 2 )."; + var actualSet = new Set(); + actualSet.add(1); + var expectedSet = new Set(); + expectedSet.add(2); + + var actual = { sets: [actualSet] }; + var expected = { sets: [expectedSet] }; + var message = "Expected $.sets[0] = Set( 1 ) to equal Set( 2 )."; expect(compareEquals(actual, expected).message).toEqual(message); }); @@ -404,9 +413,12 @@ describe("toEqual", function() { it("reports mismatches between Sets of different lengths", function() { jasmine.getEnv().requireFunctioningSets(); - var actual = new Set([1, 2]), - expected = new Set([2]), - message = 'Expected Set( 1, 2 ) to equal Set( 2 ).'; + var actual = new Set(); + actual.add(1); + actual.add(2); + var expected = new Set(); + expected.add(2); + var message = 'Expected Set( 1, 2 ) to equal Set( 2 ).'; expect(compareEquals(actual, expected).message).toEqual(message); }); @@ -415,9 +427,13 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningSets(); // Use 'duplicate' object in actual so sizes match - var actual = new Set([{x: 1}, {x: 1}]), - expected = new Set([{x: 1}, {x: 2}]), - message = 'Expected Set( Object({ x: 1 }), Object({ x: 1 }) ) to equal Set( Object({ x: 1 }), Object({ x: 2 }) ).'; + var actual = new Set(); + actual.add({x: 1}); + actual.add({x: 1}); + var expected = new Set(); + expected.add({x: 1}); + expected.add({x: 2}); + var message = 'Expected Set( Object({ x: 1 }), Object({ x: 1 }) ) to equal Set( Object({ x: 1 }), Object({ x: 2 }) ).'; expect(compareEquals(actual, expected).message).toEqual(message); }); @@ -426,9 +442,13 @@ describe("toEqual", function() { jasmine.getEnv().requireFunctioningSets(); // Use 'duplicate' object in expected so sizes match - var actual = new Set([{x: 1}, {x: 2}]), - expected = new Set([{x: 1}, {x: 1}]), - message = 'Expected Set( Object({ x: 1 }), Object({ x: 2 }) ) to equal Set( Object({ x: 1 }), Object({ x: 1 }) ).'; + var actual = new Set(); + actual.add({x: 1}); + actual.add({x: 2}); + var expected = new Set(); + expected.add({x: 1}); + expected.add({x: 1}); + var message = 'Expected Set( Object({ x: 1 }), Object({ x: 2 }) ) to equal Set( Object({ x: 1 }), Object({ x: 1 }) ).'; expect(compareEquals(actual, expected).message).toEqual(message); }); diff --git a/spec/helpers/checkForSet.js b/spec/helpers/checkForSet.js index eb31aed7..4ba13edd 100644 --- a/spec/helpers/checkForSet.js +++ b/spec/helpers/checkForSet.js @@ -3,9 +3,29 @@ if (typeof Set === 'undefined') { return false; } try { - var s = new Set([4]); - if (s.size !== 1) { return false; } - if (s.values().next().value !== 4) { return false; } + var s = new Set(); + s.add(1); + s.add(2); + + if (s.size !== 2) { return false; } + if (s.has(1) !== true) { return false; } + + var iterations = 0; + var isForEachWorking = true; + s.forEach(function(value, key, set) { + isForEachWorking = isForEachWorking && set === s; + + if (iterations===0) { + isForEachWorking = isForEachWorking && (key===value) && value===1; + } else if (iterations===1) { + isForEachWorking = isForEachWorking && (key===value) && value===2; + } + + iterations++; + }); + if (iterations !== 2) { return false; } + if (isForEachWorking !== true) { return false; } + return true; } catch(e) { return false; diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index 5f2ffbe4..ab680130 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -38,7 +38,7 @@ getJasmineRequireObj().pp = function(j$) { this.emitScalar('HTMLNode'); } else if (value instanceof Date) { this.emitScalar('Date(' + value + ')'); - } else if (j$.getType_(value) == '[object Set]') { + } else if (j$.isSet(value)) { this.emitSet(value); } else if (j$.isMap(value)) { this.emitMap(value); @@ -137,13 +137,18 @@ getJasmineRequireObj().pp = function(j$) { } this.append('Set( '); var size = Math.min(set.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); - var iter = set.values(); - for (var i = 0; i < size; i++) { + var i = 0; + set.forEach( function( value, key ) { + if (i >= size) { + return; + } if (i > 0) { this.append(', '); } - this.format(iter.next().value); - } + this.format(value); + + i++; + }, this ); if (set.size > size){ this.append(', ...'); } diff --git a/src/core/base.js b/src/core/base.js index 13d1504b..9781fa20 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -95,6 +95,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { j$.isMap = function(obj) { return typeof jasmineGlobal.Map !== 'undefined' && obj.constructor === jasmineGlobal.Map; + }; + + j$.isSet = function(obj) { + return typeof jasmineGlobal.Set !== 'undefined' && obj.constructor === jasmineGlobal.Set; }; j$.isPromise = function(obj) { diff --git a/src/core/matchers/matchersUtil.js b/src/core/matchers/matchersUtil.js index 7b9cb4b3..c91609f4 100644 --- a/src/core/matchers/matchersUtil.js +++ b/src/core/matchers/matchersUtil.js @@ -300,48 +300,49 @@ getJasmineRequireObj().matchersUtil = function(j$) { diffBuilder.record(a, b); return false; } - } else if (className == '[object Set]') { + } else if (j$.isSet(a) && j$.isSet(b)) { if (a.size != b.size) { diffBuilder.record(a, b); return false; } + var valuesA = []; + a.forEach( function( valueA ) { + valuesA.push( valueA ); + }); + var valuesB = []; + b.forEach( function( valueB ) { + valuesB.push( valueB ); + }); + // For both sets, check they are all contained in the other set - var setPairs = [[a, b], [b, a]]; + var setPairs = [[valuesA, valuesB], [valuesB, valuesA]]; var stackPairs = [[aStack, bStack], [bStack, aStack]]; - var baseIter, baseValueIt, baseValue, baseStack; - var otherSet, otherIter, otherValueIt, otherValue, otherStack; + var baseIter, baseValue, baseStack; + var otherSet, otherIter, otherValue, otherStack; var found; var prevStackSize; for (i = 0; result && i < setPairs.length; i++) { - baseIter = setPairs[i][0].values(); - otherSet = setPairs[i][1]; + baseIter = setPairs[i][0]; + otherIter = setPairs[i][1]; baseStack = stackPairs[i][0]; otherStack = stackPairs[i][1]; // For each value in the base set... - baseValueIt = baseIter.next(); - while (result && !baseValueIt.done) { - baseValue = baseValueIt.value; + for (var k = 0; result && k < baseIter.length; k++) { + baseValue = baseIter[k]; + found = false; // ... test that it is present in the other set - // Optimisation: start looking for value by object identity - found = otherSet.has(baseValue); - if (!found) { - otherIter = otherSet.values(); - otherValueIt = otherIter.next(); - } - // If not found, compare by value equality - while (!found && !otherValueIt.done) { - otherValue = otherValueIt.value; + for (var l = 0; !found && l < otherIter.length; l++) { + otherValue = otherIter[l]; prevStackSize = baseStack.length; + // compare by value equality found = eq(baseValue, otherValue, baseStack, otherStack, customTesters, j$.NullDiffBuilder()); if (!found && prevStackSize !== baseStack.length) { baseStack.splice(prevStackSize); otherStack.splice(prevStackSize); } - otherValueIt = otherIter.next(); } result = result && found; - baseValueIt = baseIter.next(); } }