BVB Source Codes

mobile-chrome-apps Show jasmine.js Source code

Return Download mobile-chrome-apps: download jasmine.js Source code - Download mobile-chrome-apps Source code - Type:.js
  1. var isCommonJS = typeof window == "undefined" && typeof exports == "object";
  2.  
  3. /**
  4.  * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
  5.  *
  6.  * @namespace
  7.  */
  8. var jasmine = {};
  9. if (isCommonJS) exports.jasmine = jasmine;
  10. /**
  11.  * @private
  12.  */
  13. jasmine.unimplementedMethod_ = function() {
  14.   throw new Error("unimplemented method");
  15. };
  16.  
  17. /**
  18.  * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
  19.  * a plain old variable and may be redefined by somebody else.
  20.  *
  21.  * @private
  22.  */
  23. jasmine.undefined = jasmine.___undefined___;
  24.  
  25. /**
  26.  * Show diagnostic messages in the console if set to true
  27.  *
  28.  */
  29. jasmine.VERBOSE = false;
  30.  
  31. /**
  32.  * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
  33.  *
  34.  */
  35. jasmine.DEFAULT_UPDATE_INTERVAL = 250;
  36.  
  37. /**
  38.  * Maximum levels of nesting that will be included when an object is pretty-printed
  39.  */
  40. jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
  41.  
  42. /**
  43.  * Default timeout interval in milliseconds for waitsFor() blocks.
  44.  */
  45. jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
  46.  
  47. /**
  48.  * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
  49.  * Set to false to let the exception bubble up in the browser.
  50.  *
  51.  */
  52. jasmine.CATCH_EXCEPTIONS = true;
  53.  
  54. jasmine.getGlobal = function() {
  55.   function getGlobal() {
  56.     return this;
  57.   }
  58.  
  59.   return getGlobal();
  60. };
  61.  
  62. /**
  63.  * Allows for bound functions to be compared.  Internal use only.
  64.  *
  65.  * @ignore
  66.  * @private
  67.  * @param base {Object} bound 'this' for the function
  68.  * @param name {Function} function to find
  69.  */
  70. jasmine.bindOriginal_ = function(base, name) {
  71.   var original = base[name];
  72.   if (original.apply) {
  73.     return function() {
  74.       return original.apply(base, arguments);
  75.     };
  76.   } else {
  77.     // IE support
  78.     return jasmine.getGlobal()[name];
  79.   }
  80. };
  81.  
  82. jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
  83. jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
  84. jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
  85. jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
  86.  
  87. jasmine.MessageResult = function(values) {
  88.   this.type = 'log';
  89.   this.values = values;
  90.   this.trace = new Error(); // todo: test better
  91. };
  92.  
  93. jasmine.MessageResult.prototype.toString = function() {
  94.   var text = "";
  95.   for (var i = 0; i < this.values.length; i++) {
  96.     if (i > 0) text += " ";
  97.     if (jasmine.isString_(this.values[i])) {
  98.       text += this.values[i];
  99.     } else {
  100.       text += jasmine.pp(this.values[i]);
  101.     }
  102.   }
  103.   return text;
  104. };
  105.  
  106. jasmine.ExpectationResult = function(params) {
  107.   this.type = 'expect';
  108.   this.matcherName = params.matcherName;
  109.   this.passed_ = params.passed;
  110.   this.expected = params.expected;
  111.   this.actual = params.actual;
  112.   this.message = this.passed_ ? 'Passed.' : params.message;
  113.  
  114.   var trace = (params.trace || new Error(this.message));
  115.   this.trace = this.passed_ ? '' : trace;
  116. };
  117.  
  118. jasmine.ExpectationResult.prototype.toString = function () {
  119.   return this.message;
  120. };
  121.  
  122. jasmine.ExpectationResult.prototype.passed = function () {
  123.   return this.passed_;
  124. };
  125.  
  126. /**
  127.  * Getter for the Jasmine environment. Ensures one gets created
  128.  */
  129. jasmine.getEnv = function() {
  130.   var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
  131.   return env;
  132. };
  133.  
  134. /**
  135.  * @ignore
  136.  * @private
  137.  * @param value
  138.  * @returns {Boolean}
  139.  */
  140. jasmine.isArray_ = function(value) {
  141.   return jasmine.isA_("Array", value);
  142. };
  143.  
  144. /**
  145.  * @ignore
  146.  * @private
  147.  * @param value
  148.  * @returns {Boolean}
  149.  */
  150. jasmine.isString_ = function(value) {
  151.   return jasmine.isA_("String", value);
  152. };
  153.  
  154. /**
  155.  * @ignore
  156.  * @private
  157.  * @param value
  158.  * @returns {Boolean}
  159.  */
  160. jasmine.isNumber_ = function(value) {
  161.   return jasmine.isA_("Number", value);
  162. };
  163.  
  164. /**
  165.  * @ignore
  166.  * @private
  167.  * @param {String} typeName
  168.  * @param value
  169.  * @returns {Boolean}
  170.  */
  171. jasmine.isA_ = function(typeName, value) {
  172.   return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
  173. };
  174.  
  175. /**
  176.  * Pretty printer for expecations.  Takes any object and turns it into a human-readable string.
  177.  *
  178.  * @param value {Object} an object to be outputted
  179.  * @returns {String}
  180.  */
  181. jasmine.pp = function(value) {
  182.   var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
  183.   stringPrettyPrinter.format(value);
  184.   return stringPrettyPrinter.string;
  185. };
  186.  
  187. /**
  188.  * Returns true if the object is a DOM Node.
  189.  *
  190.  * @param {Object} obj object to check
  191.  * @returns {Boolean}
  192.  */
  193. jasmine.isDomNode = function(obj) {
  194.   return obj.nodeType > 0;
  195. };
  196.  
  197. /**
  198.  * Returns a matchable 'generic' object of the class type.  For use in expecations of type when values don't matter.
  199.  *
  200.  * @example
  201.  * // don't care about which function is passed in, as long as it's a function
  202.  * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
  203.  *
  204.  * @param {Class} clazz
  205.  * @returns matchable object of the type clazz
  206.  */
  207. jasmine.any = function(clazz) {
  208.   return new jasmine.Matchers.Any(clazz);
  209. };
  210.  
  211. /**
  212.  * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
  213.  * attributes on the object.
  214.  *
  215.  * @example
  216.  * // don't care about any other attributes than foo.
  217.  * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
  218.  *
  219.  * @param sample {Object} sample
  220.  * @returns matchable object for the sample
  221.  */
  222. jasmine.objectContaining = function (sample) {
  223.     return new jasmine.Matchers.ObjectContaining(sample);
  224. };
  225.  
  226. /**
  227.  * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
  228.  *
  229.  * Spies should be created in test setup, before expectations.  They can then be checked, using the standard Jasmine
  230.  * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
  231.  *
  232.  * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
  233.  *
  234.  * Spies are torn down at the end of every spec.
  235.  *
  236.  * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
  237.  *
  238.  * @example
  239.  * // a stub
  240.  * var myStub = jasmine.createSpy('myStub');  // can be used anywhere
  241.  *
  242.  * // spy example
  243.  * var foo = {
  244.  *   not: function(bool) { return !bool; }
  245.  * }
  246.  *
  247.  * // actual foo.not will not be called, execution stops
  248.  * spyOn(foo, 'not');
  249.  
  250.  // foo.not spied upon, execution will continue to implementation
  251.  * spyOn(foo, 'not').andCallThrough();
  252.  *
  253.  * // fake example
  254.  * var foo = {
  255.  *   not: function(bool) { return !bool; }
  256.  * }
  257.  *
  258.  * // foo.not(val) will return val
  259.  * spyOn(foo, 'not').andCallFake(function(value) {return value;});
  260.  *
  261.  * // mock example
  262.  * foo.not(7 == 7);
  263.  * expect(foo.not).toHaveBeenCalled();
  264.  * expect(foo.not).toHaveBeenCalledWith(true);
  265.  *
  266.  * @constructor
  267.  * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
  268.  * @param {String} name
  269.  */
  270. jasmine.Spy = function(name) {
  271.   /**
  272.    * The name of the spy, if provided.
  273.    */
  274.   this.identity = name || 'unknown';
  275.   /**
  276.    *  Is this Object a spy?
  277.    */
  278.   this.isSpy = true;
  279.   /**
  280.    * The actual function this spy stubs.
  281.    */
  282.   this.plan = function() {
  283.   };
  284.   /**
  285.    * Tracking of the most recent call to the spy.
  286.    * @example
  287.    * var mySpy = jasmine.createSpy('foo');
  288.    * mySpy(1, 2);
  289.    * mySpy.mostRecentCall.args = [1, 2];
  290.    */
  291.   this.mostRecentCall = {};
  292.  
  293.   /**
  294.    * Holds arguments for each call to the spy, indexed by call count
  295.    * @example
  296.    * var mySpy = jasmine.createSpy('foo');
  297.    * mySpy(1, 2);
  298.    * mySpy(7, 8);
  299.    * mySpy.mostRecentCall.args = [7, 8];
  300.    * mySpy.argsForCall[0] = [1, 2];
  301.    * mySpy.argsForCall[1] = [7, 8];
  302.    */
  303.   this.argsForCall = [];
  304.   this.calls = [];
  305. };
  306.  
  307. /**
  308.  * Tells a spy to call through to the actual implemenatation.
  309.  *
  310.  * @example
  311.  * var foo = {
  312.  *   bar: function() { // do some stuff }
  313.  * }
  314.  *
  315.  * // defining a spy on an existing property: foo.bar
  316.  * spyOn(foo, 'bar').andCallThrough();
  317.  */
  318. jasmine.Spy.prototype.andCallThrough = function() {
  319.   this.plan = this.originalValue;
  320.   return this;
  321. };
  322.  
  323. /**
  324.  * For setting the return value of a spy.
  325.  *
  326.  * @example
  327.  * // defining a spy from scratch: foo() returns 'baz'
  328.  * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
  329.  *
  330.  * // defining a spy on an existing property: foo.bar() returns 'baz'
  331.  * spyOn(foo, 'bar').andReturn('baz');
  332.  *
  333.  * @param {Object} value
  334.  */
  335. jasmine.Spy.prototype.andReturn = function(value) {
  336.   this.plan = function() {
  337.     return value;
  338.   };
  339.   return this;
  340. };
  341.  
  342. /**
  343.  * For throwing an exception when a spy is called.
  344.  *
  345.  * @example
  346.  * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
  347.  * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
  348.  *
  349.  * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
  350.  * spyOn(foo, 'bar').andThrow('baz');
  351.  *
  352.  * @param {String} exceptionMsg
  353.  */
  354. jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
  355.   this.plan = function() {
  356.     throw exceptionMsg;
  357.   };
  358.   return this;
  359. };
  360.  
  361. /**
  362.  * Calls an alternate implementation when a spy is called.
  363.  *
  364.  * @example
  365.  * var baz = function() {
  366.  *   // do some stuff, return something
  367.  * }
  368.  * // defining a spy from scratch: foo() calls the function baz
  369.  * var foo = jasmine.createSpy('spy on foo').andCall(baz);
  370.  *
  371.  * // defining a spy on an existing property: foo.bar() calls an anonymnous function
  372.  * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
  373.  *
  374.  * @param {Function} fakeFunc
  375.  */
  376. jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
  377.   this.plan = fakeFunc;
  378.   return this;
  379. };
  380.  
  381. /**
  382.  * Resets all of a spy's the tracking variables so that it can be used again.
  383.  *
  384.  * @example
  385.  * spyOn(foo, 'bar');
  386.  *
  387.  * foo.bar();
  388.  *
  389.  * expect(foo.bar.callCount).toEqual(1);
  390.  *
  391.  * foo.bar.reset();
  392.  *
  393.  * expect(foo.bar.callCount).toEqual(0);
  394.  */
  395. jasmine.Spy.prototype.reset = function() {
  396.   this.wasCalled = false;
  397.   this.callCount = 0;
  398.   this.argsForCall = [];
  399.   this.calls = [];
  400.   this.mostRecentCall = {};
  401. };
  402.  
  403. jasmine.createSpy = function(name) {
  404.  
  405.   var spyObj = function() {
  406.     spyObj.wasCalled = true;
  407.     spyObj.callCount++;
  408.     var args = jasmine.util.argsToArray(arguments);
  409.     spyObj.mostRecentCall.object = this;
  410.     spyObj.mostRecentCall.args = args;
  411.     spyObj.argsForCall.push(args);
  412.     spyObj.calls.push({object: this, args: args});
  413.     return spyObj.plan.apply(this, arguments);
  414.   };
  415.  
  416.   var spy = new jasmine.Spy(name);
  417.  
  418.   for (var prop in spy) {
  419.     spyObj[prop] = spy[prop];
  420.   }
  421.  
  422.   spyObj.reset();
  423.  
  424.   return spyObj;
  425. };
  426.  
  427. /**
  428.  * Determines whether an object is a spy.
  429.  *
  430.  * @param {jasmine.Spy|Object} putativeSpy
  431.  * @returns {Boolean}
  432.  */
  433. jasmine.isSpy = function(putativeSpy) {
  434.   return putativeSpy && putativeSpy.isSpy;
  435. };
  436.  
  437. /**
  438.  * Creates a more complicated spy: an Object that has every property a function that is a spy.  Used for stubbing something
  439.  * large in one call.
  440.  *
  441.  * @param {String} baseName name of spy class
  442.  * @param {Array} methodNames array of names of methods to make spies
  443.  */
  444. jasmine.createSpyObj = function(baseName, methodNames) {
  445.   if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
  446.     throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
  447.   }
  448.   var obj = {};
  449.   for (var i = 0; i < methodNames.length; i++) {
  450.     obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
  451.   }
  452.   return obj;
  453. };
  454.  
  455. /**
  456.  * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
  457.  *
  458.  * Be careful not to leave calls to <code>jasmine.log</code> in production code.
  459.  */
  460. jasmine.log = function() {
  461.   var spec = jasmine.getEnv().currentSpec;
  462.   spec.log.apply(spec, arguments);
  463. };
  464.  
  465. /**
  466.  * Function that installs a spy on an existing object's method name.  Used within a Spec to create a spy.
  467.  *
  468.  * @example
  469.  * // spy example
  470.  * var foo = {
  471.  *   not: function(bool) { return !bool; }
  472.  * }
  473.  * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
  474.  *
  475.  * @see jasmine.createSpy
  476.  * @param obj
  477.  * @param methodName
  478.  * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
  479.  */
  480. var spyOn = function(obj, methodName) {
  481.   return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
  482. };
  483. if (isCommonJS) exports.spyOn = spyOn;
  484.  
  485. /**
  486.  * Creates a Jasmine spec that will be added to the current suite.
  487.  *
  488.  * // TODO: pending tests
  489.  *
  490.  * @example
  491.  * it('should be true', function() {
  492.  *   expect(true).toEqual(true);
  493.  * });
  494.  *
  495.  * @param {String} desc description of this specification
  496.  * @param {Function} func defines the preconditions and expectations of the spec
  497.  */
  498. var it = function(desc, func) {
  499.   return jasmine.getEnv().it(desc, func);
  500. };
  501. if (isCommonJS) exports.it = it;
  502.  
  503. /**
  504.  * Creates a <em>disabled</em> Jasmine spec.
  505.  *
  506.  * A convenience method that allows existing specs to be disabled temporarily during development.
  507.  *
  508.  * @param {String} desc description of this specification
  509.  * @param {Function} func defines the preconditions and expectations of the spec
  510.  */
  511. var xit = function(desc, func) {
  512.   return jasmine.getEnv().xit(desc, func);
  513. };
  514. if (isCommonJS) exports.xit = xit;
  515.  
  516. /**
  517.  * Starts a chain for a Jasmine expectation.
  518.  *
  519.  * It is passed an Object that is the actual value and should chain to one of the many
  520.  * jasmine.Matchers functions.
  521.  *
  522.  * @param {Object} actual Actual value to test against and expected value
  523.  * @return {jasmine.Matchers}
  524.  */
  525. var expect = function(actual) {
  526.   return jasmine.getEnv().currentSpec.expect(actual);
  527. };
  528. if (isCommonJS) exports.expect = expect;
  529.  
  530. /**
  531.  * Defines part of a jasmine spec.  Used in cominbination with waits or waitsFor in asynchrnous specs.
  532.  *
  533.  * @param {Function} func Function that defines part of a jasmine spec.
  534.  */
  535. var runs = function(func) {
  536.   jasmine.getEnv().currentSpec.runs(func);
  537. };
  538. if (isCommonJS) exports.runs = runs;
  539.  
  540. /**
  541.  * Waits a fixed time period before moving to the next block.
  542.  *
  543.  * @deprecated Use waitsFor() instead
  544.  * @param {Number} timeout milliseconds to wait
  545.  */
  546. var waits = function(timeout) {
  547.   jasmine.getEnv().currentSpec.waits(timeout);
  548. };
  549. if (isCommonJS) exports.waits = waits;
  550.  
  551. /**
  552.  * Waits for the latchFunction to return true before proceeding to the next block.
  553.  *
  554.  * @param {Function} latchFunction
  555.  * @param {String} optional_timeoutMessage
  556.  * @param {Number} optional_timeout
  557.  */
  558. var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
  559.   jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
  560. };
  561. if (isCommonJS) exports.waitsFor = waitsFor;
  562.  
  563. /**
  564.  * A function that is called before each spec in a suite.
  565.  *
  566.  * Used for spec setup, including validating assumptions.
  567.  *
  568.  * @param {Function} beforeEachFunction
  569.  */
  570. var beforeEach = function(beforeEachFunction) {
  571.   jasmine.getEnv().beforeEach(beforeEachFunction);
  572. };
  573. if (isCommonJS) exports.beforeEach = beforeEach;
  574.  
  575. /**
  576.  * A function that is called after each spec in a suite.
  577.  *
  578.  * Used for restoring any state that is hijacked during spec execution.
  579.  *
  580.  * @param {Function} afterEachFunction
  581.  */
  582. var afterEach = function(afterEachFunction) {
  583.   jasmine.getEnv().afterEach(afterEachFunction);
  584. };
  585. if (isCommonJS) exports.afterEach = afterEach;
  586.  
  587. /**
  588.  * Defines a suite of specifications.
  589.  *
  590.  * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
  591.  * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
  592.  * of setup in some tests.
  593.  *
  594.  * @example
  595.  * // TODO: a simple suite
  596.  *
  597.  * // TODO: a simple suite with a nested describe block
  598.  *
  599.  * @param {String} description A string, usually the class under test.
  600.  * @param {Function} specDefinitions function that defines several specs.
  601.  */
  602. var describe = function(description, specDefinitions) {
  603.   return jasmine.getEnv().describe(description, specDefinitions);
  604. };
  605. if (isCommonJS) exports.describe = describe;
  606.  
  607. /**
  608.  * Disables a suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.
  609.  *
  610.  * @param {String} description A string, usually the class under test.
  611.  * @param {Function} specDefinitions function that defines several specs.
  612.  */
  613. var xdescribe = function(description, specDefinitions) {
  614.   return jasmine.getEnv().xdescribe(description, specDefinitions);
  615. };
  616. if (isCommonJS) exports.xdescribe = xdescribe;
  617.  
  618.  
  619. // Provide the XMLHttpRequest class for IE 5.x-6.x:
  620. jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
  621.   function tryIt(f) {
  622.     try {
  623.       return f();
  624.     } catch(e) {
  625.     }
  626.     return null;
  627.   }
  628.  
  629.   var xhr = tryIt(function() {
  630.     return new ActiveXObject("Msxml2.XMLHTTP.6.0");
  631.   }) ||
  632.     tryIt(function() {
  633.       return new ActiveXObject("Msxml2.XMLHTTP.3.0");
  634.     }) ||
  635.     tryIt(function() {
  636.       return new ActiveXObject("Msxml2.XMLHTTP");
  637.     }) ||
  638.     tryIt(function() {
  639.       return new ActiveXObject("Microsoft.XMLHTTP");
  640.     });
  641.  
  642.   if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
  643.  
  644.   return xhr;
  645. } : XMLHttpRequest;
  646. /**
  647.  * @namespace
  648.  */
  649. jasmine.util = {};
  650.  
  651. /**
  652.  * Declare that a child class inherit it's prototype from the parent class.
  653.  *
  654.  * @private
  655.  * @param {Function} childClass
  656.  * @param {Function} parentClass
  657.  */
  658. jasmine.util.inherit = function(childClass, parentClass) {
  659.   /**
  660.    * @private
  661.    */
  662.   var subclass = function() {
  663.   };
  664.   subclass.prototype = parentClass.prototype;
  665.   childClass.prototype = new subclass();
  666. };
  667.  
  668. jasmine.util.formatException = function(e) {
  669.   var lineNumber;
  670.   if (e.line) {
  671.     lineNumber = e.line;
  672.   }
  673.   else if (e.lineNumber) {
  674.     lineNumber = e.lineNumber;
  675.   }
  676.  
  677.   var file;
  678.  
  679.   if (e.sourceURL) {
  680.     file = e.sourceURL;
  681.   }
  682.   else if (e.fileName) {
  683.     file = e.fileName;
  684.   }
  685.  
  686.   var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
  687.  
  688.   if (file && lineNumber) {
  689.     message += ' in ' + file + ' (line ' + lineNumber + ')';
  690.   }
  691.  
  692.   return message;
  693. };
  694.  
  695. jasmine.util.htmlEscape = function(str) {
  696.   if (!str) return str;
  697.   return str.replace(/&/g, '&amp;')
  698.     .replace(/</g, '&lt;')
  699.     .replace(/>/g, '&gt;');
  700. };
  701.  
  702. jasmine.util.argsToArray = function(args) {
  703.   var arrayOfArgs = [];
  704.   for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
  705.   return arrayOfArgs;
  706. };
  707.  
  708. jasmine.util.extend = function(destination, source) {
  709.   for (var property in source) destination[property] = source[property];
  710.   return destination;
  711. };
  712.  
  713. /**
  714.  * Environment for Jasmine
  715.  *
  716.  * @constructor
  717.  */
  718. jasmine.Env = function() {
  719.   this.currentSpec = null;
  720.   this.currentSuite = null;
  721.   this.currentRunner_ = new jasmine.Runner(this);
  722.  
  723.   this.reporter = new jasmine.MultiReporter();
  724.  
  725.   this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
  726.   this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
  727.   this.lastUpdate = 0;
  728.   this.specFilter = function() {
  729.     return true;
  730.   };
  731.  
  732.   this.nextSpecId_ = 0;
  733.   this.nextSuiteId_ = 0;
  734.   this.equalityTesters_ = [];
  735.  
  736.   // wrap matchers
  737.   this.matchersClass = function() {
  738.     jasmine.Matchers.apply(this, arguments);
  739.   };
  740.   jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
  741.  
  742.   jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
  743. };
  744.  
  745.  
  746. jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
  747. jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
  748. jasmine.Env.prototype.setInterval = jasmine.setInterval;
  749. jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
  750.  
  751. /**
  752.  * @returns an object containing jasmine version build info, if set.
  753.  */
  754. jasmine.Env.prototype.version = function () {
  755.   if (jasmine.version_) {
  756.     return jasmine.version_;
  757.   } else {
  758.     throw new Error('Version not set');
  759.   }
  760. };
  761.  
  762. /**
  763.  * @returns string containing jasmine version build info, if set.
  764.  */
  765. jasmine.Env.prototype.versionString = function() {
  766.   if (!jasmine.version_) {
  767.     return "version unknown";
  768.   }
  769.  
  770.   var version = this.version();
  771.   var versionString = version.major + "." + version.minor + "." + version.build;
  772.   if (version.release_candidate) {
  773.     versionString += ".rc" + version.release_candidate;
  774.   }
  775.   versionString += " revision " + version.revision;
  776.   return versionString;
  777. };
  778.  
  779. /**
  780.  * @returns a sequential integer starting at 0
  781.  */
  782. jasmine.Env.prototype.nextSpecId = function () {
  783.   return this.nextSpecId_++;
  784. };
  785.  
  786. /**
  787.  * @returns a sequential integer starting at 0
  788.  */
  789. jasmine.Env.prototype.nextSuiteId = function () {
  790.   return this.nextSuiteId_++;
  791. };
  792.  
  793. /**
  794.  * Register a reporter to receive status updates from Jasmine.
  795.  * @param {jasmine.Reporter} reporter An object which will receive status updates.
  796.  */
  797. jasmine.Env.prototype.addReporter = function(reporter) {
  798.   this.reporter.addReporter(reporter);
  799. };
  800.  
  801. jasmine.Env.prototype.execute = function() {
  802.   this.currentRunner_.execute();
  803. };
  804.  
  805. jasmine.Env.prototype.describe = function(description, specDefinitions) {
  806.   var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
  807.  
  808.   var parentSuite = this.currentSuite;
  809.   if (parentSuite) {
  810.     parentSuite.add(suite);
  811.   } else {
  812.     this.currentRunner_.add(suite);
  813.   }
  814.  
  815.   this.currentSuite = suite;
  816.  
  817.   var declarationError = null;
  818.   try {
  819.     specDefinitions.call(suite);
  820.   } catch(e) {
  821.     declarationError = e;
  822.   }
  823.  
  824.   if (declarationError) {
  825.     this.it("encountered a declaration exception", function() {
  826.       throw declarationError;
  827.     });
  828.   }
  829.  
  830.   this.currentSuite = parentSuite;
  831.  
  832.   return suite;
  833. };
  834.  
  835. jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
  836.   if (this.currentSuite) {
  837.     this.currentSuite.beforeEach(beforeEachFunction);
  838.   } else {
  839.     this.currentRunner_.beforeEach(beforeEachFunction);
  840.   }
  841. };
  842.  
  843. jasmine.Env.prototype.currentRunner = function () {
  844.   return this.currentRunner_;
  845. };
  846.  
  847. jasmine.Env.prototype.afterEach = function(afterEachFunction) {
  848.   if (this.currentSuite) {
  849.     this.currentSuite.afterEach(afterEachFunction);
  850.   } else {
  851.     this.currentRunner_.afterEach(afterEachFunction);
  852.   }
  853.  
  854. };
  855.  
  856. jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
  857.   return {
  858.     execute: function() {
  859.     }
  860.   };
  861. };
  862.  
  863. jasmine.Env.prototype.it = function(description, func) {
  864.   var spec = new jasmine.Spec(this, this.currentSuite, description);
  865.   this.currentSuite.add(spec);
  866.   this.currentSpec = spec;
  867.  
  868.   if (func) {
  869.     spec.runs(func);
  870.   }
  871.  
  872.   return spec;
  873. };
  874.  
  875. jasmine.Env.prototype.xit = function(desc, func) {
  876.   return {
  877.     id: this.nextSpecId(),
  878.     runs: function() {
  879.     }
  880.   };
  881. };
  882.  
  883. jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
  884.   if (a.source != b.source)
  885.     mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
  886.  
  887.   if (a.ignoreCase != b.ignoreCase)
  888.     mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
  889.  
  890.   if (a.global != b.global)
  891.     mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
  892.  
  893.   if (a.multiline != b.multiline)
  894.     mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
  895.  
  896.   if (a.sticky != b.sticky)
  897.     mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
  898.  
  899.   return (mismatchValues.length === 0);
  900. };
  901.  
  902. jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
  903.   if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
  904.     return true;
  905.   }
  906.  
  907.   a.__Jasmine_been_here_before__ = b;
  908.   b.__Jasmine_been_here_before__ = a;
  909.  
  910.   var hasKey = function(obj, keyName) {
  911.     return obj !== null && obj[keyName] !== jasmine.undefined;
  912.   };
  913.  
  914.   for (var property in b) {
  915.     if (!hasKey(a, property) && hasKey(b, property)) {
  916.       mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
  917.     }
  918.   }
  919.   for (property in a) {
  920.     if (!hasKey(b, property) && hasKey(a, property)) {
  921.       mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
  922.     }
  923.   }
  924.   for (property in b) {
  925.     if (property == '__Jasmine_been_here_before__') continue;
  926.     if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
  927.       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.");
  928.     }
  929.   }
  930.  
  931.   if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
  932.     mismatchValues.push("arrays were not the same length");
  933.   }
  934.  
  935.   delete a.__Jasmine_been_here_before__;
  936.   delete b.__Jasmine_been_here_before__;
  937.   return (mismatchKeys.length === 0 && mismatchValues.length === 0);
  938. };
  939.  
  940. jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
  941.   mismatchKeys = mismatchKeys || [];
  942.   mismatchValues = mismatchValues || [];
  943.  
  944.   for (var i = 0; i < this.equalityTesters_.length; i++) {
  945.     var equalityTester = this.equalityTesters_[i];
  946.     var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
  947.     if (result !== jasmine.undefined) return result;
  948.   }
  949.  
  950.   if (a === b) return true;
  951.  
  952.   if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
  953.     return (a == jasmine.undefined && b == jasmine.undefined);
  954.   }
  955.  
  956.   if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
  957.     return a === b;
  958.   }
  959.  
  960.   if (a instanceof Date && b instanceof Date) {
  961.     return a.getTime() == b.getTime();
  962.   }
  963.  
  964.   if (a.jasmineMatches) {
  965.     return a.jasmineMatches(b);
  966.   }
  967.  
  968.   if (b.jasmineMatches) {
  969.     return b.jasmineMatches(a);
  970.   }
  971.  
  972.   if (a instanceof jasmine.Matchers.ObjectContaining) {
  973.     return a.matches(b);
  974.   }
  975.  
  976.   if (b instanceof jasmine.Matchers.ObjectContaining) {
  977.     return b.matches(a);
  978.   }
  979.  
  980.   if (jasmine.isString_(a) && jasmine.isString_(b)) {
  981.     return (a == b);
  982.   }
  983.  
  984.   if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
  985.     return (a == b);
  986.   }
  987.  
  988.   if (a instanceof RegExp && b instanceof RegExp) {
  989.     return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
  990.   }
  991.  
  992.   if (typeof a === "object" && typeof b === "object") {
  993.     return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
  994.   }
  995.  
  996.   //Straight check
  997.   return (a === b);
  998. };
  999.  
  1000. jasmine.Env.prototype.contains_ = function(haystack, needle) {
  1001.   if (jasmine.isArray_(haystack)) {
  1002.     for (var i = 0; i < haystack.length; i++) {
  1003.       if (this.equals_(haystack[i], needle)) return true;
  1004.     }
  1005.     return false;
  1006.   }
  1007.   return haystack.indexOf(needle) >= 0;
  1008. };
  1009.  
  1010. jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
  1011.   this.equalityTesters_.push(equalityTester);
  1012. };
  1013. /** No-op base class for Jasmine reporters.
  1014.  *
  1015.  * @constructor
  1016.  */
  1017. jasmine.Reporter = function() {
  1018. };
  1019.  
  1020. //noinspection JSUnusedLocalSymbols
  1021. jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
  1022. };
  1023.  
  1024. //noinspection JSUnusedLocalSymbols
  1025. jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
  1026. };
  1027.  
  1028. //noinspection JSUnusedLocalSymbols
  1029. jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
  1030. };
  1031.  
  1032. //noinspection JSUnusedLocalSymbols
  1033. jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
  1034. };
  1035.  
  1036. //noinspection JSUnusedLocalSymbols
  1037. jasmine.Reporter.prototype.reportSpecResults = function(spec) {
  1038. };
  1039.  
  1040. //noinspection JSUnusedLocalSymbols
  1041. jasmine.Reporter.prototype.log = function(str) {
  1042. };
  1043.  
  1044. /**
  1045.  * Blocks are functions with executable code that make up a spec.
  1046.  *
  1047.  * @constructor
  1048.  * @param {jasmine.Env} env
  1049.  * @param {Function} func
  1050.  * @param {jasmine.Spec} spec
  1051.  */
  1052. jasmine.Block = function(env, func, spec) {
  1053.   this.env = env;
  1054.   this.func = func;
  1055.   this.spec = spec;
  1056. };
  1057.  
  1058. jasmine.Block.prototype.execute = function(onComplete) {
  1059.   if (!jasmine.CATCH_EXCEPTIONS) {
  1060.     this.func.apply(this.spec);
  1061.   }
  1062.   else {
  1063.     try {
  1064.       this.func.apply(this.spec);
  1065.     } catch (e) {
  1066.       this.spec.fail(e);
  1067.     }
  1068.   }
  1069.   onComplete();
  1070. };
  1071. /** JavaScript API reporter.
  1072.  *
  1073.  * @constructor
  1074.  */
  1075. jasmine.JsApiReporter = function() {
  1076.   this.started = false;
  1077.   this.finished = false;
  1078.   this.suites_ = [];
  1079.   this.results_ = {};
  1080. };
  1081.  
  1082. jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
  1083.   this.started = true;
  1084.   var suites = runner.topLevelSuites();
  1085.   for (var i = 0; i < suites.length; i++) {
  1086.     var suite = suites[i];
  1087.     this.suites_.push(this.summarize_(suite));
  1088.   }
  1089. };
  1090.  
  1091. jasmine.JsApiReporter.prototype.suites = function() {
  1092.   return this.suites_;
  1093. };
  1094.  
  1095. jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
  1096.   var isSuite = suiteOrSpec instanceof jasmine.Suite;
  1097.   var summary = {
  1098.     id: suiteOrSpec.id,
  1099.     name: suiteOrSpec.description,
  1100.     type: isSuite ? 'suite' : 'spec',
  1101.     children: []
  1102.   };
  1103.  
  1104.   if (isSuite) {
  1105.     var children = suiteOrSpec.children();
  1106.     for (var i = 0; i < children.length; i++) {
  1107.       summary.children.push(this.summarize_(children[i]));
  1108.     }
  1109.   }
  1110.   return summary;
  1111. };
  1112.  
  1113. jasmine.JsApiReporter.prototype.results = function() {
  1114.   return this.results_;
  1115. };
  1116.  
  1117. jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
  1118.   return this.results_[specId];
  1119. };
  1120.  
  1121. //noinspection JSUnusedLocalSymbols
  1122. jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
  1123.   this.finished = true;
  1124. };
  1125.  
  1126. //noinspection JSUnusedLocalSymbols
  1127. jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
  1128. };
  1129.  
  1130. //noinspection JSUnusedLocalSymbols
  1131. jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
  1132.   this.results_[spec.id] = {
  1133.     messages: spec.results().getItems(),
  1134.     result: spec.results().failedCount > 0 ? "failed" : "passed"
  1135.   };
  1136. };
  1137.  
  1138. //noinspection JSUnusedLocalSymbols
  1139. jasmine.JsApiReporter.prototype.log = function(str) {
  1140. };
  1141.  
  1142. jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
  1143.   var results = {};
  1144.   for (var i = 0; i < specIds.length; i++) {
  1145.     var specId = specIds[i];
  1146.     results[specId] = this.summarizeResult_(this.results_[specId]);
  1147.   }
  1148.   return results;
  1149. };
  1150.  
  1151. jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
  1152.   var summaryMessages = [];
  1153.   var messagesLength = result.messages.length;
  1154.   for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
  1155.     var resultMessage = result.messages[messageIndex];
  1156.     summaryMessages.push({
  1157.       text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
  1158.       passed: resultMessage.passed ? resultMessage.passed() : true,
  1159.       type: resultMessage.type,
  1160.       message: resultMessage.message,
  1161.       trace: {
  1162.         stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
  1163.       }
  1164.     });
  1165.   }
  1166.  
  1167.   return {
  1168.     result : result.result,
  1169.     messages : summaryMessages
  1170.   };
  1171. };
  1172.  
  1173. /**
  1174.  * @constructor
  1175.  * @param {jasmine.Env} env
  1176.  * @param actual
  1177.  * @param {jasmine.Spec} spec
  1178.  */
  1179. jasmine.Matchers = function(env, actual, spec, opt_isNot) {
  1180.   this.env = env;
  1181.   this.actual = actual;
  1182.   this.spec = spec;
  1183.   this.isNot = opt_isNot || false;
  1184.   this.reportWasCalled_ = false;
  1185. };
  1186.  
  1187. // todo: @deprecated as of Jasmine 0.11, remove soon [xw]
  1188. jasmine.Matchers.pp = function(str) {
  1189.   throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
  1190. };
  1191.  
  1192. // todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
  1193. jasmine.Matchers.prototype.report = function(result, failing_message, details) {
  1194.   throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
  1195. };
  1196.  
  1197. jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
  1198.   for (var methodName in prototype) {
  1199.     if (methodName == 'report') continue;
  1200.     var orig = prototype[methodName];
  1201.     matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
  1202.   }
  1203. };
  1204.  
  1205. jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
  1206.   return function() {
  1207.     var matcherArgs = jasmine.util.argsToArray(arguments);
  1208.     var result = matcherFunction.apply(this, arguments);
  1209.  
  1210.     if (this.isNot) {
  1211.       result = !result;
  1212.     }
  1213.  
  1214.     if (this.reportWasCalled_) return result;
  1215.  
  1216.     var message;
  1217.     if (!result) {
  1218.       if (this.message) {
  1219.         message = this.message.apply(this, arguments);
  1220.         if (jasmine.isArray_(message)) {
  1221.           message = message[this.isNot ? 1 : 0];
  1222.         }
  1223.       } else {
  1224.         var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
  1225.         message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
  1226.         if (matcherArgs.length > 0) {
  1227.           for (var i = 0; i < matcherArgs.length; i++) {
  1228.             if (i > 0) message += ",";
  1229.             message += " " + jasmine.pp(matcherArgs[i]);
  1230.           }
  1231.         }
  1232.         message += ".";
  1233.       }
  1234.     }
  1235.     var expectationResult = new jasmine.ExpectationResult({
  1236.       matcherName: matcherName,
  1237.       passed: result,
  1238.       expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
  1239.       actual: this.actual,
  1240.       message: message
  1241.     });
  1242.     this.spec.addMatcherResult(expectationResult);
  1243.     return jasmine.undefined;
  1244.   };
  1245. };
  1246.  
  1247.  
  1248.  
  1249.  
  1250. /**
  1251.  * toBe: compares the actual to the expected using ===
  1252.  * @param expected
  1253.  */
  1254. jasmine.Matchers.prototype.toBe = function(expected) {
  1255.   return this.actual === expected;
  1256. };
  1257.  
  1258. /**
  1259.  * toNotBe: compares the actual to the expected using !==
  1260.  * @param expected
  1261.  * @deprecated as of 1.0. Use not.toBe() instead.
  1262.  */
  1263. jasmine.Matchers.prototype.toNotBe = function(expected) {
  1264.   return this.actual !== expected;
  1265. };
  1266.  
  1267. /**
  1268.  * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
  1269.  *
  1270.  * @param expected
  1271.  */
  1272. jasmine.Matchers.prototype.toEqual = function(expected) {
  1273.   return this.env.equals_(this.actual, expected);
  1274. };
  1275.  
  1276. /**
  1277.  * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
  1278.  * @param expected
  1279.  * @deprecated as of 1.0. Use not.toEqual() instead.
  1280.  */
  1281. jasmine.Matchers.prototype.toNotEqual = function(expected) {
  1282.   return !this.env.equals_(this.actual, expected);
  1283. };
  1284.  
  1285. /**
  1286.  * Matcher that compares the actual to the expected using a regular expression.  Constructs a RegExp, so takes
  1287.  * a pattern or a String.
  1288.  *
  1289.  * @param expected
  1290.  */
  1291. jasmine.Matchers.prototype.toMatch = function(expected) {
  1292.   return new RegExp(expected).test(this.actual);
  1293. };
  1294.  
  1295. /**
  1296.  * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
  1297.  * @param expected
  1298.  * @deprecated as of 1.0. Use not.toMatch() instead.
  1299.  */
  1300. jasmine.Matchers.prototype.toNotMatch = function(expected) {
  1301.   return !(new RegExp(expected).test(this.actual));
  1302. };
  1303.  
  1304. /**
  1305.  * Matcher that compares the actual to jasmine.undefined.
  1306.  */
  1307. jasmine.Matchers.prototype.toBeDefined = function() {
  1308.   return (this.actual !== jasmine.undefined);
  1309. };
  1310.  
  1311. /**
  1312.  * Matcher that compares the actual to jasmine.undefined.
  1313.  */
  1314. jasmine.Matchers.prototype.toBeUndefined = function() {
  1315.   return (this.actual === jasmine.undefined);
  1316. };
  1317.  
  1318. /**
  1319.  * Matcher that compares the actual to null.
  1320.  */
  1321. jasmine.Matchers.prototype.toBeNull = function() {
  1322.   return (this.actual === null);
  1323. };
  1324.  
  1325. /**
  1326.  * Matcher that compares the actual to NaN.
  1327.  */
  1328. jasmine.Matchers.prototype.toBeNaN = function() {
  1329.         this.message = function() {
  1330.                 return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
  1331.         };
  1332.  
  1333.         return (this.actual !== this.actual);
  1334. };
  1335.  
  1336. /**
  1337.  * Matcher that boolean not-nots the actual.
  1338.  */
  1339. jasmine.Matchers.prototype.toBeTruthy = function() {
  1340.   return !!this.actual;
  1341. };
  1342.  
  1343.  
  1344. /**
  1345.  * Matcher that boolean nots the actual.
  1346.  */
  1347. jasmine.Matchers.prototype.toBeFalsy = function() {
  1348.   return !this.actual;
  1349. };
  1350.  
  1351.  
  1352. /**
  1353.  * Matcher that checks to see if the actual, a Jasmine spy, was called.
  1354.  */
  1355. jasmine.Matchers.prototype.toHaveBeenCalled = function() {
  1356.   if (arguments.length > 0) {
  1357.     throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
  1358.   }
  1359.  
  1360.   if (!jasmine.isSpy(this.actual)) {
  1361.     throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
  1362.   }
  1363.  
  1364.   this.message = function() {
  1365.     return [
  1366.       "Expected spy " + this.actual.identity + " to have been called.",
  1367.       "Expected spy " + this.actual.identity + " not to have been called."
  1368.     ];
  1369.   };
  1370.  
  1371.   return this.actual.wasCalled;
  1372. };
  1373.  
  1374. /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
  1375. jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
  1376.  
  1377. /**
  1378.  * Matcher that checks to see if the actual, a Jasmine spy, was not called.
  1379.  *
  1380.  * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
  1381.  */
  1382. jasmine.Matchers.prototype.wasNotCalled = function() {
  1383.   if (arguments.length > 0) {
  1384.     throw new Error('wasNotCalled does not take arguments');
  1385.   }
  1386.  
  1387.   if (!jasmine.isSpy(this.actual)) {
  1388.     throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
  1389.   }
  1390.  
  1391.   this.message = function() {
  1392.     return [
  1393.       "Expected spy " + this.actual.identity + " to not have been called.",
  1394.       "Expected spy " + this.actual.identity + " to have been called."
  1395.     ];
  1396.   };
  1397.  
  1398.   return !this.actual.wasCalled;
  1399. };
  1400.  
  1401. /**
  1402.  * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
  1403.  *
  1404.  * @example
  1405.  *
  1406.  */
  1407. jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
  1408.   var expectedArgs = jasmine.util.argsToArray(arguments);
  1409.   if (!jasmine.isSpy(this.actual)) {
  1410.     throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
  1411.   }
  1412.   this.message = function() {
  1413.     var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
  1414.     var positiveMessage = "";
  1415.     if (this.actual.callCount === 0) {
  1416.       positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
  1417.     } else {
  1418.       positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
  1419.     }
  1420.     return [positiveMessage, invertedMessage];
  1421.   };
  1422.  
  1423.   return this.env.contains_(this.actual.argsForCall, expectedArgs);
  1424. };
  1425.  
  1426. /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
  1427. jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
  1428.  
  1429. /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
  1430. jasmine.Matchers.prototype.wasNotCalledWith = function() {
  1431.   var expectedArgs = jasmine.util.argsToArray(arguments);
  1432.   if (!jasmine.isSpy(this.actual)) {
  1433.     throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
  1434.   }
  1435.  
  1436.   this.message = function() {
  1437.     return [
  1438.       "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
  1439.       "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
  1440.     ];
  1441.   };
  1442.  
  1443.   return !this.env.contains_(this.actual.argsForCall, expectedArgs);
  1444. };
  1445.  
  1446. /**
  1447.  * Matcher that checks that the expected item is an element in the actual Array.
  1448.  *
  1449.  * @param {Object} expected
  1450.  */
  1451. jasmine.Matchers.prototype.toContain = function(expected) {
  1452.   return this.env.contains_(this.actual, expected);
  1453. };
  1454.  
  1455. /**
  1456.  * Matcher that checks that the expected item is NOT an element in the actual Array.
  1457.  *
  1458.  * @param {Object} expected
  1459.  * @deprecated as of 1.0. Use not.toContain() instead.
  1460.  */
  1461. jasmine.Matchers.prototype.toNotContain = function(expected) {
  1462.   return !this.env.contains_(this.actual, expected);
  1463. };
  1464.  
  1465. jasmine.Matchers.prototype.toBeLessThan = function(expected) {
  1466.   return this.actual < expected;
  1467. };
  1468.  
  1469. jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
  1470.   return this.actual > expected;
  1471. };
  1472.  
  1473. /**
  1474.  * Matcher that checks that the expected item is equal to the actual item
  1475.  * up to a given level of decimal precision (default 2).
  1476.  *
  1477.  * @param {Number} expected
  1478.  * @param {Number} precision, as number of decimal places
  1479.  */
  1480. jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
  1481.   if (!(precision === 0)) {
  1482.     precision = precision || 2;
  1483.   }
  1484.   return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
  1485. };
  1486.  
  1487. /**
  1488.  * Matcher that checks that the expected exception was thrown by the actual.
  1489.  *
  1490.  * @param {String} [expected]
  1491.  */
  1492. jasmine.Matchers.prototype.toThrow = function(expected) {
  1493.   var result = false;
  1494.   var exception;
  1495.   if (typeof this.actual != 'function') {
  1496.     throw new Error('Actual is not a function');
  1497.   }
  1498.   try {
  1499.     this.actual();
  1500.   } catch (e) {
  1501.     exception = e;
  1502.   }
  1503.   if (exception) {
  1504.     result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
  1505.   }
  1506.  
  1507.   var not = this.isNot ? "not " : "";
  1508.  
  1509.   this.message = function() {
  1510.     if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
  1511.       return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
  1512.     } else {
  1513.       return "Expected function to throw an exception.";
  1514.     }
  1515.   };
  1516.  
  1517.   return result;
  1518. };
  1519.  
  1520. jasmine.Matchers.Any = function(expectedClass) {
  1521.   this.expectedClass = expectedClass;
  1522. };
  1523.  
  1524. jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
  1525.   if (this.expectedClass == String) {
  1526.     return typeof other == 'string' || other instanceof String;
  1527.   }
  1528.  
  1529.   if (this.expectedClass == Number) {
  1530.     return typeof other == 'number' || other instanceof Number;
  1531.   }
  1532.  
  1533.   if (this.expectedClass == Function) {
  1534.     return typeof other == 'function' || other instanceof Function;
  1535.   }
  1536.  
  1537.   if (this.expectedClass == Object) {
  1538.     return typeof other == 'object';
  1539.   }
  1540.  
  1541.   return other instanceof this.expectedClass;
  1542. };
  1543.  
  1544. jasmine.Matchers.Any.prototype.jasmineToString = function() {
  1545.   return '<jasmine.any(' + this.expectedClass + ')>';
  1546. };
  1547.  
  1548. jasmine.Matchers.ObjectContaining = function (sample) {
  1549.   this.sample = sample;
  1550. };
  1551.  
  1552. jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
  1553.   mismatchKeys = mismatchKeys || [];
  1554.   mismatchValues = mismatchValues || [];
  1555.  
  1556.   var env = jasmine.getEnv();
  1557.  
  1558.   var hasKey = function(obj, keyName) {
  1559.     return obj != null && obj[keyName] !== jasmine.undefined;
  1560.   };
  1561.  
  1562.   for (var property in this.sample) {
  1563.     if (!hasKey(other, property) && hasKey(this.sample, property)) {
  1564.       mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
  1565.     }
  1566.     else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
  1567.       mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
  1568.     }
  1569.   }
  1570.  
  1571.   return (mismatchKeys.length === 0 && mismatchValues.length === 0);
  1572. };
  1573.  
  1574. jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
  1575.   return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
  1576. };
  1577. // Mock setTimeout, clearTimeout
  1578. // Contributed by Pivotal Computer Systems, www.pivotalsf.com
  1579.  
  1580. jasmine.FakeTimer = function() {
  1581.   this.reset();
  1582.  
  1583.   var self = this;
  1584.   self.setTimeout = function(funcToCall, millis) {
  1585.     self.timeoutsMade++;
  1586.     self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
  1587.     return self.timeoutsMade;
  1588.   };
  1589.  
  1590.   self.setInterval = function(funcToCall, millis) {
  1591.     self.timeoutsMade++;
  1592.     self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
  1593.     return self.timeoutsMade;
  1594.   };
  1595.  
  1596.   self.clearTimeout = function(timeoutKey) {
  1597.     self.scheduledFunctions[timeoutKey] = jasmine.undefined;
  1598.   };
  1599.  
  1600.   self.clearInterval = function(timeoutKey) {
  1601.     self.scheduledFunctions[timeoutKey] = jasmine.undefined;
  1602.   };
  1603.  
  1604. };
  1605.  
  1606. jasmine.FakeTimer.prototype.reset = function() {
  1607.   this.timeoutsMade = 0;
  1608.   this.scheduledFunctions = {};
  1609.   this.nowMillis = 0;
  1610. };
  1611.  
  1612. jasmine.FakeTimer.prototype.tick = function(millis) {
  1613.   var oldMillis = this.nowMillis;
  1614.   var newMillis = oldMillis + millis;
  1615.   this.runFunctionsWithinRange(oldMillis, newMillis);
  1616.   this.nowMillis = newMillis;
  1617. };
  1618.  
  1619. jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
  1620.   var scheduledFunc;
  1621.   var funcsToRun = [];
  1622.   for (var timeoutKey in this.scheduledFunctions) {
  1623.     scheduledFunc = this.scheduledFunctions[timeoutKey];
  1624.     if (scheduledFunc != jasmine.undefined &&
  1625.         scheduledFunc.runAtMillis >= oldMillis &&
  1626.         scheduledFunc.runAtMillis <= nowMillis) {
  1627.       funcsToRun.push(scheduledFunc);
  1628.       this.scheduledFunctions[timeoutKey] = jasmine.undefined;
  1629.     }
  1630.   }
  1631.  
  1632.   if (funcsToRun.length > 0) {
  1633.     funcsToRun.sort(function(a, b) {
  1634.       return a.runAtMillis - b.runAtMillis;
  1635.     });
  1636.     for (var i = 0; i < funcsToRun.length; ++i) {
  1637.       try {
  1638.         var funcToRun = funcsToRun[i];
  1639.         this.nowMillis = funcToRun.runAtMillis;
  1640.         funcToRun.funcToCall();
  1641.         if (funcToRun.recurring) {
  1642.           this.scheduleFunction(funcToRun.timeoutKey,
  1643.               funcToRun.funcToCall,
  1644.               funcToRun.millis,
  1645.               true);
  1646.         }
  1647.       } catch(e) {
  1648.       }
  1649.     }
  1650.     this.runFunctionsWithinRange(oldMillis, nowMillis);
  1651.   }
  1652. };
  1653.  
  1654. jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
  1655.   this.scheduledFunctions[timeoutKey] = {
  1656.     runAtMillis: this.nowMillis + millis,
  1657.     funcToCall: funcToCall,
  1658.     recurring: recurring,
  1659.     timeoutKey: timeoutKey,
  1660.     millis: millis
  1661.   };
  1662. };
  1663.  
  1664. /**
  1665.  * @namespace
  1666.  */
  1667. jasmine.Clock = {
  1668.   defaultFakeTimer: new jasmine.FakeTimer(),
  1669.  
  1670.   reset: function() {
  1671.     jasmine.Clock.assertInstalled();
  1672.     jasmine.Clock.defaultFakeTimer.reset();
  1673.   },
  1674.  
  1675.   tick: function(millis) {
  1676.     jasmine.Clock.assertInstalled();
  1677.     jasmine.Clock.defaultFakeTimer.tick(millis);
  1678.   },
  1679.  
  1680.   runFunctionsWithinRange: function(oldMillis, nowMillis) {
  1681.     jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
  1682.   },
  1683.  
  1684.   scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
  1685.     jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
  1686.   },
  1687.  
  1688.   useMock: function() {
  1689.     if (!jasmine.Clock.isInstalled()) {
  1690.       var spec = jasmine.getEnv().currentSpec;
  1691.       spec.after(jasmine.Clock.uninstallMock);
  1692.  
  1693.       jasmine.Clock.installMock();
  1694.     }
  1695.   },
  1696.  
  1697.   installMock: function() {
  1698.     jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
  1699.   },
  1700.  
  1701.   uninstallMock: function() {
  1702.     jasmine.Clock.assertInstalled();
  1703.     jasmine.Clock.installed = jasmine.Clock.real;
  1704.   },
  1705.  
  1706.   real: {
  1707.     setTimeout: jasmine.getGlobal().setTimeout,
  1708.     clearTimeout: jasmine.getGlobal().clearTimeout,
  1709.     setInterval: jasmine.getGlobal().setInterval,
  1710.     clearInterval: jasmine.getGlobal().clearInterval
  1711.   },
  1712.  
  1713.   assertInstalled: function() {
  1714.     if (!jasmine.Clock.isInstalled()) {
  1715.       throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
  1716.     }
  1717.   },
  1718.  
  1719.   isInstalled: function() {
  1720.     return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
  1721.   },
  1722.  
  1723.   installed: null
  1724. };
  1725. jasmine.Clock.installed = jasmine.Clock.real;
  1726.  
  1727. //else for IE support
  1728. jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
  1729.   if (jasmine.Clock.installed.setTimeout.apply) {
  1730.     return jasmine.Clock.installed.setTimeout.apply(this, arguments);
  1731.   } else {
  1732.     return jasmine.Clock.installed.setTimeout(funcToCall, millis);
  1733.   }
  1734. };
  1735.  
  1736. jasmine.getGlobal().setInterval = function(funcToCall, millis) {
  1737.   if (jasmine.Clock.installed.setInterval.apply) {
  1738.     return jasmine.Clock.installed.setInterval.apply(this, arguments);
  1739.   } else {
  1740.     return jasmine.Clock.installed.setInterval(funcToCall, millis);
  1741.   }
  1742. };
  1743.  
  1744. jasmine.getGlobal().clearTimeout = function(timeoutKey) {
  1745.   if (jasmine.Clock.installed.clearTimeout.apply) {
  1746.     return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
  1747.   } else {
  1748.     return jasmine.Clock.installed.clearTimeout(timeoutKey);
  1749.   }
  1750. };
  1751.  
  1752. jasmine.getGlobal().clearInterval = function(timeoutKey) {
  1753.   if (jasmine.Clock.installed.clearTimeout.apply) {
  1754.     return jasmine.Clock.installed.clearInterval.apply(this, arguments);
  1755.   } else {
  1756.     return jasmine.Clock.installed.clearInterval(timeoutKey);
  1757.   }
  1758. };
  1759.  
  1760. /**
  1761.  * @constructor
  1762.  */
  1763. jasmine.MultiReporter = function() {
  1764.   this.subReporters_ = [];
  1765. };
  1766. jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
  1767.  
  1768. jasmine.MultiReporter.prototype.addReporter = function(reporter) {
  1769.   this.subReporters_.push(reporter);
  1770. };
  1771.  
  1772. (function() {
  1773.   var functionNames = [
  1774.     "reportRunnerStarting",
  1775.     "reportRunnerResults",
  1776.     "reportSuiteResults",
  1777.     "reportSpecStarting",
  1778.     "reportSpecResults",
  1779.     "log"
  1780.   ];
  1781.   for (var i = 0; i < functionNames.length; i++) {
  1782.     var functionName = functionNames[i];
  1783.     jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
  1784.       return function() {
  1785.         for (var j = 0; j < this.subReporters_.length; j++) {
  1786.           var subReporter = this.subReporters_[j];
  1787.           if (subReporter[functionName]) {
  1788.             subReporter[functionName].apply(subReporter, arguments);
  1789.           }
  1790.         }
  1791.       };
  1792.     })(functionName);
  1793.   }
  1794. })();
  1795. /**
  1796.  * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
  1797.  *
  1798.  * @constructor
  1799.  */
  1800. jasmine.NestedResults = function() {
  1801.   /**
  1802.    * The total count of results
  1803.    */
  1804.   this.totalCount = 0;
  1805.   /**
  1806.    * Number of passed results
  1807.    */
  1808.   this.passedCount = 0;
  1809.   /**
  1810.    * Number of failed results
  1811.    */
  1812.   this.failedCount = 0;
  1813.   /**
  1814.    * Was this suite/spec skipped?
  1815.    */
  1816.   this.skipped = false;
  1817.   /**
  1818.    * @ignore
  1819.    */
  1820.   this.items_ = [];
  1821. };
  1822.  
  1823. /**
  1824.  * Roll up the result counts.
  1825.  *
  1826.  * @param result
  1827.  */
  1828. jasmine.NestedResults.prototype.rollupCounts = function(result) {
  1829.   this.totalCount += result.totalCount;
  1830.   this.passedCount += result.passedCount;
  1831.   this.failedCount += result.failedCount;
  1832. };
  1833.  
  1834. /**
  1835.  * Adds a log message.
  1836.  * @param values Array of message parts which will be concatenated later.
  1837.  */
  1838. jasmine.NestedResults.prototype.log = function(values) {
  1839.   this.items_.push(new jasmine.MessageResult(values));
  1840. };
  1841.  
  1842. /**
  1843.  * Getter for the results: message & results.
  1844.  */
  1845. jasmine.NestedResults.prototype.getItems = function() {
  1846.   return this.items_;
  1847. };
  1848.  
  1849. /**
  1850.  * Adds a result, tracking counts (total, passed, & failed)
  1851.  * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
  1852.  */
  1853. jasmine.NestedResults.prototype.addResult = function(result) {
  1854.   if (result.type != 'log') {
  1855.     if (result.items_) {
  1856.       this.rollupCounts(result);
  1857.     } else {
  1858.       this.totalCount++;
  1859.       if (result.passed()) {
  1860.         this.passedCount++;
  1861.       } else {
  1862.         this.failedCount++;
  1863.       }
  1864.     }
  1865.   }
  1866.   this.items_.push(result);
  1867. };
  1868.  
  1869. /**
  1870.  * @returns {Boolean} True if <b>everything</b> below passed
  1871.  */
  1872. jasmine.NestedResults.prototype.passed = function() {
  1873.   return this.passedCount === this.totalCount;
  1874. };
  1875. /**
  1876.  * Base class for pretty printing for expectation results.
  1877.  */
  1878. jasmine.PrettyPrinter = function() {
  1879.   this.ppNestLevel_ = 0;
  1880. };
  1881.  
  1882. /**
  1883.  * Formats a value in a nice, human-readable string.
  1884.  *
  1885.  * @param value
  1886.  */
  1887. jasmine.PrettyPrinter.prototype.format = function(value) {
  1888.   this.ppNestLevel_++;
  1889.   try {
  1890.     if (value === jasmine.undefined) {
  1891.       this.emitScalar('undefined');
  1892.     } else if (value === null) {
  1893.       this.emitScalar('null');
  1894.     } else if (value === jasmine.getGlobal()) {
  1895.       this.emitScalar('<global>');
  1896.     } else if (value.jasmineToString) {
  1897.       this.emitScalar(value.jasmineToString());
  1898.     } else if (typeof value === 'string') {
  1899.       this.emitString(value);
  1900.     } else if (jasmine.isSpy(value)) {
  1901.       this.emitScalar("spy on " + value.identity);
  1902.     } else if (value instanceof RegExp) {
  1903.       this.emitScalar(value.toString());
  1904.     } else if (typeof value === 'function') {
  1905.       this.emitScalar('Function');
  1906.     } else if (typeof value.nodeType === 'number') {
  1907.       this.emitScalar('HTMLNode');
  1908.     } else if (value instanceof Date) {
  1909.       this.emitScalar('Date(' + value + ')');
  1910.     } else if (value.__Jasmine_been_here_before__) {
  1911.       this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
  1912.     } else if (jasmine.isArray_(value) || typeof value == 'object') {
  1913.       value.__Jasmine_been_here_before__ = true;
  1914.       if (jasmine.isArray_(value)) {
  1915.         this.emitArray(value);
  1916.       } else {
  1917.         this.emitObject(value);
  1918.       }
  1919.       delete value.__Jasmine_been_here_before__;
  1920.     } else {
  1921.       this.emitScalar(value.toString());
  1922.     }
  1923.   } finally {
  1924.     this.ppNestLevel_--;
  1925.   }
  1926. };
  1927.  
  1928. jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
  1929.   for (var property in obj) {
  1930.     if (!obj.hasOwnProperty(property)) continue;
  1931.     if (property == '__Jasmine_been_here_before__') continue;
  1932.     fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
  1933.                                          obj.__lookupGetter__(property) !== null) : false);
  1934.   }
  1935. };
  1936.  
  1937. jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
  1938. jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
  1939. jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
  1940. jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
  1941.  
  1942. jasmine.StringPrettyPrinter = function() {
  1943.   jasmine.PrettyPrinter.call(this);
  1944.  
  1945.   this.string = '';
  1946. };
  1947. jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
  1948.  
  1949. jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
  1950.   this.append(value);
  1951. };
  1952.  
  1953. jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
  1954.   this.append("'" + value + "'");
  1955. };
  1956.  
  1957. jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
  1958.   if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
  1959.     this.append("Array");
  1960.     return;
  1961.   }
  1962.  
  1963.   this.append('[ ');
  1964.   for (var i = 0; i < array.length; i++) {
  1965.     if (i > 0) {
  1966.       this.append(', ');
  1967.     }
  1968.     this.format(array[i]);
  1969.   }
  1970.   this.append(' ]');
  1971. };
  1972.  
  1973. jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
  1974.   if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
  1975.     this.append("Object");
  1976.     return;
  1977.   }
  1978.  
  1979.   var self = this;
  1980.   this.append('{ ');
  1981.   var first = true;
  1982.  
  1983.   this.iterateObject(obj, function(property, isGetter) {
  1984.     if (first) {
  1985.       first = false;
  1986.     } else {
  1987.       self.append(', ');
  1988.     }
  1989.  
  1990.     self.append(property);
  1991.     self.append(' : ');
  1992.     if (isGetter) {
  1993.       self.append('<getter>');
  1994.     } else {
  1995.       self.format(obj[property]);
  1996.     }
  1997.   });
  1998.  
  1999.   this.append(' }');
  2000. };
  2001.  
  2002. jasmine.StringPrettyPrinter.prototype.append = function(value) {
  2003.   this.string += value;
  2004. };
  2005. jasmine.Queue = function(env) {
  2006.   this.env = env;
  2007.  
  2008.   // parallel to blocks. each true value in this array means the block will
  2009.   // get executed even if we abort
  2010.   this.ensured = [];
  2011.   this.blocks = [];
  2012.   this.running = false;
  2013.   this.index = 0;
  2014.   this.offset = 0;
  2015.   this.abort = false;
  2016. };
  2017.  
  2018. jasmine.Queue.prototype.addBefore = function(block, ensure) {
  2019.   if (ensure === jasmine.undefined) {
  2020.     ensure = false;
  2021.   }
  2022.  
  2023.   this.blocks.unshift(block);
  2024.   this.ensured.unshift(ensure);
  2025. };
  2026.  
  2027. jasmine.Queue.prototype.add = function(block, ensure) {
  2028.   if (ensure === jasmine.undefined) {
  2029.     ensure = false;
  2030.   }
  2031.  
  2032.   this.blocks.push(block);
  2033.   this.ensured.push(ensure);
  2034. };
  2035.  
  2036. jasmine.Queue.prototype.insertNext = function(block, ensure) {
  2037.   if (ensure === jasmine.undefined) {
  2038.     ensure = false;
  2039.   }
  2040.  
  2041.   this.ensured.splice((this.index + this.offset + 1), 0, ensure);
  2042.   this.blocks.splice((this.index + this.offset + 1), 0, block);
  2043.   this.offset++;
  2044. };
  2045.  
  2046. jasmine.Queue.prototype.start = function(onComplete) {
  2047.   this.running = true;
  2048.   this.onComplete = onComplete;
  2049.   this.next_();
  2050. };
  2051.  
  2052. jasmine.Queue.prototype.isRunning = function() {
  2053.   return this.running;
  2054. };
  2055.  
  2056. jasmine.Queue.LOOP_DONT_RECURSE = true;
  2057.  
  2058. jasmine.Queue.prototype.next_ = function() {
  2059.   var self = this;
  2060.   var goAgain = true;
  2061.  
  2062.   while (goAgain) {
  2063.     goAgain = false;
  2064.    
  2065.     if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
  2066.       var calledSynchronously = true;
  2067.       var completedSynchronously = false;
  2068.  
  2069.       var onComplete = function () {
  2070.         if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
  2071.           completedSynchronously = true;
  2072.           return;
  2073.         }
  2074.  
  2075.         if (self.blocks[self.index].abort) {
  2076.           self.abort = true;
  2077.         }
  2078.  
  2079.         self.offset = 0;
  2080.         self.index++;
  2081.  
  2082.         var now = new Date().getTime();
  2083.         if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
  2084.           self.env.lastUpdate = now;
  2085.           self.env.setTimeout(function() {
  2086.             self.next_();
  2087.           }, 0);
  2088.         } else {
  2089.           if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
  2090.             goAgain = true;
  2091.           } else {
  2092.             self.next_();
  2093.           }
  2094.         }
  2095.       };
  2096.       self.blocks[self.index].execute(onComplete);
  2097.  
  2098.       calledSynchronously = false;
  2099.       if (completedSynchronously) {
  2100.         onComplete();
  2101.       }
  2102.      
  2103.     } else {
  2104.       self.running = false;
  2105.       if (self.onComplete) {
  2106.         self.onComplete();
  2107.       }
  2108.     }
  2109.   }
  2110. };
  2111.  
  2112. jasmine.Queue.prototype.results = function() {
  2113.   var results = new jasmine.NestedResults();
  2114.   for (var i = 0; i < this.blocks.length; i++) {
  2115.     if (this.blocks[i].results) {
  2116.       results.addResult(this.blocks[i].results());
  2117.     }
  2118.   }
  2119.   return results;
  2120. };
  2121.  
  2122.  
  2123. /**
  2124.  * Runner
  2125.  *
  2126.  * @constructor
  2127.  * @param {jasmine.Env} env
  2128.  */
  2129. jasmine.Runner = function(env) {
  2130.   var self = this;
  2131.   self.env = env;
  2132.   self.queue = new jasmine.Queue(env);
  2133.   self.before_ = [];
  2134.   self.after_ = [];
  2135.   self.suites_ = [];
  2136. };
  2137.  
  2138. jasmine.Runner.prototype.execute = function() {
  2139.   var self = this;
  2140.   if (self.env.reporter.reportRunnerStarting) {
  2141.     self.env.reporter.reportRunnerStarting(this);
  2142.   }
  2143.   self.queue.start(function () {
  2144.     self.finishCallback();
  2145.   });
  2146. };
  2147.  
  2148. jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
  2149.   beforeEachFunction.typeName = 'beforeEach';
  2150.   this.before_.splice(0,0,beforeEachFunction);
  2151. };
  2152.  
  2153. jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
  2154.   afterEachFunction.typeName = 'afterEach';
  2155.   this.after_.splice(0,0,afterEachFunction);
  2156. };
  2157.  
  2158.  
  2159. jasmine.Runner.prototype.finishCallback = function() {
  2160.   this.env.reporter.reportRunnerResults(this);
  2161. };
  2162.  
  2163. jasmine.Runner.prototype.addSuite = function(suite) {
  2164.   this.suites_.push(suite);
  2165. };
  2166.  
  2167. jasmine.Runner.prototype.add = function(block) {
  2168.   if (block instanceof jasmine.Suite) {
  2169.     this.addSuite(block);
  2170.   }
  2171.   this.queue.add(block);
  2172. };
  2173.  
  2174. jasmine.Runner.prototype.specs = function () {
  2175.   var suites = this.suites();
  2176.   var specs = [];
  2177.   for (var i = 0; i < suites.length; i++) {
  2178.     specs = specs.concat(suites[i].specs());
  2179.   }
  2180.   return specs;
  2181. };
  2182.  
  2183. jasmine.Runner.prototype.suites = function() {
  2184.   return this.suites_;
  2185. };
  2186.  
  2187. jasmine.Runner.prototype.topLevelSuites = function() {
  2188.   var topLevelSuites = [];
  2189.   for (var i = 0; i < this.suites_.length; i++) {
  2190.     if (!this.suites_[i].parentSuite) {
  2191.       topLevelSuites.push(this.suites_[i]);
  2192.     }
  2193.   }
  2194.   return topLevelSuites;
  2195. };
  2196.  
  2197. jasmine.Runner.prototype.results = function() {
  2198.   return this.queue.results();
  2199. };
  2200. /**
  2201.  * Internal representation of a Jasmine specification, or test.
  2202.  *
  2203.  * @constructor
  2204.  * @param {jasmine.Env} env
  2205.  * @param {jasmine.Suite} suite
  2206.  * @param {String} description
  2207.  */
  2208. jasmine.Spec = function(env, suite, description) {
  2209.   if (!env) {
  2210.     throw new Error('jasmine.Env() required');
  2211.   }
  2212.   if (!suite) {
  2213.     throw new Error('jasmine.Suite() required');
  2214.   }
  2215.   var spec = this;
  2216.   spec.id = env.nextSpecId ? env.nextSpecId() : null;
  2217.   spec.env = env;
  2218.   spec.suite = suite;
  2219.   spec.description = description;
  2220.   spec.queue = new jasmine.Queue(env);
  2221.  
  2222.   spec.afterCallbacks = [];
  2223.   spec.spies_ = [];
  2224.  
  2225.   spec.results_ = new jasmine.NestedResults();
  2226.   spec.results_.description = description;
  2227.   spec.matchersClass = null;
  2228. };
  2229.  
  2230. jasmine.Spec.prototype.getFullName = function() {
  2231.   return this.suite.getFullName() + ' ' + this.description + '.';
  2232. };
  2233.  
  2234.  
  2235. jasmine.Spec.prototype.results = function() {
  2236.   return this.results_;
  2237. };
  2238.  
  2239. /**
  2240.  * All parameters are pretty-printed and concatenated together, then written to the spec's output.
  2241.  *
  2242.  * Be careful not to leave calls to <code>jasmine.log</code> in production code.
  2243.  */
  2244. jasmine.Spec.prototype.log = function() {
  2245.   return this.results_.log(arguments);
  2246. };
  2247.  
  2248. jasmine.Spec.prototype.runs = function (func) {
  2249.   var block = new jasmine.Block(this.env, func, this);
  2250.   this.addToQueue(block);
  2251.   return this;
  2252. };
  2253.  
  2254. jasmine.Spec.prototype.addToQueue = function (block) {
  2255.   if (this.queue.isRunning()) {
  2256.     this.queue.insertNext(block);
  2257.   } else {
  2258.     this.queue.add(block);
  2259.   }
  2260. };
  2261.  
  2262. /**
  2263.  * @param {jasmine.ExpectationResult} result
  2264.  */
  2265. jasmine.Spec.prototype.addMatcherResult = function(result) {
  2266.   this.results_.addResult(result);
  2267. };
  2268.  
  2269. jasmine.Spec.prototype.expect = function(actual) {
  2270.   var positive = new (this.getMatchersClass_())(this.env, actual, this);
  2271.   positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
  2272.   return positive;
  2273. };
  2274.  
  2275. /**
  2276.  * Waits a fixed time period before moving to the next block.
  2277.  *
  2278.  * @deprecated Use waitsFor() instead
  2279.  * @param {Number} timeout milliseconds to wait
  2280.  */
  2281. jasmine.Spec.prototype.waits = function(timeout) {
  2282.   var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
  2283.   this.addToQueue(waitsFunc);
  2284.   return this;
  2285. };
  2286.  
  2287. /**
  2288.  * Waits for the latchFunction to return true before proceeding to the next block.
  2289.  *
  2290.  * @param {Function} latchFunction
  2291.  * @param {String} optional_timeoutMessage
  2292.  * @param {Number} optional_timeout
  2293.  */
  2294. jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
  2295.   var latchFunction_ = null;
  2296.   var optional_timeoutMessage_ = null;
  2297.   var optional_timeout_ = null;
  2298.  
  2299.   for (var i = 0; i < arguments.length; i++) {
  2300.     var arg = arguments[i];
  2301.     switch (typeof arg) {
  2302.       case 'function':
  2303.         latchFunction_ = arg;
  2304.         break;
  2305.       case 'string':
  2306.         optional_timeoutMessage_ = arg;
  2307.         break;
  2308.       case 'number':
  2309.         optional_timeout_ = arg;
  2310.         break;
  2311.     }
  2312.   }
  2313.  
  2314.   var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
  2315.   this.addToQueue(waitsForFunc);
  2316.   return this;
  2317. };
  2318.  
  2319. jasmine.Spec.prototype.fail = function (e) {
  2320.   var expectationResult = new jasmine.ExpectationResult({
  2321.     passed: false,
  2322.     message: e ? jasmine.util.formatException(e) : 'Exception',
  2323.     trace: { stack: e.stack }
  2324.   });
  2325.   this.results_.addResult(expectationResult);
  2326. };
  2327.  
  2328. jasmine.Spec.prototype.getMatchersClass_ = function() {
  2329.   return this.matchersClass || this.env.matchersClass;
  2330. };
  2331.  
  2332. jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
  2333.   var parent = this.getMatchersClass_();
  2334.   var newMatchersClass = function() {
  2335.     parent.apply(this, arguments);
  2336.   };
  2337.   jasmine.util.inherit(newMatchersClass, parent);
  2338.   jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
  2339.   this.matchersClass = newMatchersClass;
  2340. };
  2341.  
  2342. jasmine.Spec.prototype.finishCallback = function() {
  2343.   this.env.reporter.reportSpecResults(this);
  2344. };
  2345.  
  2346. jasmine.Spec.prototype.finish = function(onComplete) {
  2347.   this.removeAllSpies();
  2348.   this.finishCallback();
  2349.   if (onComplete) {
  2350.     onComplete();
  2351.   }
  2352. };
  2353.  
  2354. jasmine.Spec.prototype.after = function(doAfter) {
  2355.   if (this.queue.isRunning()) {
  2356.     this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
  2357.   } else {
  2358.     this.afterCallbacks.unshift(doAfter);
  2359.   }
  2360. };
  2361.  
  2362. jasmine.Spec.prototype.execute = function(onComplete) {
  2363.   var spec = this;
  2364.   if (!spec.env.specFilter(spec)) {
  2365.     spec.results_.skipped = true;
  2366.     spec.finish(onComplete);
  2367.     return;
  2368.   }
  2369.  
  2370.   this.env.reporter.reportSpecStarting(this);
  2371.  
  2372.   spec.env.currentSpec = spec;
  2373.  
  2374.   spec.addBeforesAndAftersToQueue();
  2375.  
  2376.   spec.queue.start(function () {
  2377.     spec.finish(onComplete);
  2378.   });
  2379. };
  2380.  
  2381. jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
  2382.   var runner = this.env.currentRunner();
  2383.   var i;
  2384.  
  2385.   for (var suite = this.suite; suite; suite = suite.parentSuite) {
  2386.     for (i = 0; i < suite.before_.length; i++) {
  2387.       this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
  2388.     }
  2389.   }
  2390.   for (i = 0; i < runner.before_.length; i++) {
  2391.     this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
  2392.   }
  2393.   for (i = 0; i < this.afterCallbacks.length; i++) {
  2394.     this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
  2395.   }
  2396.   for (suite = this.suite; suite; suite = suite.parentSuite) {
  2397.     for (i = 0; i < suite.after_.length; i++) {
  2398.       this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
  2399.     }
  2400.   }
  2401.   for (i = 0; i < runner.after_.length; i++) {
  2402.     this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
  2403.   }
  2404. };
  2405.  
  2406. jasmine.Spec.prototype.explodes = function() {
  2407.   throw 'explodes function should not have been called';
  2408. };
  2409.  
  2410. jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
  2411.   if (obj == jasmine.undefined) {
  2412.     throw "spyOn could not find an object to spy upon for " + methodName + "()";
  2413.   }
  2414.  
  2415.   if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
  2416.     throw methodName + '() method does not exist';
  2417.   }
  2418.  
  2419.   if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
  2420.     throw new Error(methodName + ' has already been spied upon');
  2421.   }
  2422.  
  2423.   var spyObj = jasmine.createSpy(methodName);
  2424.  
  2425.   this.spies_.push(spyObj);
  2426.   spyObj.baseObj = obj;
  2427.   spyObj.methodName = methodName;
  2428.   spyObj.originalValue = obj[methodName];
  2429.  
  2430.   obj[methodName] = spyObj;
  2431.  
  2432.   return spyObj;
  2433. };
  2434.  
  2435. jasmine.Spec.prototype.removeAllSpies = function() {
  2436.   for (var i = 0; i < this.spies_.length; i++) {
  2437.     var spy = this.spies_[i];
  2438.     spy.baseObj[spy.methodName] = spy.originalValue;
  2439.   }
  2440.   this.spies_ = [];
  2441. };
  2442.  
  2443. /**
  2444.  * Internal representation of a Jasmine suite.
  2445.  *
  2446.  * @constructor
  2447.  * @param {jasmine.Env} env
  2448.  * @param {String} description
  2449.  * @param {Function} specDefinitions
  2450.  * @param {jasmine.Suite} parentSuite
  2451.  */
  2452. jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
  2453.   var self = this;
  2454.   self.id = env.nextSuiteId ? env.nextSuiteId() : null;
  2455.   self.description = description;
  2456.   self.queue = new jasmine.Queue(env);
  2457.   self.parentSuite = parentSuite;
  2458.   self.env = env;
  2459.   self.before_ = [];
  2460.   self.after_ = [];
  2461.   self.children_ = [];
  2462.   self.suites_ = [];
  2463.   self.specs_ = [];
  2464. };
  2465.  
  2466. jasmine.Suite.prototype.getFullName = function() {
  2467.   var fullName = this.description;
  2468.   for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
  2469.     fullName = parentSuite.description + ' ' + fullName;
  2470.   }
  2471.   return fullName;
  2472. };
  2473.  
  2474. jasmine.Suite.prototype.finish = function(onComplete) {
  2475.   this.env.reporter.reportSuiteResults(this);
  2476.   this.finished = true;
  2477.   if (typeof(onComplete) == 'function') {
  2478.     onComplete();
  2479.   }
  2480. };
  2481.  
  2482. jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
  2483.   beforeEachFunction.typeName = 'beforeEach';
  2484.   this.before_.unshift(beforeEachFunction);
  2485. };
  2486.  
  2487. jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
  2488.   afterEachFunction.typeName = 'afterEach';
  2489.   this.after_.unshift(afterEachFunction);
  2490. };
  2491.  
  2492. jasmine.Suite.prototype.results = function() {
  2493.   return this.queue.results();
  2494. };
  2495.  
  2496. jasmine.Suite.prototype.add = function(suiteOrSpec) {
  2497.   this.children_.push(suiteOrSpec);
  2498.   if (suiteOrSpec instanceof jasmine.Suite) {
  2499.     this.suites_.push(suiteOrSpec);
  2500.     this.env.currentRunner().addSuite(suiteOrSpec);
  2501.   } else {
  2502.     this.specs_.push(suiteOrSpec);
  2503.   }
  2504.   this.queue.add(suiteOrSpec);
  2505. };
  2506.  
  2507. jasmine.Suite.prototype.specs = function() {
  2508.   return this.specs_;
  2509. };
  2510.  
  2511. jasmine.Suite.prototype.suites = function() {
  2512.   return this.suites_;
  2513. };
  2514.  
  2515. jasmine.Suite.prototype.children = function() {
  2516.   return this.children_;
  2517. };
  2518.  
  2519. jasmine.Suite.prototype.execute = function(onComplete) {
  2520.   var self = this;
  2521.   this.queue.start(function () {
  2522.     self.finish(onComplete);
  2523.   });
  2524. };
  2525. jasmine.WaitsBlock = function(env, timeout, spec) {
  2526.   this.timeout = timeout;
  2527.   jasmine.Block.call(this, env, null, spec);
  2528. };
  2529.  
  2530. jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
  2531.  
  2532. jasmine.WaitsBlock.prototype.execute = function (onComplete) {
  2533.   if (jasmine.VERBOSE) {
  2534.     this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
  2535.   }
  2536.   this.env.setTimeout(function () {
  2537.     onComplete();
  2538.   }, this.timeout);
  2539. };
  2540. /**
  2541.  * A block which waits for some condition to become true, with timeout.
  2542.  *
  2543.  * @constructor
  2544.  * @extends jasmine.Block
  2545.  * @param {jasmine.Env} env The Jasmine environment.
  2546.  * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
  2547.  * @param {Function} latchFunction A function which returns true when the desired condition has been met.
  2548.  * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
  2549.  * @param {jasmine.Spec} spec The Jasmine spec.
  2550.  */
  2551. jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
  2552.   this.timeout = timeout || env.defaultTimeoutInterval;
  2553.   this.latchFunction = latchFunction;
  2554.   this.message = message;
  2555.   this.totalTimeSpentWaitingForLatch = 0;
  2556.   jasmine.Block.call(this, env, null, spec);
  2557. };
  2558. jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
  2559.  
  2560. jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
  2561.  
  2562. jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
  2563.   if (jasmine.VERBOSE) {
  2564.     this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
  2565.   }
  2566.   var latchFunctionResult;
  2567.   try {
  2568.     latchFunctionResult = this.latchFunction.apply(this.spec);
  2569.   } catch (e) {
  2570.     this.spec.fail(e);
  2571.     onComplete();
  2572.     return;
  2573.   }
  2574.  
  2575.   if (latchFunctionResult) {
  2576.     onComplete();
  2577.   } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
  2578.     var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
  2579.     this.spec.fail({
  2580.       name: 'timeout',
  2581.       message: message
  2582.     });
  2583.  
  2584.     this.abort = true;
  2585.     onComplete();
  2586.   } else {
  2587.     this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
  2588.     var self = this;
  2589.     this.env.setTimeout(function() {
  2590.       self.execute(onComplete);
  2591.     }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
  2592.   }
  2593. };
  2594.  
  2595. jasmine.version_= {
  2596.   "major": 1,
  2597.   "minor": 3,
  2598.   "build": 1,
  2599.   "revision": 1354556913
  2600. };
  2601.  
downloadjasmine.js Source code - Download mobile-chrome-apps Source code
Related Source Codes/Software:
pycrumbs - Bits and bytes of Python from the Internet 2017-02-20
drupal - Verbatim mirror of the git.drupal.org repository f... 2017-02-20
elasticsearch-head - A web front end for an elastic search cluster 2017-02-19
launchrocket - A Mac PrefPane to manage all your Homebrew-install... 2017-02-19
jquery-boilerplate - A jump-start for jQuery plugins development ... 2017-02-19
ricochet - Anonymous peer-to-peer instant messaging ... 2017-02-20
octokit.rb - Ruby toolkit for the GitHub API ... 2017-02-20
sticky-headers-recyclerview - [UNMAINTAINED] Sticky Headers decorator for Androi... 2017-02-20
shuttle - A simple SSH shortcut menu for macOS ... 2017-02-20
postgres - Mirror of the official PostgreSQL GIT repository. ... 2017-02-20
sharingbuttons.io - Quickly generate social sharing buttons with a tin... 2017-04-12
angular-schema-form - Generate forms from a JSON schema, with AngularJS!... 2017-04-12
sisyphus - Gmail-like client-side drafts and bit more. Plugin... 2017-04-12
git-recall - Handy tool to easily recall what you've done 2017-04-12
devise_invitable - An invitation strategy for devise 2017-04-12
redux-ecosystem-links - A categorized list of Redux-related addons, librar... 2017-04-12
code - Douban CODE http://douban-c... 2017-04-12
PullZoomView - An Android custom ListView and ScrollView with pul... 2017-04-12
scrollability - Imitates iOS native scrolling in JavaScript. http:... 2017-04-12
pyxley - Python helpers for building dashboards using Flask... 2017-04-12

 Back to top