1 /** 2 * Environment for Jasmine 3 * 4 * @constructor 5 */ 6 jasmine.Env = function() { 7 this.currentSpec = null; 8 this.currentSuite = null; 9 this.currentRunner_ = new jasmine.Runner(this); 10 11 this.reporter = new jasmine.MultiReporter(); 12 13 this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; 14 this.lastUpdate = 0; 15 this.specFilter = function() { 16 return true; 17 }; 18 19 this.nextSpecId_ = 0; 20 this.nextSuiteId_ = 0; 21 this.equalityTesters_ = []; 22 23 // wrap matchers 24 this.matchersClass = function() { 25 jasmine.Matchers.apply(this, arguments); 26 }; 27 jasmine.util.inherit(this.matchersClass, jasmine.Matchers); 28 29 for (var methodName in jasmine.Matchers.prototype) { 30 var orig = jasmine.Matchers.prototype[methodName]; 31 this.matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); 32 } 33 }; 34 35 36 jasmine.Env.prototype.setTimeout = jasmine.setTimeout; 37 jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; 38 jasmine.Env.prototype.setInterval = jasmine.setInterval; 39 jasmine.Env.prototype.clearInterval = jasmine.clearInterval; 40 41 /** 42 * @returns an object containing jasmine version build info, if set. 43 */ 44 jasmine.Env.prototype.version = function () { 45 if (jasmine.version_) { 46 return jasmine.version_; 47 } else { 48 throw new Error('Version not set'); 49 } 50 }; 51 52 /** 53 * @returns a sequential integer starting at 0 54 */ 55 jasmine.Env.prototype.nextSpecId = function () { 56 return this.nextSpecId_++; 57 }; 58 59 /** 60 * @returns a sequential integer starting at 0 61 */ 62 jasmine.Env.prototype.nextSuiteId = function () { 63 return this.nextSuiteId_++; 64 }; 65 66 /** 67 * Register a reporter to receive status updates from Jasmine. 68 * @param {jasmine.Reporter} reporter An object which will receive status updates. 69 */ 70 jasmine.Env.prototype.addReporter = function(reporter) { 71 this.reporter.addReporter(reporter); 72 }; 73 74 jasmine.Env.prototype.execute = function() { 75 this.currentRunner_.execute(); 76 }; 77 78 jasmine.Env.prototype.describe = function(description, specDefinitions) { 79 var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); 80 81 var parentSuite = this.currentSuite; 82 if (parentSuite) { 83 parentSuite.add(suite); 84 } else { 85 this.currentRunner_.add(suite); 86 } 87 88 this.currentSuite = suite; 89 90 specDefinitions.call(suite); 91 92 this.currentSuite = parentSuite; 93 94 return suite; 95 }; 96 97 jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { 98 if (this.currentSuite) { 99 this.currentSuite.beforeEach(beforeEachFunction); 100 } else { 101 this.currentRunner_.beforeEach(beforeEachFunction); 102 } 103 }; 104 105 jasmine.Env.prototype.currentRunner = function () { 106 return this.currentRunner_; 107 }; 108 109 jasmine.Env.prototype.afterEach = function(afterEachFunction) { 110 if (this.currentSuite) { 111 this.currentSuite.afterEach(afterEachFunction); 112 } else { 113 this.currentRunner_.afterEach(afterEachFunction); 114 } 115 116 }; 117 118 jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { 119 return { 120 execute: function() { 121 } 122 }; 123 }; 124 125 jasmine.Env.prototype.it = function(description, func) { 126 var spec = new jasmine.Spec(this, this.currentSuite, description); 127 this.currentSuite.add(spec); 128 this.currentSpec = spec; 129 130 if (func) { 131 spec.runs(func); 132 } 133 134 return spec; 135 }; 136 137 jasmine.Env.prototype.xit = function(desc, func) { 138 return { 139 id: this.nextSpecId(), 140 runs: function() { 141 } 142 }; 143 }; 144 145 jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { 146 if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { 147 return true; 148 } 149 150 a.__Jasmine_been_here_before__ = b; 151 b.__Jasmine_been_here_before__ = a; 152 153 var hasKey = function(obj, keyName) { 154 return obj != null && obj[keyName] !== jasmine.undefined; 155 }; 156 157 for (var property in b) { 158 if (!hasKey(a, property) && hasKey(b, property)) { 159 mismatchKeys.push("expected has key '" + property + "', but missing from actual."); 160 } 161 } 162 for (property in a) { 163 if (!hasKey(b, property) && hasKey(a, property)) { 164 mismatchKeys.push("expected missing key '" + property + "', but present in actual."); 165 } 166 } 167 for (property in b) { 168 if (property == '__Jasmine_been_here_before__') continue; 169 if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { 170 mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); 171 } 172 } 173 174 if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { 175 mismatchValues.push("arrays were not the same length"); 176 } 177 178 delete a.__Jasmine_been_here_before__; 179 delete b.__Jasmine_been_here_before__; 180 return (mismatchKeys.length == 0 && mismatchValues.length == 0); 181 }; 182 183 jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { 184 mismatchKeys = mismatchKeys || []; 185 mismatchValues = mismatchValues || []; 186 187 if (a === b) return true; 188 189 if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { 190 return (a == jasmine.undefined && b == jasmine.undefined); 191 } 192 193 if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { 194 return a === b; 195 } 196 197 if (a instanceof Date && b instanceof Date) { 198 return a.getTime() == b.getTime(); 199 } 200 201 if (a instanceof jasmine.Matchers.Any) { 202 return a.matches(b); 203 } 204 205 if (b instanceof jasmine.Matchers.Any) { 206 return b.matches(a); 207 } 208 209 if (typeof a === "object" && typeof b === "object") { 210 return this.compareObjects_(a, b, mismatchKeys, mismatchValues); 211 } 212 213 for (var i = 0; i < this.equalityTesters_.length; i++) { 214 var equalityTester = this.equalityTesters_[i]; 215 var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); 216 if (result !== jasmine.undefined) return result; 217 } 218 219 //Straight check 220 return (a === b); 221 }; 222 223 jasmine.Env.prototype.contains_ = function(haystack, needle) { 224 if (jasmine.isArray_(haystack)) { 225 for (var i = 0; i < haystack.length; i++) { 226 if (this.equals_(haystack[i], needle)) return true; 227 } 228 return false; 229 } 230 return haystack.indexOf(needle) >= 0; 231 }; 232 233 jasmine.Env.prototype.addEqualityTester = function(equalityTester) { 234 this.equalityTesters_.push(equalityTester); 235 }; 236