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.emitString(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__ ? (obj.__lookupGetter__(property) != null) : false); 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 jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; 67 68 jasmine.StringPrettyPrinter = function() { 69 jasmine.PrettyPrinter.call(this); 70 71 this.string = ''; 72 }; 73 jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); 74 75 jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { 76 this.append(value); 77 }; 78 79 jasmine.StringPrettyPrinter.prototype.emitString = function(value) { 80 this.append("'" + value + "'"); 81 }; 82 83 jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { 84 this.append('[ '); 85 for (var i = 0; i < array.length; i++) { 86 if (i > 0) { 87 this.append(', '); 88 } 89 this.format(array[i]); 90 } 91 this.append(' ]'); 92 }; 93 94 jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { 95 var self = this; 96 this.append('{ '); 97 var first = true; 98 99 this.iterateObject(obj, function(property, isGetter) { 100 if (first) { 101 first = false; 102 } else { 103 self.append(', '); 104 } 105 106 self.append(property); 107 self.append(' : '); 108 if (isGetter) { 109 self.append('<getter>'); 110 } else { 111 self.format(obj[property]); 112 } 113 }); 114 115 this.append(' }'); 116 }; 117 118 jasmine.StringPrettyPrinter.prototype.append = function(value) { 119 this.string += value; 120 }; 121