diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index b08998f0..34627628 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -3699,11 +3699,23 @@ getJasmineRequireObj().pp = function(j$) { }; PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } - fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && - obj.__lookupGetter__(property) !== null) : false); + var objKeys = keys(obj, j$.isArray_(obj)); + var isGetter = function isGetter(prop) {}; + + if (obj.__lookupGetter__) { + isGetter = function isGetter(prop) { + var getter = obj.__lookupGetter__(prop); + return !j$.util.isUndefined(getter) && getter !== null; + }; + } + var length = Math.min(objKeys.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + for (var i = 0; i < length; i++) { + var property = objKeys[i]; + fn(property, isGetter(property)); + } + + return objKeys.length > length; }; PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; @@ -3716,7 +3728,7 @@ getJasmineRequireObj().pp = function(j$) { function StringPrettyPrinter() { PrettyPrinter.call(this); - this.string = ''; + this.stringParts = []; } j$.util.inherit(StringPrettyPrinter, PrettyPrinter); @@ -3748,11 +3760,7 @@ getJasmineRequireObj().pp = function(j$) { var self = this; var first = array.length === 0; - this.iterateObject(array, function(property, isGetter) { - if (property.match(/^\d+$/)) { - return; - } - + var truncated = this.iterateObject(array, function(property, isGetter) { if (first) { first = false; } else { @@ -3762,6 +3770,8 @@ getJasmineRequireObj().pp = function(j$) { self.formatProperty(array, property, isGetter); }); + if (truncated) { this.append(', ...'); } + this.append(' ]'); }; @@ -3823,7 +3833,7 @@ getJasmineRequireObj().pp = function(j$) { this.append('({ '); var first = true; - this.iterateObject(obj, function(property, isGetter) { + var truncated = this.iterateObject(obj, function(property, isGetter) { if (first) { first = false; } else { @@ -3833,6 +3843,8 @@ getJasmineRequireObj().pp = function(j$) { self.formatProperty(obj, property, isGetter); }); + if (truncated) { this.append(', ...'); } + this.append(' })'); }; @@ -3847,13 +3859,42 @@ getJasmineRequireObj().pp = function(j$) { }; StringPrettyPrinter.prototype.append = function(value) { - this.string += value; + this.stringParts.push(value); }; + function keys(obj, isArray) { + var allKeys = Object.keys ? Object.keys(obj) : + (function(o) { + var keys = []; + for (var key in o) { + if (j$.util.has(o, key)) { + keys.push(key); + } + } + return keys; + })(obj); + + if (!isArray) { + return allKeys; + } + + if (allKeys.length === 0) { + return allKeys; + } + + var extraKeys = []; + for (var i = 0; i < allKeys.length; i++) { + if (!/^[0-9]+$/.test(allKeys[i])) { + extraKeys.push(allKeys[i]); + } + } + + return extraKeys; + } return function(value) { var stringPrettyPrinter = new StringPrettyPrinter(); stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; + return stringPrettyPrinter.stringParts.join(''); }; }; diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index 980ae736..905c27ec 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -119,6 +119,18 @@ describe("jasmineUnderTest.pp", function () { }, bar: [1, 2, 3]})).toEqual("Object({ foo: Function, bar: [ 1, 2, 3 ] })"); }); + it("should truncate objects with too many keys", function () { + var originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH; + var long = {a: 1, b: 2, c: 3}; + + try { + jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2; + expect(jasmineUnderTest.pp(long)).toEqual("Object({ a: 1, b: 2, ... })"); + } finally { + jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength; + } + }); + it("should print 'null' as the constructor of an object with its own constructor property", function() { expect(jasmineUnderTest.pp({constructor: function() {}})).toContain("null({"); expect(jasmineUnderTest.pp({constructor: 'foo'})).toContain("null({"); diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index 0a6da994..bd4d8360 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -61,11 +61,23 @@ getJasmineRequireObj().pp = function(j$) { }; PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } - fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && - obj.__lookupGetter__(property) !== null) : false); + var objKeys = keys(obj, j$.isArray_(obj)); + var isGetter = function isGetter(prop) {}; + + if (obj.__lookupGetter__) { + isGetter = function isGetter(prop) { + var getter = obj.__lookupGetter__(prop); + return !j$.util.isUndefined(getter) && getter !== null; + }; + } + var length = Math.min(objKeys.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + for (var i = 0; i < length; i++) { + var property = objKeys[i]; + fn(property, isGetter(property)); + } + + return objKeys.length > length; }; PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; @@ -78,7 +90,7 @@ getJasmineRequireObj().pp = function(j$) { function StringPrettyPrinter() { PrettyPrinter.call(this); - this.string = ''; + this.stringParts = []; } j$.util.inherit(StringPrettyPrinter, PrettyPrinter); @@ -110,11 +122,7 @@ getJasmineRequireObj().pp = function(j$) { var self = this; var first = array.length === 0; - this.iterateObject(array, function(property, isGetter) { - if (property.match(/^\d+$/)) { - return; - } - + var truncated = this.iterateObject(array, function(property, isGetter) { if (first) { first = false; } else { @@ -124,6 +132,8 @@ getJasmineRequireObj().pp = function(j$) { self.formatProperty(array, property, isGetter); }); + if (truncated) { this.append(', ...'); } + this.append(' ]'); }; @@ -185,7 +195,7 @@ getJasmineRequireObj().pp = function(j$) { this.append('({ '); var first = true; - this.iterateObject(obj, function(property, isGetter) { + var truncated = this.iterateObject(obj, function(property, isGetter) { if (first) { first = false; } else { @@ -195,6 +205,8 @@ getJasmineRequireObj().pp = function(j$) { self.formatProperty(obj, property, isGetter); }); + if (truncated) { this.append(', ...'); } + this.append(' })'); }; @@ -209,12 +221,41 @@ getJasmineRequireObj().pp = function(j$) { }; StringPrettyPrinter.prototype.append = function(value) { - this.string += value; + this.stringParts.push(value); }; + function keys(obj, isArray) { + var allKeys = Object.keys ? Object.keys(obj) : + (function(o) { + var keys = []; + for (var key in o) { + if (j$.util.has(o, key)) { + keys.push(key); + } + } + return keys; + })(obj); + + if (!isArray) { + return allKeys; + } + + if (allKeys.length === 0) { + return allKeys; + } + + var extraKeys = []; + for (var i = 0; i < allKeys.length; i++) { + if (!/^[0-9]+$/.test(allKeys[i])) { + extraKeys.push(allKeys[i]); + } + } + + return extraKeys; + } return function(value) { var stringPrettyPrinter = new StringPrettyPrinter(); stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; + return stringPrettyPrinter.stringParts.join(''); }; }; diff --git a/src/core/base.js b/src/core/base.js index bbd81170..949f9f29 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -11,6 +11,7 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { j$.MAX_PRETTY_PRINT_DEPTH = 40; /** * Maximum number of array elements to display when pretty printing objects. + * This will also limit the number of keys and values displayed for an object. * Elements past this number will be ellipised. * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH */