1 /**
  2  * QueuedFunction is how ActionCollections' actions are implemented
  3  *
  4  * @constructor
  5  * @param {jasmine.Env} env
  6  * @param {Function} func
  7  * @param {Number} timeout
  8  * @param {Function} latchFunction
  9  * @param {jasmine.Spec} spec
 10  */
 11 jasmine.QueuedFunction = function(env, func, timeout, latchFunction, spec) {
 12   this.env = env;
 13   this.func = func;
 14   this.timeout = timeout;
 15   this.latchFunction = latchFunction;
 16   this.spec = spec;
 17 
 18   this.totalTimeSpentWaitingForLatch = 0;
 19   this.latchTimeoutIncrement = 100;
 20 };
 21 
 22 jasmine.QueuedFunction.prototype.next = function() {
 23   this.spec.finish(); // default value is to be done after one function
 24 };
 25 
 26 jasmine.QueuedFunction.prototype.safeExecute = function() {
 27   if (this.env.reporter) {
 28     this.env.reporter.log('>> Jasmine Running ' + this.spec.suite.description + ' ' + this.spec.description + '...');
 29   }
 30 
 31   try {
 32     this.func.apply(this.spec);
 33   } catch (e) {
 34     this.fail(e);
 35   }
 36 };
 37 
 38 jasmine.QueuedFunction.prototype.execute = function() {
 39   var self = this;
 40   var executeNow = function() {
 41     self.safeExecute();
 42     self.next();
 43   };
 44 
 45   var executeLater = function() {
 46     self.env.setTimeout(executeNow, self.timeout);
 47   };
 48 
 49   var executeNowOrLater = function() {
 50     var latchFunctionResult;
 51 
 52     try {
 53       latchFunctionResult = self.latchFunction.apply(self.spec);
 54     } catch (e) {
 55       self.fail(e);
 56       self.next();
 57       return;
 58     }
 59 
 60     if (latchFunctionResult) {
 61       executeNow();
 62     } else if (self.totalTimeSpentWaitingForLatch >= self.timeout) {
 63       var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.latchFunction.description || 'something to happen');
 64       self.fail({
 65         name: 'timeout',
 66         message: message
 67       });
 68       self.next();
 69     } else {
 70       self.totalTimeSpentWaitingForLatch += self.latchTimeoutIncrement;
 71       self.env.setTimeout(executeNowOrLater, self.latchTimeoutIncrement);
 72     }
 73   };
 74 
 75   if (this.latchFunction !== undefined) {
 76     executeNowOrLater();
 77   } else if (this.timeout > 0) {
 78     executeLater();
 79   } else {
 80     executeNow();
 81   }
 82 };
 83 
 84 jasmine.QueuedFunction.prototype.fail = function(e) {
 85   this.spec.results.addResult(new jasmine.ExpectationResult(false, jasmine.util.formatException(e), null));
 86 };
 87