1 /** 2 * Internal representation of a Jasmine specification, or test. 3 * @private 4 * @constructs 5 * @param {jasmine.Env} env 6 * @param {jasmine.Suite} suite 7 * @param {String} description 8 */ 9 jasmine.Spec = function(env, suite, description) { 10 this.id = env.nextSpecId_++; 11 this.env = env; 12 this.suite = suite; 13 this.description = description; 14 this.queue = []; 15 this.currentTimeout = 0; 16 this.currentLatchFunction = undefined; 17 this.finished = false; 18 this.afterCallbacks = []; 19 this.spies_ = []; 20 21 this.results = new jasmine.NestedResults(); 22 this.results.description = description; 23 this.runs = this.addToQueue; 24 }; 25 26 jasmine.Spec.prototype.getFullName = function() { 27 return this.suite.getFullName() + ' ' + this.description + '.'; 28 }; 29 30 jasmine.Spec.prototype.getResults = function() { 31 return this.results; 32 }; 33 34 jasmine.Spec.prototype.addToQueue = function(func) { 35 var queuedFunction = new jasmine.QueuedFunction(this.env, func, this.currentTimeout, this.currentLatchFunction, this); 36 this.queue.push(queuedFunction); 37 38 if (this.queue.length > 1) { 39 var previousQueuedFunction = this.queue[this.queue.length - 2]; 40 previousQueuedFunction.next = function() { 41 queuedFunction.execute(); 42 }; 43 } 44 45 this.resetTimeout(); 46 return this; 47 }; 48 49 /** 50 * @private 51 * @deprecated 52 */ 53 jasmine.Spec.prototype.expects_that = function(actual) { 54 return this.expect(actual); 55 }; 56 57 /** 58 * @private 59 * @deprecated 60 */ 61 jasmine.Spec.prototype.expect = function(actual) { 62 return new jasmine.Matchers(this.env, actual, this.results); 63 }; 64 65 /** 66 * @private 67 * @deprecated 68 */ 69 jasmine.Spec.prototype.waits = function(timeout) { 70 this.currentTimeout = timeout; 71 this.currentLatchFunction = undefined; 72 return this; 73 }; 74 75 /** 76 * @private 77 * @deprecated 78 */ 79 jasmine.Spec.prototype.waitsFor = function(timeout, latchFunction, message) { 80 this.currentTimeout = timeout; 81 this.currentLatchFunction = latchFunction; 82 this.currentLatchFunction.description = message; 83 return this; 84 }; 85 86 jasmine.Spec.prototype.resetTimeout = function() { 87 this.currentTimeout = 0; 88 this.currentLatchFunction = undefined; 89 }; 90 91 jasmine.Spec.prototype.finishCallback = function() { 92 if (this.env.reporter) { 93 this.env.reporter.reportSpecResults(this); 94 } 95 }; 96 97 jasmine.Spec.prototype.finish = function() { 98 this.safeExecuteAfters(); 99 100 this.removeAllSpies(); 101 this.finishCallback(); 102 this.finished = true; 103 }; 104 105 jasmine.Spec.prototype.after = function(doAfter) { 106 this.afterCallbacks.unshift(doAfter); 107 }; 108 109 jasmine.Spec.prototype.execute = function() { 110 if (!this.env.specFilter(this)) { 111 this.results.skipped = true; 112 this.finishCallback(); 113 this.finished = true; 114 return; 115 } 116 117 this.env.currentSpec = this; 118 this.env.currentlyRunningTests = true; 119 120 this.safeExecuteBefores(); 121 122 if (this.queue[0]) { 123 this.queue[0].execute(); 124 } else { 125 this.finish(); 126 } 127 this.env.currentlyRunningTests = false; 128 }; 129 130 jasmine.Spec.prototype.safeExecuteBefores = function() { 131 var befores = []; 132 for (var suite = this.suite; suite; suite = suite.parentSuite) { 133 if (suite.beforeEachFunction) befores.push(suite.beforeEachFunction); 134 } 135 136 while (befores.length) { 137 this.safeExecuteBeforeOrAfter(befores.pop()); 138 } 139 }; 140 141 jasmine.Spec.prototype.safeExecuteAfters = function() { 142 for (var suite = this.suite; suite; suite = suite.parentSuite) { 143 if (suite.afterEachFunction) this.safeExecuteBeforeOrAfter(suite.afterEachFunction); 144 } 145 }; 146 147 jasmine.Spec.prototype.safeExecuteBeforeOrAfter = function(func) { 148 try { 149 func.apply(this); 150 } catch (e) { 151 this.results.addResult(new jasmine.ExpectationResult(false, func.typeName + '() fail: ' + jasmine.util.formatException(e), null)); 152 } 153 }; 154 155 jasmine.Spec.prototype.explodes = function() { 156 throw 'explodes function should not have been called'; 157 }; 158 159 jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { 160 if (obj == undefined) { 161 throw "spyOn could not find an object to spy upon for " + methodName + "()"; 162 } 163 164 if (!ignoreMethodDoesntExist && obj[methodName] === undefined) { 165 throw methodName + '() method does not exist'; 166 } 167 168 if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { 169 throw new Error(methodName + ' has already been spied upon'); 170 } 171 172 var spyObj = jasmine.createSpy(methodName); 173 174 this.spies_.push(spyObj); 175 spyObj.baseObj = obj; 176 spyObj.methodName = methodName; 177 spyObj.originalValue = obj[methodName]; 178 179 obj[methodName] = spyObj; 180 181 return spyObj; 182 }; 183 184 jasmine.Spec.prototype.removeAllSpies = function() { 185 for (var i = 0; i < this.spies_.length; i++) { 186 var spy = this.spies_[i]; 187 spy.baseObj[spy.methodName] = spy.originalValue; 188 } 189 this.spies_ = []; 190 }; 191 192