1 /** 2 * Base class for pretty printing for expectation results. 3 */ 4 jasmine.PrettyPrinter = function() { 5 this.ppNestLevel_ = 0; 6 }; 7 8 /** 9 * Formats a value in a nice, human-readable string. 10 * 11 * @param value 12 * @returns {String} 13 */ 14 jasmine.PrettyPrinter.prototype.format = function(value) { 15 if (this.ppNestLevel_ > 40) { 16 // return '(jasmine.pp nested too deeply!)'; 17 throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); 18 } 19 20 this.ppNestLevel_++; 21 try { 22 if (value === undefined) { 23 this.emitScalar('undefined'); 24 } else if (value === null) { 25 this.emitScalar('null'); 26 } else if (value.navigator && value.frames && value.setTimeout) { 27 this.emitScalar('<window>'); 28 } else if (value instanceof jasmine.Matchers.Any) { 29 this.emitScalar(value.toString()); 30 } else if (typeof value === 'string') { 31 this.emitScalar("'" + value + "'"); 32 } else if (typeof value === 'function') { 33 this.emitScalar('Function'); 34 } else if (typeof value.nodeType === 'number') { 35 this.emitScalar('HTMLNode'); 36 } else if (value instanceof Date) { 37 this.emitScalar('Date(' + value + ')'); 38 } else if (value.__Jasmine_been_here_before__) { 39 this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>'); 40 } else if (jasmine.isArray_(value) || typeof value == 'object') { 41 value.__Jasmine_been_here_before__ = true; 42 if (jasmine.isArray_(value)) { 43 this.emitArray(value); 44 } else { 45 this.emitObject(value); 46 } 47 delete value.__Jasmine_been_here_before__; 48 } else { 49 this.emitScalar(value.toString()); 50 } 51 } finally { 52 this.ppNestLevel_--; 53 } 54 }; 55 56 jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { 57 for (var property in obj) { 58 if (property == '__Jasmine_been_here_before__') continue; 59 fn(property, obj.__lookupGetter__(property) != null); 60 } 61 }; 62 63 jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; 64 jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; 65 jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; 66 67 jasmine.StringPrettyPrinter = function() { 68 jasmine.PrettyPrinter.call(this); 69 70 this.string = ''; 71 }; 72 jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); 73 74 jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { 75 this.append(value); 76 }; 77 78 jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { 79 this.append('[ '); 80 for (var i = 0; i < array.length; i++) { 81 if (i > 0) { 82 this.append(', '); 83 } 84 this.format(array[i]); 85 } 86 this.append(' ]'); 87 }; 88 89 jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { 90 var self = this; 91 this.append('{ '); 92 var first = true; 93 94 this.iterateObject(obj, function(property, isGetter) { 95 if (first) { 96 first = false; 97 } else { 98 self.append(', '); 99 } 100 101 self.append(property); 102 self.append(' : '); 103 if (isGetter) { 104 self.append('<getter>'); 105 } else { 106 self.format(obj[property]); 107 } 108 }); 109 110 this.append(' }'); 111 }; 112 113 jasmine.StringPrettyPrinter.prototype.append = function(value) { 114 this.string += value; 115 }; 116