Currently, jasmine's pretty printer traverses objects to 40 levels of nesting. If an object is more deeply nested than that, an exception is thrown. I find that after a few levels of nesting, the output becomes difficult to read. The process of serializing such deep objects also sometimes crashes the browser or causes a 'slow script' warning. This commit exposes a 'MAX_PRETTY_PRINT_DEPTH' option. It also causes the pretty printer to skip over parts of an object that are nested to deeply by simply printing out 'Object' or 'Array', rather than throwing an exception.
131 lines
3.7 KiB
JavaScript
131 lines
3.7 KiB
JavaScript
/**
|
|
* Base class for pretty printing for expectation results.
|
|
*/
|
|
jasmine.PrettyPrinter = function() {
|
|
this.ppNestLevel_ = 0;
|
|
};
|
|
|
|
/**
|
|
* Formats a value in a nice, human-readable string.
|
|
*
|
|
* @param value
|
|
*/
|
|
jasmine.PrettyPrinter.prototype.format = function(value) {
|
|
this.ppNestLevel_++;
|
|
try {
|
|
if (value === jasmine.undefined) {
|
|
this.emitScalar('undefined');
|
|
} else if (value === null) {
|
|
this.emitScalar('null');
|
|
} else if (value === jasmine.getGlobal()) {
|
|
this.emitScalar('<global>');
|
|
} else if (value.jasmineToString) {
|
|
this.emitScalar(value.jasmineToString());
|
|
} else if (typeof value === 'string') {
|
|
this.emitString(value);
|
|
} else if (jasmine.isSpy(value)) {
|
|
this.emitScalar("spy on " + value.identity);
|
|
} else if (value instanceof RegExp) {
|
|
this.emitScalar(value.toString());
|
|
} else if (typeof value === 'function') {
|
|
this.emitScalar('Function');
|
|
} else if (typeof value.nodeType === 'number') {
|
|
this.emitScalar('HTMLNode');
|
|
} else if (value instanceof Date) {
|
|
this.emitScalar('Date(' + value + ')');
|
|
} else if (value.__Jasmine_been_here_before__) {
|
|
this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
|
|
} else if (jasmine.isArray_(value) || typeof value == 'object') {
|
|
value.__Jasmine_been_here_before__ = true;
|
|
if (jasmine.isArray_(value)) {
|
|
this.emitArray(value);
|
|
} else {
|
|
this.emitObject(value);
|
|
}
|
|
delete value.__Jasmine_been_here_before__;
|
|
} else {
|
|
this.emitScalar(value.toString());
|
|
}
|
|
} finally {
|
|
this.ppNestLevel_--;
|
|
}
|
|
};
|
|
|
|
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
|
|
for (var property in obj) {
|
|
if (!obj.hasOwnProperty(property)) continue;
|
|
if (property == '__Jasmine_been_here_before__') continue;
|
|
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
|
|
obj.__lookupGetter__(property) !== null) : false);
|
|
}
|
|
};
|
|
|
|
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
|
|
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
|
|
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
|
|
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
|
|
|
|
jasmine.StringPrettyPrinter = function() {
|
|
jasmine.PrettyPrinter.call(this);
|
|
|
|
this.string = '';
|
|
};
|
|
jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
|
|
|
|
jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
|
|
this.append(value);
|
|
};
|
|
|
|
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
|
|
this.append("'" + value + "'");
|
|
};
|
|
|
|
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
|
|
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
|
|
this.append("Array");
|
|
return;
|
|
}
|
|
|
|
this.append('[ ');
|
|
for (var i = 0; i < array.length; i++) {
|
|
if (i > 0) {
|
|
this.append(', ');
|
|
}
|
|
this.format(array[i]);
|
|
}
|
|
this.append(' ]');
|
|
};
|
|
|
|
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
|
|
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
|
|
this.append("Object");
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
this.append('{ ');
|
|
var first = true;
|
|
|
|
this.iterateObject(obj, function(property, isGetter) {
|
|
if (first) {
|
|
first = false;
|
|
} else {
|
|
self.append(', ');
|
|
}
|
|
|
|
self.append(property);
|
|
self.append(' : ');
|
|
if (isGetter) {
|
|
self.append('<getter>');
|
|
} else {
|
|
self.format(obj[property]);
|
|
}
|
|
});
|
|
|
|
this.append(' }');
|
|
};
|
|
|
|
jasmine.StringPrettyPrinter.prototype.append = function(value) {
|
|
this.string += value;
|
|
};
|