diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 66e56f95..712a8bf4 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1770,6 +1770,8 @@ getJasmineRequireObj().pp = function(j$) { this.emitScalar('HTMLNode'); } else if (value instanceof Date) { this.emitScalar('Date(' + value + ')'); + } else if (value.toString && value.toString() == '[object Set]') { + this.emitSet(value); } else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) { this.emitScalar(value.toString()); } else if (j$.util.arrayContains(this.seen, value)) { @@ -1799,6 +1801,7 @@ getJasmineRequireObj().pp = function(j$) { }; PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_; PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; @@ -1855,6 +1858,26 @@ getJasmineRequireObj().pp = function(j$) { this.append(' ]'); }; + StringPrettyPrinter.prototype.emitSet = function(set) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Set'); + return; + } + 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++) { + if (i > 0) { + this.append(', '); + } + this.format(iter.next().value); + } + if (set.size > size){ + this.append(', ...'); + } + this.append(' )'); + }; + StringPrettyPrinter.prototype.emitObject = function(obj) { var constructorName = obj.constructor ? j$.fnNameFor(obj.constructor) : 'null'; this.append(constructorName); @@ -2796,6 +2819,10 @@ getJasmineRequireObj().matchersUtil = function(j$) { contains: function(haystack, needle, customTesters) { customTesters = customTesters || []; + if ((Object.prototype.toString.apply(haystack) === '[object Set]')) { + return haystack.has(needle); + } + if ((Object.prototype.toString.apply(haystack) === '[object Array]') || (!!haystack && !haystack.indexOf)) { @@ -2958,6 +2985,19 @@ getJasmineRequireObj().matchersUtil = function(j$) { return false; } } + } else if (className == '[object Set]') { + if (a.size != b.size) { + return false; + } + var iterA = a.values(), iterB = b.values(); + var valA, valB; + do { + valA = iterA.next(); + valB = iterB.next(); + if (!eq(valA.value, valB.value, aStack, bStack, customTesters)) { + return false; + } + } while (!valA.done && !valB.done); } else { // Objects with different constructors are not equivalent, but `Object`s diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index a6c6057f..415839b0 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -14,6 +14,25 @@ describe("jasmineUnderTest.pp", function () { expect(jasmineUnderTest.pp(-0)).toEqual("-0"); }); + describe('stringify sets', function() { + if (typeof Set === 'undefined') { return; } + + it("should stringify sets properly", function() { + expect(jasmineUnderTest.pp(new Set([1, 2]))).toEqual("Set( 1, 2 )"); + }); + + it("should truncate sets with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", 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', ... )"); + } finally { + jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize; + } + }) + }); + describe('stringify arrays', function() { it("should stringify arrays properly", function() { expect(jasmineUnderTest.pp([1, 2])).toEqual("[ 1, 2 ]"); diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index 313c4427..950c3427 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -367,6 +367,42 @@ describe("matchersUtil", function() { expect(jasmineUnderTest.matchersUtil.equals(objA, objB)).toBe(false); }); + + it("passes when comparing two empty sets", function() { + if (typeof Set === 'undefined') { return; } + expect(jasmineUnderTest.matchersUtil.equals(new Set(), new Set())).toBe(true); + }); + + it("passes when comparing identical sets", function() { + if (typeof Set === 'undefined') { return; } + var setA = new Set([6, 5]); + var setB = new Set(); + setB.add(6); + setB.add(5); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(true); + }); + + it("fails for sets with different elements", function() { + if (typeof Set === 'undefined') { return; } + var setA = new Set([6, 3, 5]); + var setB = new Set([6, 4, 5]); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(false); + }); + + it("fails for sets of different size", function() { + if (typeof Set === 'undefined') { return; } + var setA = new Set([6, 3]); + var setB = new Set([6, 4, 5]); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(false); + }); + + it("fails for sets with different insertion order", function() { + if (typeof Set === 'undefined') { return; } + var setA = new Set([3, 6]); + var setB = new Set([6, 3]); + expect(jasmineUnderTest.matchersUtil.equals(setA, setB)).toBe(false); + }); + }); describe("contains", function() { diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index e6683fa7..4aebd96f 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -36,6 +36,8 @@ getJasmineRequireObj().pp = function(j$) { this.emitScalar('HTMLNode'); } else if (value instanceof Date) { this.emitScalar('Date(' + value + ')'); + } else if (value.toString && value.toString() == '[object Set]') { + this.emitSet(value); } else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) { this.emitScalar(value.toString()); } else if (j$.util.arrayContains(this.seen, value)) { @@ -65,6 +67,7 @@ getJasmineRequireObj().pp = function(j$) { }; PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_; PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; @@ -121,6 +124,26 @@ getJasmineRequireObj().pp = function(j$) { this.append(' ]'); }; + StringPrettyPrinter.prototype.emitSet = function(set) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Set'); + return; + } + 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++) { + if (i > 0) { + this.append(', '); + } + this.format(iter.next().value); + } + if (set.size > size){ + this.append(', ...'); + } + this.append(' )'); + }; + StringPrettyPrinter.prototype.emitObject = function(obj) { var constructorName = obj.constructor ? j$.fnNameFor(obj.constructor) : 'null'; this.append(constructorName); diff --git a/src/core/matchers/matchersUtil.js b/src/core/matchers/matchersUtil.js index f5c040e3..52dfaece 100644 --- a/src/core/matchers/matchersUtil.js +++ b/src/core/matchers/matchersUtil.js @@ -11,6 +11,10 @@ getJasmineRequireObj().matchersUtil = function(j$) { contains: function(haystack, needle, customTesters) { customTesters = customTesters || []; + if ((Object.prototype.toString.apply(haystack) === '[object Set]')) { + return haystack.has(needle); + } + if ((Object.prototype.toString.apply(haystack) === '[object Array]') || (!!haystack && !haystack.indexOf)) { @@ -173,6 +177,19 @@ getJasmineRequireObj().matchersUtil = function(j$) { return false; } } + } else if (className == '[object Set]') { + if (a.size != b.size) { + return false; + } + var iterA = a.values(), iterB = b.values(); + var valA, valB; + do { + valA = iterA.next(); + valB = iterB.next(); + if (!eq(valA.value, valB.value, aStack, bStack, customTesters)) { + return false; + } + } while (!valA.done && !valB.done); } else { // Objects with different constructors are not equivalent, but `Object`s