github.com/kvattikuti/drone@v0.2.1-0.20140603034306-d400229a327a/cmd/droned/assets/test/lib/jasmine-2.0.0/jasmine.js (about)

     1  /*
     2  Copyright (c) 2008-2013 Pivotal Labs
     3  
     4  Permission is hereby granted, free of charge, to any person obtaining
     5  a copy of this software and associated documentation files (the
     6  "Software"), to deal in the Software without restriction, including
     7  without limitation the rights to use, copy, modify, merge, publish,
     8  distribute, sublicense, and/or sell copies of the Software, and to
     9  permit persons to whom the Software is furnished to do so, subject to
    10  the following conditions:
    11  
    12  The above copyright notice and this permission notice shall be
    13  included in all copies or substantial portions of the Software.
    14  
    15  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    16  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    17  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    18  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    19  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    20  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    21  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    22  */
    23  function getJasmineRequireObj() {
    24    if (typeof module !== "undefined" && module.exports) {
    25      return exports;
    26    } else {
    27      window.jasmineRequire = window.jasmineRequire || {};
    28      return window.jasmineRequire;
    29    }
    30  }
    31  
    32  getJasmineRequireObj().core = function(jRequire) {
    33    var j$ = {};
    34  
    35    jRequire.base(j$);
    36    j$.util = jRequire.util();
    37    j$.Any = jRequire.Any();
    38    j$.CallTracker = jRequire.CallTracker();
    39    j$.Clock = jRequire.Clock();
    40    j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
    41    j$.Env = jRequire.Env(j$);
    42    j$.ExceptionFormatter = jRequire.ExceptionFormatter();
    43    j$.Expectation = jRequire.Expectation();
    44    j$.buildExpectationResult = jRequire.buildExpectationResult();
    45    j$.JsApiReporter = jRequire.JsApiReporter();
    46    j$.matchersUtil = jRequire.matchersUtil(j$);
    47    j$.ObjectContaining = jRequire.ObjectContaining(j$);
    48    j$.pp = jRequire.pp(j$);
    49    j$.QueueRunner = jRequire.QueueRunner();
    50    j$.ReportDispatcher = jRequire.ReportDispatcher();
    51    j$.Spec = jRequire.Spec(j$);
    52    j$.SpyStrategy = jRequire.SpyStrategy();
    53    j$.Suite = jRequire.Suite();
    54    j$.Timer = jRequire.Timer();
    55    j$.version = jRequire.version();
    56  
    57    j$.matchers = jRequire.requireMatchers(jRequire, j$);
    58  
    59    return j$;
    60  };
    61  
    62  getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
    63    var availableMatchers = [
    64        "toBe",
    65        "toBeCloseTo",
    66        "toBeDefined",
    67        "toBeFalsy",
    68        "toBeGreaterThan",
    69        "toBeLessThan",
    70        "toBeNaN",
    71        "toBeNull",
    72        "toBeTruthy",
    73        "toBeUndefined",
    74        "toContain",
    75        "toEqual",
    76        "toHaveBeenCalled",
    77        "toHaveBeenCalledWith",
    78        "toMatch",
    79        "toThrow",
    80        "toThrowError"
    81      ],
    82      matchers = {};
    83  
    84    for (var i = 0; i < availableMatchers.length; i++) {
    85      var name = availableMatchers[i];
    86      matchers[name] = jRequire[name](j$);
    87    }
    88  
    89    return matchers;
    90  };
    91  
    92  getJasmineRequireObj().base = function(j$) {
    93    j$.unimplementedMethod_ = function() {
    94      throw new Error("unimplemented method");
    95    };
    96  
    97    j$.MAX_PRETTY_PRINT_DEPTH = 40;
    98    j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
    99  
   100    j$.getGlobal = (function() {
   101      var jasmineGlobal = eval.call(null, "this");
   102      return function() {
   103        return jasmineGlobal;
   104      };
   105    })();
   106  
   107    j$.getEnv = function(options) {
   108      var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
   109      //jasmine. singletons in here (setTimeout blah blah).
   110      return env;
   111    };
   112  
   113    j$.isArray_ = function(value) {
   114      return j$.isA_("Array", value);
   115    };
   116  
   117    j$.isString_ = function(value) {
   118      return j$.isA_("String", value);
   119    };
   120  
   121    j$.isNumber_ = function(value) {
   122      return j$.isA_("Number", value);
   123    };
   124  
   125    j$.isA_ = function(typeName, value) {
   126      return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
   127    };
   128  
   129    j$.isDomNode = function(obj) {
   130      return obj.nodeType > 0;
   131    };
   132  
   133    j$.any = function(clazz) {
   134      return new j$.Any(clazz);
   135    };
   136  
   137    j$.objectContaining = function(sample) {
   138      return new j$.ObjectContaining(sample);
   139    };
   140  
   141    j$.createSpy = function(name, originalFn) {
   142  
   143      var spyStrategy = new j$.SpyStrategy({
   144          name: name,
   145          fn: originalFn,
   146          getSpy: function() { return spy; }
   147        }),
   148        callTracker = new j$.CallTracker(),
   149        spy = function() {
   150          callTracker.track({
   151            object: this,
   152            args: Array.prototype.slice.apply(arguments)
   153          });
   154          return spyStrategy.exec.apply(this, arguments);
   155        };
   156  
   157      for (var prop in originalFn) {
   158        if (prop === 'and' || prop === 'calls') {
   159          throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
   160        }
   161  
   162        spy[prop] = originalFn[prop];
   163      }
   164  
   165      spy.and = spyStrategy;
   166      spy.calls = callTracker;
   167  
   168      return spy;
   169    };
   170  
   171    j$.isSpy = function(putativeSpy) {
   172      if (!putativeSpy) {
   173        return false;
   174      }
   175      return putativeSpy.and instanceof j$.SpyStrategy &&
   176        putativeSpy.calls instanceof j$.CallTracker;
   177    };
   178  
   179    j$.createSpyObj = function(baseName, methodNames) {
   180      if (!j$.isArray_(methodNames) || methodNames.length === 0) {
   181        throw "createSpyObj requires a non-empty array of method names to create spies for";
   182      }
   183      var obj = {};
   184      for (var i = 0; i < methodNames.length; i++) {
   185        obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]);
   186      }
   187      return obj;
   188    };
   189  };
   190  
   191  getJasmineRequireObj().util = function() {
   192  
   193    var util = {};
   194  
   195    util.inherit = function(childClass, parentClass) {
   196      var Subclass = function() {
   197      };
   198      Subclass.prototype = parentClass.prototype;
   199      childClass.prototype = new Subclass();
   200    };
   201  
   202    util.htmlEscape = function(str) {
   203      if (!str) {
   204        return str;
   205      }
   206      return str.replace(/&/g, '&amp;')
   207        .replace(/</g, '&lt;')
   208        .replace(/>/g, '&gt;');
   209    };
   210  
   211    util.argsToArray = function(args) {
   212      var arrayOfArgs = [];
   213      for (var i = 0; i < args.length; i++) {
   214        arrayOfArgs.push(args[i]);
   215      }
   216      return arrayOfArgs;
   217    };
   218  
   219    util.isUndefined = function(obj) {
   220      return obj === void 0;
   221    };
   222  
   223    return util;
   224  };
   225  
   226  getJasmineRequireObj().Spec = function(j$) {
   227    function Spec(attrs) {
   228      this.expectationFactory = attrs.expectationFactory;
   229      this.resultCallback = attrs.resultCallback || function() {};
   230      this.id = attrs.id;
   231      this.description = attrs.description || '';
   232      this.fn = attrs.fn;
   233      this.beforeFns = attrs.beforeFns || function() { return []; };
   234      this.afterFns = attrs.afterFns || function() { return []; };
   235      this.onStart = attrs.onStart || function() {};
   236      this.exceptionFormatter = attrs.exceptionFormatter || function() {};
   237      this.getSpecName = attrs.getSpecName || function() { return ''; };
   238      this.expectationResultFactory = attrs.expectationResultFactory || function() { };
   239      this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
   240      this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
   241  
   242      this.timer = attrs.timer || {setTimeout: setTimeout, clearTimeout: clearTimeout};
   243  
   244      if (!this.fn) {
   245        this.pend();
   246      }
   247  
   248      this.result = {
   249        id: this.id,
   250        description: this.description,
   251        fullName: this.getFullName(),
   252        failedExpectations: []
   253      };
   254    }
   255  
   256    Spec.prototype.addExpectationResult = function(passed, data) {
   257      if (passed) {
   258        return;
   259      }
   260      this.result.failedExpectations.push(this.expectationResultFactory(data));
   261    };
   262  
   263    Spec.prototype.expect = function(actual) {
   264      return this.expectationFactory(actual, this);
   265    };
   266  
   267    Spec.prototype.execute = function(onComplete) {
   268      var self = this,
   269          timeout;
   270  
   271      this.onStart(this);
   272  
   273      if (this.markedPending || this.disabled) {
   274        complete();
   275        return;
   276      }
   277  
   278      function timeoutable(fn) {
   279        return function(done) {
   280          timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
   281            onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
   282            done();
   283          }, j$.DEFAULT_TIMEOUT_INTERVAL]]);
   284  
   285          var callDone = function() {
   286            clearTimeoutable();
   287            done();
   288          };
   289  
   290          fn.call(this, callDone); //TODO: do we care about more than 1 arg?
   291        };
   292      }
   293  
   294      function clearTimeoutable() {
   295        Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
   296        timeout = void 0;
   297      }
   298  
   299      var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()),
   300        allTimeoutableFns = [];
   301      for (var i = 0; i < allFns.length; i++) {
   302        var fn = allFns[i];
   303        allTimeoutableFns.push(fn.length > 0 ? timeoutable(fn) : fn);
   304      }
   305  
   306      this.queueRunnerFactory({
   307        fns: allTimeoutableFns,
   308        onException: onException,
   309        onComplete: complete
   310      });
   311  
   312      function onException(e) {
   313        clearTimeoutable();
   314        if (Spec.isPendingSpecException(e)) {
   315          self.pend();
   316          return;
   317        }
   318  
   319        self.addExpectationResult(false, {
   320          matcherName: "",
   321          passed: false,
   322          expected: "",
   323          actual: "",
   324          error: e
   325        });
   326      }
   327  
   328      function complete() {
   329        self.result.status = self.status();
   330        self.resultCallback(self.result);
   331  
   332        if (onComplete) {
   333          onComplete();
   334        }
   335      }
   336    };
   337  
   338    Spec.prototype.disable = function() {
   339      this.disabled = true;
   340    };
   341  
   342    Spec.prototype.pend = function() {
   343      this.markedPending = true;
   344    };
   345  
   346    Spec.prototype.status = function() {
   347      if (this.disabled) {
   348        return 'disabled';
   349      }
   350  
   351      if (this.markedPending) {
   352        return 'pending';
   353      }
   354  
   355      if (this.result.failedExpectations.length > 0) {
   356        return 'failed';
   357      } else {
   358        return 'passed';
   359      }
   360    };
   361  
   362    Spec.prototype.getFullName = function() {
   363      return this.getSpecName(this);
   364    };
   365  
   366    Spec.pendingSpecExceptionMessage = "=> marked Pending";
   367  
   368    Spec.isPendingSpecException = function(e) {
   369      return e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1;
   370    };
   371  
   372    return Spec;
   373  };
   374  
   375  if (typeof window == void 0 && typeof exports == "object") {
   376    exports.Spec = jasmineRequire.Spec;
   377  }
   378  
   379  getJasmineRequireObj().Env = function(j$) {
   380    function Env(options) {
   381      options = options || {};
   382  
   383      var self = this;
   384      var global = options.global || j$.getGlobal();
   385  
   386      var totalSpecsDefined = 0;
   387  
   388      var catchExceptions = true;
   389  
   390      var realSetTimeout = j$.getGlobal().setTimeout;
   391      var realClearTimeout = j$.getGlobal().clearTimeout;
   392      this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
   393  
   394      var runnableLookupTable = {};
   395  
   396      var spies = [];
   397  
   398      var currentSpec = null;
   399      var currentSuite = null;
   400  
   401      var reporter = new j$.ReportDispatcher([
   402        "jasmineStarted",
   403        "jasmineDone",
   404        "suiteStarted",
   405        "suiteDone",
   406        "specStarted",
   407        "specDone"
   408      ]);
   409  
   410      this.specFilter = function() {
   411        return true;
   412      };
   413  
   414      var equalityTesters = [];
   415  
   416      var customEqualityTesters = [];
   417      this.addCustomEqualityTester = function(tester) {
   418        customEqualityTesters.push(tester);
   419      };
   420  
   421      j$.Expectation.addCoreMatchers(j$.matchers);
   422  
   423      var nextSpecId = 0;
   424      var getNextSpecId = function() {
   425        return 'spec' + nextSpecId++;
   426      };
   427  
   428      var nextSuiteId = 0;
   429      var getNextSuiteId = function() {
   430        return 'suite' + nextSuiteId++;
   431      };
   432  
   433      var expectationFactory = function(actual, spec) {
   434        return j$.Expectation.Factory({
   435          util: j$.matchersUtil,
   436          customEqualityTesters: customEqualityTesters,
   437          actual: actual,
   438          addExpectationResult: addExpectationResult
   439        });
   440  
   441        function addExpectationResult(passed, result) {
   442          return spec.addExpectationResult(passed, result);
   443        }
   444      };
   445  
   446      var specStarted = function(spec) {
   447        currentSpec = spec;
   448        reporter.specStarted(spec.result);
   449      };
   450  
   451      var beforeFns = function(suite) {
   452        return function() {
   453          var befores = [];
   454          while(suite) {
   455            befores = befores.concat(suite.beforeFns);
   456            suite = suite.parentSuite;
   457          }
   458          return befores.reverse();
   459        };
   460      };
   461  
   462      var afterFns = function(suite) {
   463        return function() {
   464          var afters = [];
   465          while(suite) {
   466            afters = afters.concat(suite.afterFns);
   467            suite = suite.parentSuite;
   468          }
   469          return afters;
   470        };
   471      };
   472  
   473      var getSpecName = function(spec, suite) {
   474        return suite.getFullName() + ' ' + spec.description;
   475      };
   476  
   477      // TODO: we may just be able to pass in the fn instead of wrapping here
   478      var buildExpectationResult = j$.buildExpectationResult,
   479          exceptionFormatter = new j$.ExceptionFormatter(),
   480          expectationResultFactory = function(attrs) {
   481            attrs.messageFormatter = exceptionFormatter.message;
   482            attrs.stackFormatter = exceptionFormatter.stack;
   483  
   484            return buildExpectationResult(attrs);
   485          };
   486  
   487      // TODO: fix this naming, and here's where the value comes in
   488      this.catchExceptions = function(value) {
   489        catchExceptions = !!value;
   490        return catchExceptions;
   491      };
   492  
   493      this.catchingExceptions = function() {
   494        return catchExceptions;
   495      };
   496  
   497      var maximumSpecCallbackDepth = 20;
   498      var currentSpecCallbackDepth = 0;
   499  
   500      function clearStack(fn) {
   501        currentSpecCallbackDepth++;
   502        if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) {
   503          currentSpecCallbackDepth = 0;
   504          realSetTimeout(fn, 0);
   505        } else {
   506          fn();
   507        }
   508      }
   509  
   510      var catchException = function(e) {
   511        return j$.Spec.isPendingSpecException(e) || catchExceptions;
   512      };
   513  
   514      var queueRunnerFactory = function(options) {
   515        options.catchException = catchException;
   516        options.clearStack = options.clearStack || clearStack;
   517  
   518        new j$.QueueRunner(options).execute();
   519      };
   520  
   521      var topSuite = new j$.Suite({
   522        env: this,
   523        id: getNextSuiteId(),
   524        description: 'Jasmine__TopLevel__Suite',
   525        queueRunner: queueRunnerFactory,
   526        resultCallback: function() {} // TODO - hook this up
   527      });
   528      runnableLookupTable[topSuite.id] = topSuite;
   529      currentSuite = topSuite;
   530  
   531      this.topSuite = function() {
   532        return topSuite;
   533      };
   534  
   535      this.execute = function(runnablesToRun) {
   536        runnablesToRun = runnablesToRun || [topSuite.id];
   537  
   538        var allFns = [];
   539        for(var i = 0; i < runnablesToRun.length; i++) {
   540          var runnable = runnableLookupTable[runnablesToRun[i]];
   541          allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
   542        }
   543  
   544        reporter.jasmineStarted({
   545          totalSpecsDefined: totalSpecsDefined
   546        });
   547  
   548        queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
   549      };
   550  
   551      this.addReporter = function(reporterToAdd) {
   552        reporter.addReporter(reporterToAdd);
   553      };
   554  
   555      this.addMatchers = function(matchersToAdd) {
   556        j$.Expectation.addMatchers(matchersToAdd);
   557      };
   558  
   559      this.spyOn = function(obj, methodName) {
   560        if (j$.util.isUndefined(obj)) {
   561          throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
   562        }
   563  
   564        if (j$.util.isUndefined(obj[methodName])) {
   565          throw new Error(methodName + '() method does not exist');
   566        }
   567  
   568        if (obj[methodName] && j$.isSpy(obj[methodName])) {
   569          //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
   570          throw new Error(methodName + ' has already been spied upon');
   571        }
   572  
   573        var spy = j$.createSpy(methodName, obj[methodName]);
   574  
   575        spies.push({
   576          spy: spy,
   577          baseObj: obj,
   578          methodName: methodName,
   579          originalValue: obj[methodName]
   580        });
   581  
   582        obj[methodName] = spy;
   583  
   584        return spy;
   585      };
   586  
   587      var suiteFactory = function(description) {
   588        var suite = new j$.Suite({
   589          env: self,
   590          id: getNextSuiteId(),
   591          description: description,
   592          parentSuite: currentSuite,
   593          queueRunner: queueRunnerFactory,
   594          onStart: suiteStarted,
   595          resultCallback: function(attrs) {
   596            reporter.suiteDone(attrs);
   597          }
   598        });
   599  
   600        runnableLookupTable[suite.id] = suite;
   601        return suite;
   602      };
   603  
   604      this.describe = function(description, specDefinitions) {
   605        var suite = suiteFactory(description);
   606  
   607        var parentSuite = currentSuite;
   608        parentSuite.addChild(suite);
   609        currentSuite = suite;
   610  
   611        var declarationError = null;
   612        try {
   613          specDefinitions.call(suite);
   614        } catch (e) {
   615          declarationError = e;
   616        }
   617  
   618        if (declarationError) {
   619          this.it("encountered a declaration exception", function() {
   620            throw declarationError;
   621          });
   622        }
   623  
   624        currentSuite = parentSuite;
   625  
   626        return suite;
   627      };
   628  
   629      this.xdescribe = function(description, specDefinitions) {
   630        var suite = this.describe(description, specDefinitions);
   631        suite.disable();
   632        return suite;
   633      };
   634  
   635      var specFactory = function(description, fn, suite) {
   636        totalSpecsDefined++;
   637  
   638        var spec = new j$.Spec({
   639          id: getNextSpecId(),
   640          beforeFns: beforeFns(suite),
   641          afterFns: afterFns(suite),
   642          expectationFactory: expectationFactory,
   643          exceptionFormatter: exceptionFormatter,
   644          resultCallback: specResultCallback,
   645          getSpecName: function(spec) {
   646            return getSpecName(spec, suite);
   647          },
   648          onStart: specStarted,
   649          description: description,
   650          expectationResultFactory: expectationResultFactory,
   651          queueRunnerFactory: queueRunnerFactory,
   652          fn: fn,
   653          timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
   654        });
   655  
   656        runnableLookupTable[spec.id] = spec;
   657  
   658        if (!self.specFilter(spec)) {
   659          spec.disable();
   660        }
   661  
   662        return spec;
   663  
   664        function removeAllSpies() {
   665          for (var i = 0; i < spies.length; i++) {
   666            var spyEntry = spies[i];
   667            spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
   668          }
   669          spies = [];
   670        }
   671  
   672        function specResultCallback(result) {
   673          removeAllSpies();
   674          j$.Expectation.resetMatchers();
   675          customEqualityTesters = [];
   676          currentSpec = null;
   677          reporter.specDone(result);
   678        }
   679      };
   680  
   681      var suiteStarted = function(suite) {
   682        reporter.suiteStarted(suite.result);
   683      };
   684  
   685      this.it = function(description, fn) {
   686        var spec = specFactory(description, fn, currentSuite);
   687        currentSuite.addChild(spec);
   688        return spec;
   689      };
   690  
   691      this.xit = function(description, fn) {
   692        var spec = this.it(description, fn);
   693        spec.pend();
   694        return spec;
   695      };
   696  
   697      this.expect = function(actual) {
   698        return currentSpec.expect(actual);
   699      };
   700  
   701      this.beforeEach = function(beforeEachFunction) {
   702        currentSuite.beforeEach(beforeEachFunction);
   703      };
   704  
   705      this.afterEach = function(afterEachFunction) {
   706        currentSuite.afterEach(afterEachFunction);
   707      };
   708  
   709      this.pending = function() {
   710        throw j$.Spec.pendingSpecExceptionMessage;
   711      };
   712    }
   713  
   714    return Env;
   715  };
   716  
   717  getJasmineRequireObj().JsApiReporter = function() {
   718  
   719    var noopTimer = {
   720      start: function(){},
   721      elapsed: function(){ return 0; }
   722    };
   723  
   724    function JsApiReporter(options) {
   725      var timer = options.timer || noopTimer,
   726          status = "loaded";
   727  
   728      this.started = false;
   729      this.finished = false;
   730  
   731      this.jasmineStarted = function() {
   732        this.started = true;
   733        status = 'started';
   734        timer.start();
   735      };
   736  
   737      var executionTime;
   738  
   739      this.jasmineDone = function() {
   740        this.finished = true;
   741        executionTime = timer.elapsed();
   742        status = 'done';
   743      };
   744  
   745      this.status = function() {
   746        return status;
   747      };
   748  
   749      var suites = {};
   750  
   751      this.suiteStarted = function(result) {
   752        storeSuite(result);
   753      };
   754  
   755      this.suiteDone = function(result) {
   756        storeSuite(result);
   757      };
   758  
   759      function storeSuite(result) {
   760        suites[result.id] = result;
   761      }
   762  
   763      this.suites = function() {
   764        return suites;
   765      };
   766  
   767      var specs = [];
   768      this.specStarted = function(result) { };
   769  
   770      this.specDone = function(result) {
   771        specs.push(result);
   772      };
   773  
   774      this.specResults = function(index, length) {
   775        return specs.slice(index, index + length);
   776      };
   777  
   778      this.specs = function() {
   779        return specs;
   780      };
   781  
   782      this.executionTime = function() {
   783        return executionTime;
   784      };
   785  
   786    }
   787  
   788    return JsApiReporter;
   789  };
   790  
   791  getJasmineRequireObj().Any = function() {
   792  
   793    function Any(expectedObject) {
   794      this.expectedObject = expectedObject;
   795    }
   796  
   797    Any.prototype.jasmineMatches = function(other) {
   798      if (this.expectedObject == String) {
   799        return typeof other == 'string' || other instanceof String;
   800      }
   801  
   802      if (this.expectedObject == Number) {
   803        return typeof other == 'number' || other instanceof Number;
   804      }
   805  
   806      if (this.expectedObject == Function) {
   807        return typeof other == 'function' || other instanceof Function;
   808      }
   809  
   810      if (this.expectedObject == Object) {
   811        return typeof other == 'object';
   812      }
   813  
   814      if (this.expectedObject == Boolean) {
   815        return typeof other == 'boolean';
   816      }
   817  
   818      return other instanceof this.expectedObject;
   819    };
   820  
   821    Any.prototype.jasmineToString = function() {
   822      return '<jasmine.any(' + this.expectedClass + ')>';
   823    };
   824  
   825    return Any;
   826  };
   827  
   828  getJasmineRequireObj().CallTracker = function() {
   829  
   830    function CallTracker() {
   831      var calls = [];
   832  
   833      this.track = function(context) {
   834        calls.push(context);
   835      };
   836  
   837      this.any = function() {
   838        return !!calls.length;
   839      };
   840  
   841      this.count = function() {
   842        return calls.length;
   843      };
   844  
   845      this.argsFor = function(index) {
   846        var call = calls[index];
   847        return call ? call.args : [];
   848      };
   849  
   850      this.all = function() {
   851        return calls;
   852      };
   853  
   854      this.allArgs = function() {
   855        var callArgs = [];
   856        for(var i = 0; i < calls.length; i++){
   857          callArgs.push(calls[i].args);
   858        }
   859  
   860        return callArgs;
   861      };
   862  
   863      this.first = function() {
   864        return calls[0];
   865      };
   866  
   867      this.mostRecent = function() {
   868        return calls[calls.length - 1];
   869      };
   870  
   871      this.reset = function() {
   872        calls = [];
   873      };
   874    }
   875  
   876    return CallTracker;
   877  };
   878  
   879  getJasmineRequireObj().Clock = function() {
   880    function Clock(global, delayedFunctionScheduler) {
   881      var self = this,
   882        realTimingFunctions = {
   883          setTimeout: global.setTimeout,
   884          clearTimeout: global.clearTimeout,
   885          setInterval: global.setInterval,
   886          clearInterval: global.clearInterval
   887        },
   888        fakeTimingFunctions = {
   889          setTimeout: setTimeout,
   890          clearTimeout: clearTimeout,
   891          setInterval: setInterval,
   892          clearInterval: clearInterval
   893        },
   894        installed = false,
   895        timer;
   896  
   897      self.install = function() {
   898        replace(global, fakeTimingFunctions);
   899        timer = fakeTimingFunctions;
   900        installed = true;
   901      };
   902  
   903      self.uninstall = function() {
   904        delayedFunctionScheduler.reset();
   905        replace(global, realTimingFunctions);
   906        timer = realTimingFunctions;
   907        installed = false;
   908      };
   909  
   910      self.setTimeout = function(fn, delay, params) {
   911        if (legacyIE()) {
   912          if (arguments.length > 2) {
   913            throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill");
   914          }
   915          return timer.setTimeout(fn, delay);
   916        }
   917        return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]);
   918      };
   919  
   920      self.setInterval = function(fn, delay, params) {
   921        if (legacyIE()) {
   922          if (arguments.length > 2) {
   923            throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill");
   924          }
   925          return timer.setInterval(fn, delay);
   926        }
   927        return Function.prototype.apply.apply(timer.setInterval, [global, arguments]);
   928      };
   929  
   930      self.clearTimeout = function(id) {
   931        return Function.prototype.call.apply(timer.clearTimeout, [global, id]);
   932      };
   933  
   934      self.clearInterval = function(id) {
   935        return Function.prototype.call.apply(timer.clearInterval, [global, id]);
   936      };
   937  
   938      self.tick = function(millis) {
   939        if (installed) {
   940          delayedFunctionScheduler.tick(millis);
   941        } else {
   942          throw new Error("Mock clock is not installed, use jasmine.clock().install()");
   943        }
   944      };
   945  
   946      return self;
   947  
   948      function legacyIE() {
   949        //if these methods are polyfilled, apply will be present
   950        return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
   951      }
   952  
   953      function replace(dest, source) {
   954        for (var prop in source) {
   955          dest[prop] = source[prop];
   956        }
   957      }
   958  
   959      function setTimeout(fn, delay) {
   960        return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
   961      }
   962  
   963      function clearTimeout(id) {
   964        return delayedFunctionScheduler.removeFunctionWithId(id);
   965      }
   966  
   967      function setInterval(fn, interval) {
   968        return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
   969      }
   970  
   971      function clearInterval(id) {
   972        return delayedFunctionScheduler.removeFunctionWithId(id);
   973      }
   974  
   975      function argSlice(argsObj, n) {
   976        return Array.prototype.slice.call(argsObj, 2);
   977      }
   978    }
   979  
   980    return Clock;
   981  };
   982  
   983  getJasmineRequireObj().DelayedFunctionScheduler = function() {
   984    function DelayedFunctionScheduler() {
   985      var self = this;
   986      var scheduledLookup = [];
   987      var scheduledFunctions = {};
   988      var currentTime = 0;
   989      var delayedFnCount = 0;
   990  
   991      self.tick = function(millis) {
   992        millis = millis || 0;
   993        var endTime = currentTime + millis;
   994  
   995        runScheduledFunctions(endTime);
   996        currentTime = endTime;
   997      };
   998  
   999      self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
  1000        var f;
  1001        if (typeof(funcToCall) === 'string') {
  1002          /* jshint evil: true */
  1003          f = function() { return eval(funcToCall); };
  1004          /* jshint evil: false */
  1005        } else {
  1006          f = funcToCall;
  1007        }
  1008  
  1009        millis = millis || 0;
  1010        timeoutKey = timeoutKey || ++delayedFnCount;
  1011        runAtMillis = runAtMillis || (currentTime + millis);
  1012  
  1013        var funcToSchedule = {
  1014          runAtMillis: runAtMillis,
  1015          funcToCall: f,
  1016          recurring: recurring,
  1017          params: params,
  1018          timeoutKey: timeoutKey,
  1019          millis: millis
  1020        };
  1021  
  1022        if (runAtMillis in scheduledFunctions) {
  1023          scheduledFunctions[runAtMillis].push(funcToSchedule);
  1024        } else {
  1025          scheduledFunctions[runAtMillis] = [funcToSchedule];
  1026          scheduledLookup.push(runAtMillis);
  1027          scheduledLookup.sort(function (a, b) {
  1028            return a - b;
  1029          });
  1030        }
  1031  
  1032        return timeoutKey;
  1033      };
  1034  
  1035      self.removeFunctionWithId = function(timeoutKey) {
  1036        for (var runAtMillis in scheduledFunctions) {
  1037          var funcs = scheduledFunctions[runAtMillis];
  1038          var i = indexOfFirstToPass(funcs, function (func) {
  1039            return func.timeoutKey === timeoutKey;
  1040          });
  1041  
  1042          if (i > -1) {
  1043            if (funcs.length === 1) {
  1044              delete scheduledFunctions[runAtMillis];
  1045              deleteFromLookup(runAtMillis);
  1046            } else {
  1047              funcs.splice(i, 1);
  1048            }
  1049  
  1050            // intervals get rescheduled when executed, so there's never more
  1051            // than a single scheduled function with a given timeoutKey
  1052            break;
  1053          }
  1054        }
  1055      };
  1056  
  1057      self.reset = function() {
  1058        currentTime = 0;
  1059        scheduledLookup = [];
  1060        scheduledFunctions = {};
  1061        delayedFnCount = 0;
  1062      };
  1063  
  1064      return self;
  1065  
  1066      function indexOfFirstToPass(array, testFn) {
  1067        var index = -1;
  1068  
  1069        for (var i = 0; i < array.length; ++i) {
  1070          if (testFn(array[i])) {
  1071            index = i;
  1072            break;
  1073          }
  1074        }
  1075  
  1076        return index;
  1077      }
  1078  
  1079      function deleteFromLookup(key) {
  1080        var value = Number(key);
  1081        var i = indexOfFirstToPass(scheduledLookup, function (millis) {
  1082          return millis === value;
  1083        });
  1084  
  1085        if (i > -1) {
  1086          scheduledLookup.splice(i, 1);
  1087        }
  1088      }
  1089  
  1090      function reschedule(scheduledFn) {
  1091        self.scheduleFunction(scheduledFn.funcToCall,
  1092          scheduledFn.millis,
  1093          scheduledFn.params,
  1094          true,
  1095          scheduledFn.timeoutKey,
  1096          scheduledFn.runAtMillis + scheduledFn.millis);
  1097      }
  1098  
  1099      function runScheduledFunctions(endTime) {
  1100        if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
  1101          return;
  1102        }
  1103  
  1104        do {
  1105          currentTime = scheduledLookup.shift();
  1106  
  1107          var funcsToRun = scheduledFunctions[currentTime];
  1108          delete scheduledFunctions[currentTime];
  1109  
  1110          for (var i = 0; i < funcsToRun.length; ++i) {
  1111            var funcToRun = funcsToRun[i];
  1112            funcToRun.funcToCall.apply(null, funcToRun.params || []);
  1113  
  1114            if (funcToRun.recurring) {
  1115              reschedule(funcToRun);
  1116            }
  1117          }
  1118        } while (scheduledLookup.length > 0 &&
  1119                // checking first if we're out of time prevents setTimeout(0)
  1120                // scheduled in a funcToRun from forcing an extra iteration
  1121                   currentTime !== endTime  &&
  1122                   scheduledLookup[0] <= endTime);
  1123      }
  1124    }
  1125  
  1126    return DelayedFunctionScheduler;
  1127  };
  1128  
  1129  getJasmineRequireObj().ExceptionFormatter = function() {
  1130    function ExceptionFormatter() {
  1131      this.message = function(error) {
  1132        var message = error.name +
  1133          ': ' +
  1134          error.message;
  1135  
  1136        if (error.fileName || error.sourceURL) {
  1137          message += " in " + (error.fileName || error.sourceURL);
  1138        }
  1139  
  1140        if (error.line || error.lineNumber) {
  1141          message += " (line " + (error.line || error.lineNumber) + ")";
  1142        }
  1143  
  1144        return message;
  1145      };
  1146  
  1147      this.stack = function(error) {
  1148        return error ? error.stack : null;
  1149      };
  1150    }
  1151  
  1152    return ExceptionFormatter;
  1153  };
  1154  
  1155  getJasmineRequireObj().Expectation = function() {
  1156  
  1157    var matchers = {};
  1158  
  1159    function Expectation(options) {
  1160      this.util = options.util || { buildFailureMessage: function() {} };
  1161      this.customEqualityTesters = options.customEqualityTesters || [];
  1162      this.actual = options.actual;
  1163      this.addExpectationResult = options.addExpectationResult || function(){};
  1164      this.isNot = options.isNot;
  1165  
  1166      for (var matcherName in matchers) {
  1167        this[matcherName] = matchers[matcherName];
  1168      }
  1169    }
  1170  
  1171    Expectation.prototype.wrapCompare = function(name, matcherFactory) {
  1172      return function() {
  1173        var args = Array.prototype.slice.call(arguments, 0),
  1174          expected = args.slice(0),
  1175          message = "";
  1176  
  1177        args.unshift(this.actual);
  1178  
  1179        var matcher = matcherFactory(this.util, this.customEqualityTesters),
  1180            matcherCompare = matcher.compare;
  1181  
  1182        function defaultNegativeCompare() {
  1183          var result = matcher.compare.apply(null, args);
  1184          result.pass = !result.pass;
  1185          return result;
  1186        }
  1187  
  1188        if (this.isNot) {
  1189          matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
  1190        }
  1191  
  1192        var result = matcherCompare.apply(null, args);
  1193  
  1194        if (!result.pass) {
  1195          if (!result.message) {
  1196            args.unshift(this.isNot);
  1197            args.unshift(name);
  1198            message = this.util.buildFailureMessage.apply(null, args);
  1199          } else {
  1200            message = result.message;
  1201          }
  1202        }
  1203  
  1204        if (expected.length == 1) {
  1205          expected = expected[0];
  1206        }
  1207  
  1208        // TODO: how many of these params are needed?
  1209        this.addExpectationResult(
  1210          result.pass,
  1211          {
  1212            matcherName: name,
  1213            passed: result.pass,
  1214            message: message,
  1215            actual: this.actual,
  1216            expected: expected // TODO: this may need to be arrayified/sliced
  1217          }
  1218        );
  1219      };
  1220    };
  1221  
  1222    Expectation.addCoreMatchers = function(matchers) {
  1223      var prototype = Expectation.prototype;
  1224      for (var matcherName in matchers) {
  1225        var matcher = matchers[matcherName];
  1226        prototype[matcherName] = prototype.wrapCompare(matcherName, matcher);
  1227      }
  1228    };
  1229  
  1230    Expectation.addMatchers = function(matchersToAdd) {
  1231      for (var name in matchersToAdd) {
  1232        var matcher = matchersToAdd[name];
  1233        matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
  1234      }
  1235    };
  1236  
  1237    Expectation.resetMatchers = function() {
  1238      for (var name in matchers) {
  1239        delete matchers[name];
  1240      }
  1241    };
  1242  
  1243    Expectation.Factory = function(options) {
  1244      options = options || {};
  1245  
  1246      var expect = new Expectation(options);
  1247  
  1248      // TODO: this would be nice as its own Object - NegativeExpectation
  1249      // TODO: copy instead of mutate options
  1250      options.isNot = true;
  1251      expect.not = new Expectation(options);
  1252  
  1253      return expect;
  1254    };
  1255  
  1256    return Expectation;
  1257  };
  1258  
  1259  //TODO: expectation result may make more sense as a presentation of an expectation.
  1260  getJasmineRequireObj().buildExpectationResult = function() {
  1261    function buildExpectationResult(options) {
  1262      var messageFormatter = options.messageFormatter || function() {},
  1263        stackFormatter = options.stackFormatter || function() {};
  1264  
  1265      return {
  1266        matcherName: options.matcherName,
  1267        expected: options.expected,
  1268        actual: options.actual,
  1269        message: message(),
  1270        stack: stack(),
  1271        passed: options.passed
  1272      };
  1273  
  1274      function message() {
  1275        if (options.passed) {
  1276          return "Passed.";
  1277        } else if (options.message) {
  1278          return options.message;
  1279        } else if (options.error) {
  1280          return messageFormatter(options.error);
  1281        }
  1282        return "";
  1283      }
  1284  
  1285      function stack() {
  1286        if (options.passed) {
  1287          return "";
  1288        }
  1289  
  1290        var error = options.error;
  1291        if (!error) {
  1292          try {
  1293            throw new Error(message());
  1294          } catch (e) {
  1295            error = e;
  1296          }
  1297        }
  1298        return stackFormatter(error);
  1299      }
  1300    }
  1301  
  1302    return buildExpectationResult;
  1303  };
  1304  
  1305  getJasmineRequireObj().ObjectContaining = function(j$) {
  1306  
  1307    function ObjectContaining(sample) {
  1308      this.sample = sample;
  1309    }
  1310  
  1311    ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
  1312      if (typeof(this.sample) !== "object") { throw new Error("You must provide an object to objectContaining, not '"+this.sample+"'."); }
  1313  
  1314      mismatchKeys = mismatchKeys || [];
  1315      mismatchValues = mismatchValues || [];
  1316  
  1317      var hasKey = function(obj, keyName) {
  1318        return obj !== null && !j$.util.isUndefined(obj[keyName]);
  1319      };
  1320  
  1321      for (var property in this.sample) {
  1322        if (!hasKey(other, property) && hasKey(this.sample, property)) {
  1323          mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
  1324        }
  1325        else if (!j$.matchersUtil.equals(this.sample[property], other[property])) {
  1326          mismatchValues.push("'" + property + "' was '" + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + "' in actual, but was '" + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in expected.");
  1327        }
  1328      }
  1329  
  1330      return (mismatchKeys.length === 0 && mismatchValues.length === 0);
  1331    };
  1332  
  1333    ObjectContaining.prototype.jasmineToString = function() {
  1334      return "<jasmine.objectContaining(" + j$.pp(this.sample) + ")>";
  1335    };
  1336  
  1337    return ObjectContaining;
  1338  };
  1339  
  1340  getJasmineRequireObj().pp = function(j$) {
  1341  
  1342    function PrettyPrinter() {
  1343      this.ppNestLevel_ = 0;
  1344    }
  1345  
  1346    PrettyPrinter.prototype.format = function(value) {
  1347      this.ppNestLevel_++;
  1348      try {
  1349        if (j$.util.isUndefined(value)) {
  1350          this.emitScalar('undefined');
  1351        } else if (value === null) {
  1352          this.emitScalar('null');
  1353        } else if (value === j$.getGlobal()) {
  1354          this.emitScalar('<global>');
  1355        } else if (value.jasmineToString) {
  1356          this.emitScalar(value.jasmineToString());
  1357        } else if (typeof value === 'string') {
  1358          this.emitString(value);
  1359        } else if (j$.isSpy(value)) {
  1360          this.emitScalar("spy on " + value.and.identity());
  1361        } else if (value instanceof RegExp) {
  1362          this.emitScalar(value.toString());
  1363        } else if (typeof value === 'function') {
  1364          this.emitScalar('Function');
  1365        } else if (typeof value.nodeType === 'number') {
  1366          this.emitScalar('HTMLNode');
  1367        } else if (value instanceof Date) {
  1368          this.emitScalar('Date(' + value + ')');
  1369        } else if (value.__Jasmine_been_here_before__) {
  1370          this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
  1371        } else if (j$.isArray_(value) || j$.isA_('Object', value)) {
  1372          value.__Jasmine_been_here_before__ = true;
  1373          if (j$.isArray_(value)) {
  1374            this.emitArray(value);
  1375          } else {
  1376            this.emitObject(value);
  1377          }
  1378          delete value.__Jasmine_been_here_before__;
  1379        } else {
  1380          this.emitScalar(value.toString());
  1381        }
  1382      } finally {
  1383        this.ppNestLevel_--;
  1384      }
  1385    };
  1386  
  1387    PrettyPrinter.prototype.iterateObject = function(obj, fn) {
  1388      for (var property in obj) {
  1389        if (!obj.hasOwnProperty(property)) { continue; }
  1390        if (property == '__Jasmine_been_here_before__') { continue; }
  1391        fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
  1392            obj.__lookupGetter__(property) !== null) : false);
  1393      }
  1394    };
  1395  
  1396    PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_;
  1397    PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_;
  1398    PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_;
  1399    PrettyPrinter.prototype.emitString = j$.unimplementedMethod_;
  1400  
  1401    function StringPrettyPrinter() {
  1402      PrettyPrinter.call(this);
  1403  
  1404      this.string = '';
  1405    }
  1406  
  1407    j$.util.inherit(StringPrettyPrinter, PrettyPrinter);
  1408  
  1409    StringPrettyPrinter.prototype.emitScalar = function(value) {
  1410      this.append(value);
  1411    };
  1412  
  1413    StringPrettyPrinter.prototype.emitString = function(value) {
  1414      this.append("'" + value + "'");
  1415    };
  1416  
  1417    StringPrettyPrinter.prototype.emitArray = function(array) {
  1418      if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
  1419        this.append("Array");
  1420        return;
  1421      }
  1422  
  1423      this.append('[ ');
  1424      for (var i = 0; i < array.length; i++) {
  1425        if (i > 0) {
  1426          this.append(', ');
  1427        }
  1428        this.format(array[i]);
  1429      }
  1430      this.append(' ]');
  1431    };
  1432  
  1433    StringPrettyPrinter.prototype.emitObject = function(obj) {
  1434      if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
  1435        this.append("Object");
  1436        return;
  1437      }
  1438  
  1439      var self = this;
  1440      this.append('{ ');
  1441      var first = true;
  1442  
  1443      this.iterateObject(obj, function(property, isGetter) {
  1444        if (first) {
  1445          first = false;
  1446        } else {
  1447          self.append(', ');
  1448        }
  1449  
  1450        self.append(property);
  1451        self.append(' : ');
  1452        if (isGetter) {
  1453          self.append('<getter>');
  1454        } else {
  1455          self.format(obj[property]);
  1456        }
  1457      });
  1458  
  1459      this.append(' }');
  1460    };
  1461  
  1462    StringPrettyPrinter.prototype.append = function(value) {
  1463      this.string += value;
  1464    };
  1465  
  1466    return function(value) {
  1467      var stringPrettyPrinter = new StringPrettyPrinter();
  1468      stringPrettyPrinter.format(value);
  1469      return stringPrettyPrinter.string;
  1470    };
  1471  };
  1472  
  1473  getJasmineRequireObj().QueueRunner = function() {
  1474  
  1475    function QueueRunner(attrs) {
  1476      this.fns = attrs.fns || [];
  1477      this.onComplete = attrs.onComplete || function() {};
  1478      this.clearStack = attrs.clearStack || function(fn) {fn();};
  1479      this.onException = attrs.onException || function() {};
  1480      this.catchException = attrs.catchException || function() { return true; };
  1481      this.userContext = {};
  1482    }
  1483  
  1484    QueueRunner.prototype.execute = function() {
  1485      this.run(this.fns, 0);
  1486    };
  1487  
  1488    QueueRunner.prototype.run = function(fns, recursiveIndex) {
  1489      var length = fns.length,
  1490          self = this,
  1491          iterativeIndex;
  1492  
  1493      for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
  1494        var fn = fns[iterativeIndex];
  1495        if (fn.length > 0) {
  1496          return attemptAsync(fn);
  1497        } else {
  1498          attemptSync(fn);
  1499        }
  1500      }
  1501  
  1502      var runnerDone = iterativeIndex >= length;
  1503  
  1504      if (runnerDone) {
  1505        this.clearStack(this.onComplete);
  1506      }
  1507  
  1508      function attemptSync(fn) {
  1509        try {
  1510          fn.call(self.userContext);
  1511        } catch (e) {
  1512          handleException(e);
  1513        }
  1514      }
  1515  
  1516      function attemptAsync(fn) {
  1517        var next = function () { self.run(fns, iterativeIndex + 1); };
  1518  
  1519        try {
  1520          fn.call(self.userContext, next);
  1521        } catch (e) {
  1522          handleException(e);
  1523          next();
  1524        }
  1525      }
  1526  
  1527      function handleException(e) {
  1528        self.onException(e);
  1529        if (!self.catchException(e)) {
  1530          //TODO: set a var when we catch an exception and
  1531          //use a finally block to close the loop in a nice way..
  1532          throw e;
  1533        }
  1534      }
  1535    };
  1536  
  1537    return QueueRunner;
  1538  };
  1539  
  1540  getJasmineRequireObj().ReportDispatcher = function() {
  1541    function ReportDispatcher(methods) {
  1542  
  1543      var dispatchedMethods = methods || [];
  1544  
  1545      for (var i = 0; i < dispatchedMethods.length; i++) {
  1546        var method = dispatchedMethods[i];
  1547        this[method] = (function(m) {
  1548          return function() {
  1549            dispatch(m, arguments);
  1550          };
  1551        }(method));
  1552      }
  1553  
  1554      var reporters = [];
  1555  
  1556      this.addReporter = function(reporter) {
  1557        reporters.push(reporter);
  1558      };
  1559  
  1560      return this;
  1561  
  1562      function dispatch(method, args) {
  1563        for (var i = 0; i < reporters.length; i++) {
  1564          var reporter = reporters[i];
  1565          if (reporter[method]) {
  1566            reporter[method].apply(reporter, args);
  1567          }
  1568        }
  1569      }
  1570    }
  1571  
  1572    return ReportDispatcher;
  1573  };
  1574  
  1575  
  1576  getJasmineRequireObj().SpyStrategy = function() {
  1577  
  1578    function SpyStrategy(options) {
  1579      options = options || {};
  1580  
  1581      var identity = options.name || "unknown",
  1582          originalFn = options.fn || function() {},
  1583          getSpy = options.getSpy || function() {},
  1584          plan = function() {};
  1585  
  1586      this.identity = function() {
  1587        return identity;
  1588      };
  1589  
  1590      this.exec = function() {
  1591        return plan.apply(this, arguments);
  1592      };
  1593  
  1594      this.callThrough = function() {
  1595        plan = originalFn;
  1596        return getSpy();
  1597      };
  1598  
  1599      this.returnValue = function(value) {
  1600        plan = function() {
  1601          return value;
  1602        };
  1603        return getSpy();
  1604      };
  1605  
  1606      this.throwError = function(something) {
  1607        var error = (something instanceof Error) ? something : new Error(something);
  1608        plan = function() {
  1609          throw error;
  1610        };
  1611        return getSpy();
  1612      };
  1613  
  1614      this.callFake = function(fn) {
  1615        plan = fn;
  1616        return getSpy();
  1617      };
  1618  
  1619      this.stub = function(fn) {
  1620        plan = function() {};
  1621        return getSpy();
  1622      };
  1623    }
  1624  
  1625    return SpyStrategy;
  1626  };
  1627  
  1628  getJasmineRequireObj().Suite = function() {
  1629    function Suite(attrs) {
  1630      this.env = attrs.env;
  1631      this.id = attrs.id;
  1632      this.parentSuite = attrs.parentSuite;
  1633      this.description = attrs.description;
  1634      this.onStart = attrs.onStart || function() {};
  1635      this.resultCallback = attrs.resultCallback || function() {};
  1636      this.clearStack = attrs.clearStack || function(fn) {fn();};
  1637  
  1638      this.beforeFns = [];
  1639      this.afterFns = [];
  1640      this.queueRunner = attrs.queueRunner || function() {};
  1641      this.disabled = false;
  1642  
  1643      this.children = [];
  1644  
  1645      this.result = {
  1646        id: this.id,
  1647        status: this.disabled ? 'disabled' : '',
  1648        description: this.description,
  1649        fullName: this.getFullName()
  1650      };
  1651    }
  1652  
  1653    Suite.prototype.getFullName = function() {
  1654      var fullName = this.description;
  1655      for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
  1656        if (parentSuite.parentSuite) {
  1657          fullName = parentSuite.description + ' ' + fullName;
  1658        }
  1659      }
  1660      return fullName;
  1661    };
  1662  
  1663    Suite.prototype.disable = function() {
  1664      this.disabled = true;
  1665    };
  1666  
  1667    Suite.prototype.beforeEach = function(fn) {
  1668      this.beforeFns.unshift(fn);
  1669    };
  1670  
  1671    Suite.prototype.afterEach = function(fn) {
  1672      this.afterFns.unshift(fn);
  1673    };
  1674  
  1675    Suite.prototype.addChild = function(child) {
  1676      this.children.push(child);
  1677    };
  1678  
  1679    Suite.prototype.execute = function(onComplete) {
  1680      var self = this;
  1681      if (this.disabled) {
  1682        complete();
  1683        return;
  1684      }
  1685  
  1686      var allFns = [];
  1687  
  1688      for (var i = 0; i < this.children.length; i++) {
  1689        allFns.push(wrapChildAsAsync(this.children[i]));
  1690      }
  1691  
  1692      this.onStart(this);
  1693  
  1694      this.queueRunner({
  1695        fns: allFns,
  1696        onComplete: complete
  1697      });
  1698  
  1699      function complete() {
  1700        self.resultCallback(self.result);
  1701  
  1702        if (onComplete) {
  1703          onComplete();
  1704        }
  1705      }
  1706  
  1707      function wrapChildAsAsync(child) {
  1708        return function(done) { child.execute(done); };
  1709      }
  1710    };
  1711  
  1712    return Suite;
  1713  };
  1714  
  1715  if (typeof window == void 0 && typeof exports == "object") {
  1716    exports.Suite = jasmineRequire.Suite;
  1717  }
  1718  
  1719  getJasmineRequireObj().Timer = function() {
  1720    function Timer(options) {
  1721      options = options || {};
  1722  
  1723      var now = options.now || function() { return new Date().getTime(); },
  1724          startTime;
  1725  
  1726      this.start = function() {
  1727        startTime = now();
  1728      };
  1729  
  1730      this.elapsed = function() {
  1731        return now() - startTime;
  1732      };
  1733    }
  1734  
  1735    return Timer;
  1736  };
  1737  
  1738  getJasmineRequireObj().matchersUtil = function(j$) {
  1739    // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
  1740  
  1741    return {
  1742      equals: function(a, b, customTesters) {
  1743        customTesters = customTesters || [];
  1744  
  1745        return eq(a, b, [], [], customTesters);
  1746      },
  1747  
  1748      contains: function(haystack, needle, customTesters) {
  1749        customTesters = customTesters || [];
  1750  
  1751        if (Object.prototype.toString.apply(haystack) === "[object Array]") {
  1752          for (var i = 0; i < haystack.length; i++) {
  1753            if (eq(haystack[i], needle, [], [], customTesters)) {
  1754              return true;
  1755            }
  1756          }
  1757          return false;
  1758        }
  1759        return haystack.indexOf(needle) >= 0;
  1760      },
  1761  
  1762      buildFailureMessage: function() {
  1763        var args = Array.prototype.slice.call(arguments, 0),
  1764          matcherName = args[0],
  1765          isNot = args[1],
  1766          actual = args[2],
  1767          expected = args.slice(3),
  1768          englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
  1769  
  1770        var message = "Expected " +
  1771          j$.pp(actual) +
  1772          (isNot ? " not " : " ") +
  1773          englishyPredicate;
  1774  
  1775        if (expected.length > 0) {
  1776          for (var i = 0; i < expected.length; i++) {
  1777            if (i > 0) {
  1778              message += ",";
  1779            }
  1780            message += " " + j$.pp(expected[i]);
  1781          }
  1782        }
  1783  
  1784        return message + ".";
  1785      }
  1786    };
  1787  
  1788    // Equality function lovingly adapted from isEqual in
  1789    //   [Underscore](http://underscorejs.org)
  1790    function eq(a, b, aStack, bStack, customTesters) {
  1791      var result = true;
  1792  
  1793      for (var i = 0; i < customTesters.length; i++) {
  1794        var customTesterResult = customTesters[i](a, b);
  1795        if (!j$.util.isUndefined(customTesterResult)) {
  1796          return customTesterResult;
  1797        }
  1798      }
  1799  
  1800      if (a instanceof j$.Any) {
  1801        result = a.jasmineMatches(b);
  1802        if (result) {
  1803          return true;
  1804        }
  1805      }
  1806  
  1807      if (b instanceof j$.Any) {
  1808        result = b.jasmineMatches(a);
  1809        if (result) {
  1810          return true;
  1811        }
  1812      }
  1813  
  1814      if (b instanceof j$.ObjectContaining) {
  1815        result = b.jasmineMatches(a);
  1816        if (result) {
  1817          return true;
  1818        }
  1819      }
  1820  
  1821      if (a instanceof Error && b instanceof Error) {
  1822        return a.message == b.message;
  1823      }
  1824  
  1825      // Identical objects are equal. `0 === -0`, but they aren't identical.
  1826      // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
  1827      if (a === b) { return a !== 0 || 1 / a == 1 / b; }
  1828      // A strict comparison is necessary because `null == undefined`.
  1829      if (a === null || b === null) { return a === b; }
  1830      var className = Object.prototype.toString.call(a);
  1831      if (className != Object.prototype.toString.call(b)) { return false; }
  1832      switch (className) {
  1833        // Strings, numbers, dates, and booleans are compared by value.
  1834        case '[object String]':
  1835          // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
  1836          // equivalent to `new String("5")`.
  1837          return a == String(b);
  1838        case '[object Number]':
  1839          // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
  1840          // other numeric values.
  1841          return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b);
  1842        case '[object Date]':
  1843        case '[object Boolean]':
  1844          // Coerce dates and booleans to numeric primitive values. Dates are compared by their
  1845          // millisecond representations. Note that invalid dates with millisecond representations
  1846          // of `NaN` are not equivalent.
  1847          return +a == +b;
  1848        // RegExps are compared by their source patterns and flags.
  1849        case '[object RegExp]':
  1850          return a.source == b.source &&
  1851            a.global == b.global &&
  1852            a.multiline == b.multiline &&
  1853            a.ignoreCase == b.ignoreCase;
  1854      }
  1855      if (typeof a != 'object' || typeof b != 'object') { return false; }
  1856      // Assume equality for cyclic structures. The algorithm for detecting cyclic
  1857      // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
  1858      var length = aStack.length;
  1859      while (length--) {
  1860        // Linear search. Performance is inversely proportional to the number of
  1861        // unique nested structures.
  1862        if (aStack[length] == a) { return bStack[length] == b; }
  1863      }
  1864      // Add the first object to the stack of traversed objects.
  1865      aStack.push(a);
  1866      bStack.push(b);
  1867      var size = 0;
  1868      // Recursively compare objects and arrays.
  1869      if (className == '[object Array]') {
  1870        // Compare array lengths to determine if a deep comparison is necessary.
  1871        size = a.length;
  1872        result = size == b.length;
  1873        if (result) {
  1874          // Deep compare the contents, ignoring non-numeric properties.
  1875          while (size--) {
  1876            if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
  1877          }
  1878        }
  1879      } else {
  1880        // Objects with different constructors are not equivalent, but `Object`s
  1881        // from different frames are.
  1882        var aCtor = a.constructor, bCtor = b.constructor;
  1883        if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) &&
  1884          isFunction(bCtor) && (bCtor instanceof bCtor))) {
  1885          return false;
  1886        }
  1887        // Deep compare objects.
  1888        for (var key in a) {
  1889          if (has(a, key)) {
  1890            // Count the expected number of properties.
  1891            size++;
  1892            // Deep compare each member.
  1893            if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; }
  1894          }
  1895        }
  1896        // Ensure that both objects contain the same number of properties.
  1897        if (result) {
  1898          for (key in b) {
  1899            if (has(b, key) && !(size--)) { break; }
  1900          }
  1901          result = !size;
  1902        }
  1903      }
  1904      // Remove the first object from the stack of traversed objects.
  1905      aStack.pop();
  1906      bStack.pop();
  1907  
  1908      return result;
  1909  
  1910      function has(obj, key) {
  1911        return obj.hasOwnProperty(key);
  1912      }
  1913  
  1914      function isFunction(obj) {
  1915        return typeof obj === 'function';
  1916      }
  1917    }
  1918  };
  1919  
  1920  getJasmineRequireObj().toBe = function() {
  1921    function toBe() {
  1922      return {
  1923        compare: function(actual, expected) {
  1924          return {
  1925            pass: actual === expected
  1926          };
  1927        }
  1928      };
  1929    }
  1930  
  1931    return toBe;
  1932  };
  1933  
  1934  getJasmineRequireObj().toBeCloseTo = function() {
  1935  
  1936    function toBeCloseTo() {
  1937      return {
  1938        compare: function(actual, expected, precision) {
  1939          if (precision !== 0) {
  1940            precision = precision || 2;
  1941          }
  1942  
  1943          return {
  1944            pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2)
  1945          };
  1946        }
  1947      };
  1948    }
  1949  
  1950    return toBeCloseTo;
  1951  };
  1952  
  1953  getJasmineRequireObj().toBeDefined = function() {
  1954    function toBeDefined() {
  1955      return {
  1956        compare: function(actual) {
  1957          return {
  1958            pass: (void 0 !== actual)
  1959          };
  1960        }
  1961      };
  1962    }
  1963  
  1964    return toBeDefined;
  1965  };
  1966  
  1967  getJasmineRequireObj().toBeFalsy = function() {
  1968    function toBeFalsy() {
  1969      return {
  1970        compare: function(actual) {
  1971          return {
  1972            pass: !!!actual
  1973          };
  1974        }
  1975      };
  1976    }
  1977  
  1978    return toBeFalsy;
  1979  };
  1980  
  1981  getJasmineRequireObj().toBeGreaterThan = function() {
  1982  
  1983    function toBeGreaterThan() {
  1984      return {
  1985        compare: function(actual, expected) {
  1986          return {
  1987            pass: actual > expected
  1988          };
  1989        }
  1990      };
  1991    }
  1992  
  1993    return toBeGreaterThan;
  1994  };
  1995  
  1996  
  1997  getJasmineRequireObj().toBeLessThan = function() {
  1998    function toBeLessThan() {
  1999      return {
  2000  
  2001        compare: function(actual, expected) {
  2002          return {
  2003            pass: actual < expected
  2004          };
  2005        }
  2006      };
  2007    }
  2008  
  2009    return toBeLessThan;
  2010  };
  2011  getJasmineRequireObj().toBeNaN = function(j$) {
  2012  
  2013    function toBeNaN() {
  2014      return {
  2015        compare: function(actual) {
  2016          var result = {
  2017            pass: (actual !== actual)
  2018          };
  2019  
  2020          if (result.pass) {
  2021            result.message = "Expected actual not to be NaN.";
  2022          } else {
  2023            result.message = "Expected " + j$.pp(actual) + " to be NaN.";
  2024          }
  2025  
  2026          return result;
  2027        }
  2028      };
  2029    }
  2030  
  2031    return toBeNaN;
  2032  };
  2033  
  2034  getJasmineRequireObj().toBeNull = function() {
  2035  
  2036    function toBeNull() {
  2037      return {
  2038        compare: function(actual) {
  2039          return {
  2040            pass: actual === null
  2041          };
  2042        }
  2043      };
  2044    }
  2045  
  2046    return toBeNull;
  2047  };
  2048  
  2049  getJasmineRequireObj().toBeTruthy = function() {
  2050  
  2051    function toBeTruthy() {
  2052      return {
  2053        compare: function(actual) {
  2054          return {
  2055            pass: !!actual
  2056          };
  2057        }
  2058      };
  2059    }
  2060  
  2061    return toBeTruthy;
  2062  };
  2063  
  2064  getJasmineRequireObj().toBeUndefined = function() {
  2065  
  2066    function toBeUndefined() {
  2067      return {
  2068        compare: function(actual) {
  2069          return {
  2070            pass: void 0 === actual
  2071          };
  2072        }
  2073      };
  2074    }
  2075  
  2076    return toBeUndefined;
  2077  };
  2078  
  2079  getJasmineRequireObj().toContain = function() {
  2080    function toContain(util, customEqualityTesters) {
  2081      customEqualityTesters = customEqualityTesters || [];
  2082  
  2083      return {
  2084        compare: function(actual, expected) {
  2085  
  2086          return {
  2087            pass: util.contains(actual, expected, customEqualityTesters)
  2088          };
  2089        }
  2090      };
  2091    }
  2092  
  2093    return toContain;
  2094  };
  2095  
  2096  getJasmineRequireObj().toEqual = function() {
  2097  
  2098    function toEqual(util, customEqualityTesters) {
  2099      customEqualityTesters = customEqualityTesters || [];
  2100  
  2101      return {
  2102        compare: function(actual, expected) {
  2103          var result = {
  2104            pass: false
  2105          };
  2106  
  2107          result.pass = util.equals(actual, expected, customEqualityTesters);
  2108  
  2109          return result;
  2110        }
  2111      };
  2112    }
  2113  
  2114    return toEqual;
  2115  };
  2116  
  2117  getJasmineRequireObj().toHaveBeenCalled = function(j$) {
  2118  
  2119    function toHaveBeenCalled() {
  2120      return {
  2121        compare: function(actual) {
  2122          var result = {};
  2123  
  2124          if (!j$.isSpy(actual)) {
  2125            throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
  2126          }
  2127  
  2128          if (arguments.length > 1) {
  2129            throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
  2130          }
  2131  
  2132          result.pass = actual.calls.any();
  2133  
  2134          result.message = result.pass ?
  2135            "Expected spy " + actual.and.identity() + " not to have been called." :
  2136            "Expected spy " + actual.and.identity() + " to have been called.";
  2137  
  2138          return result;
  2139        }
  2140      };
  2141    }
  2142  
  2143    return toHaveBeenCalled;
  2144  };
  2145  
  2146  getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
  2147  
  2148    function toHaveBeenCalledWith(util) {
  2149      return {
  2150        compare: function() {
  2151          var args = Array.prototype.slice.call(arguments, 0),
  2152            actual = args[0],
  2153            expectedArgs = args.slice(1),
  2154            result = { pass: false };
  2155  
  2156          if (!j$.isSpy(actual)) {
  2157            throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
  2158          }
  2159  
  2160          if (!actual.calls.any()) {
  2161            result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but it was never called.";
  2162            return result;
  2163          }
  2164  
  2165          if (util.contains(actual.calls.allArgs(), expectedArgs)) {
  2166            result.pass = true;
  2167            result.message = "Expected spy " + actual.and.identity() + " not to have been called with " + j$.pp(expectedArgs) + " but it was.";
  2168          } else {
  2169            result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but actual calls were " + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + ".";
  2170          }
  2171  
  2172          return result;
  2173        }
  2174      };
  2175    }
  2176  
  2177    return toHaveBeenCalledWith;
  2178  };
  2179  
  2180  getJasmineRequireObj().toMatch = function() {
  2181  
  2182    function toMatch() {
  2183      return {
  2184        compare: function(actual, expected) {
  2185          var regexp = new RegExp(expected);
  2186  
  2187          return {
  2188            pass: regexp.test(actual)
  2189          };
  2190        }
  2191      };
  2192    }
  2193  
  2194    return toMatch;
  2195  };
  2196  
  2197  getJasmineRequireObj().toThrow = function(j$) {
  2198  
  2199    function toThrow(util) {
  2200      return {
  2201        compare: function(actual, expected) {
  2202          var result = { pass: false },
  2203            threw = false,
  2204            thrown;
  2205  
  2206          if (typeof actual != "function") {
  2207            throw new Error("Actual is not a Function");
  2208          }
  2209  
  2210          try {
  2211            actual();
  2212          } catch (e) {
  2213            threw = true;
  2214            thrown = e;
  2215          }
  2216  
  2217          if (!threw) {
  2218            result.message = "Expected function to throw an exception.";
  2219            return result;
  2220          }
  2221  
  2222          if (arguments.length == 1) {
  2223            result.pass = true;
  2224            result.message = "Expected function not to throw, but it threw " + j$.pp(thrown) + ".";
  2225  
  2226            return result;
  2227          }
  2228  
  2229          if (util.equals(thrown, expected)) {
  2230            result.pass = true;
  2231            result.message = "Expected function not to throw " + j$.pp(expected) + ".";
  2232          } else {
  2233            result.message = "Expected function to throw " + j$.pp(expected) + ", but it threw " +  j$.pp(thrown) + ".";
  2234          }
  2235  
  2236          return result;
  2237        }
  2238      };
  2239    }
  2240  
  2241    return toThrow;
  2242  };
  2243  
  2244  getJasmineRequireObj().toThrowError = function(j$) {
  2245    function toThrowError (util) {
  2246      return {
  2247        compare: function(actual) {
  2248          var threw = false,
  2249            thrown,
  2250            errorType,
  2251            message,
  2252            regexp,
  2253            name,
  2254            constructorName;
  2255  
  2256          if (typeof actual != "function") {
  2257            throw new Error("Actual is not a Function");
  2258          }
  2259  
  2260          extractExpectedParams.apply(null, arguments);
  2261  
  2262          try {
  2263            actual();
  2264          } catch (e) {
  2265            threw = true;
  2266            thrown = e;
  2267          }
  2268  
  2269          if (!threw) {
  2270            return fail("Expected function to throw an Error.");
  2271          }
  2272  
  2273          if (!(thrown instanceof Error)) {
  2274            return fail("Expected function to throw an Error, but it threw " + thrown + ".");
  2275          }
  2276  
  2277          if (arguments.length == 1) {
  2278            return pass("Expected function not to throw an Error, but it threw " + fnNameFor(thrown) + ".");
  2279          }
  2280  
  2281          if (errorType) {
  2282            name = fnNameFor(errorType);
  2283            constructorName = fnNameFor(thrown.constructor);
  2284          }
  2285  
  2286          if (errorType && message) {
  2287            if (thrown.constructor == errorType && util.equals(thrown.message, message)) {
  2288              return pass("Expected function not to throw " + name + " with message \"" + message + "\".");
  2289            } else {
  2290              return fail("Expected function to throw " + name + " with message \"" + message +
  2291                          "\", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
  2292            }
  2293          }
  2294  
  2295          if (errorType && regexp) {
  2296            if (thrown.constructor == errorType && regexp.test(thrown.message)) {
  2297              return pass("Expected function not to throw " + name + " with message matching " + regexp + ".");
  2298            } else {
  2299              return fail("Expected function to throw " + name + " with message matching " + regexp +
  2300                          ", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
  2301            }
  2302          }
  2303  
  2304          if (errorType) {
  2305            if (thrown.constructor == errorType) {
  2306              return pass("Expected function not to throw " + name + ".");
  2307            } else {
  2308              return fail("Expected function to throw " + name + ", but it threw " + constructorName + ".");
  2309            }
  2310          }
  2311  
  2312          if (message) {
  2313            if (thrown.message == message) {
  2314              return pass("Expected function not to throw an exception with message " + j$.pp(message) + ".");
  2315            } else {
  2316              return fail("Expected function to throw an exception with message " + j$.pp(message) +
  2317                          ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
  2318            }
  2319          }
  2320  
  2321          if (regexp) {
  2322            if (regexp.test(thrown.message)) {
  2323              return pass("Expected function not to throw an exception with a message matching " + j$.pp(regexp) + ".");
  2324            } else {
  2325              return fail("Expected function to throw an exception with a message matching " + j$.pp(regexp) +
  2326                          ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
  2327            }
  2328          }
  2329  
  2330          function fnNameFor(func) {
  2331              return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
  2332          }
  2333  
  2334          function pass(notMessage) {
  2335            return {
  2336              pass: true,
  2337              message: notMessage
  2338            };
  2339          }
  2340  
  2341          function fail(message) {
  2342            return {
  2343              pass: false,
  2344              message: message
  2345            };
  2346          }
  2347  
  2348          function extractExpectedParams() {
  2349            if (arguments.length == 1) {
  2350              return;
  2351            }
  2352  
  2353            if (arguments.length == 2) {
  2354              var expected = arguments[1];
  2355  
  2356              if (expected instanceof RegExp) {
  2357                regexp = expected;
  2358              } else if (typeof expected == "string") {
  2359                message = expected;
  2360              } else if (checkForAnErrorType(expected)) {
  2361                errorType = expected;
  2362              }
  2363  
  2364              if (!(errorType || message || regexp)) {
  2365                throw new Error("Expected is not an Error, string, or RegExp.");
  2366              }
  2367            } else {
  2368              if (checkForAnErrorType(arguments[1])) {
  2369                errorType = arguments[1];
  2370              } else {
  2371                throw new Error("Expected error type is not an Error.");
  2372              }
  2373  
  2374              if (arguments[2] instanceof RegExp) {
  2375                regexp = arguments[2];
  2376              } else if (typeof arguments[2] == "string") {
  2377                message = arguments[2];
  2378              } else {
  2379                throw new Error("Expected error message is not a string or RegExp.");
  2380              }
  2381            }
  2382          }
  2383  
  2384          function checkForAnErrorType(type) {
  2385            if (typeof type !== "function") {
  2386              return false;
  2387            }
  2388  
  2389            var Surrogate = function() {};
  2390            Surrogate.prototype = type.prototype;
  2391            return (new Surrogate()) instanceof Error;
  2392          }
  2393        }
  2394      };
  2395    }
  2396  
  2397    return toThrowError;
  2398  };
  2399  
  2400  getJasmineRequireObj().version = function() {
  2401    return "2.0.0";
  2402  };