From d7a47264efceb4433dc47e22997b404e1c0b34a8 Mon Sep 17 00:00:00 2001 From: ragaskar Date: Thu, 27 Aug 2009 22:15:50 -0700 Subject: [PATCH] Automatically build jsdocs on rake build tasks --- Rakefile | 55 +- doc/files.html | 34 +- doc/index.html | 24 +- doc/symbols/_global_.html | 30 +- ...QueuedFunction.html => jasmine.Block.html} | 36 +- doc/symbols/jasmine.Env.html | 12 +- ...ection.html => jasmine.JsApiReporter.html} | 198 +- doc/symbols/jasmine.MultiReporter.html | 12 +- doc/symbols/jasmine.NestedResults.html | 12 +- doc/symbols/jasmine.Reporter.html | 12 +- doc/symbols/jasmine.Runner.html | 12 +- doc/symbols/jasmine.Spec.html | 12 +- doc/symbols/jasmine.Spy.html | 12 +- doc/symbols/jasmine.Suite.html | 12 +- doc/symbols/jasmine.html | 12 +- doc/symbols/jasmine.util.html | 12 +- doc/symbols/src/lib_TrivialReporter.js.html | 128 + ...mine.js.html => lib_jasmine-0.9.0.js.html} | 3702 +++++++++-------- doc/symbols/src/lib_json2.js.html | 486 +++ 19 files changed, 2681 insertions(+), 2132 deletions(-) rename doc/symbols/{jasmine.QueuedFunction.html => jasmine.Block.html} (84%) rename doc/symbols/{jasmine.ActionCollection.html => jasmine.JsApiReporter.html} (56%) create mode 100644 doc/symbols/src/lib_TrivialReporter.js.html rename doc/symbols/src/{lib_jasmine.js.html => lib_jasmine-0.9.0.js.html} (63%) create mode 100644 doc/symbols/src/lib_json2.js.html diff --git a/Rakefile b/Rakefile index f0d5206..3a09256 100644 --- a/Rakefile +++ b/Rakefile @@ -1,15 +1,16 @@ desc 'Builds lib/jasmine from source' -task :build do - require 'json' - sources = jasmine_sources - version = version_hash - old_jasmine_files = Dir.glob('lib/jasmine*.js') - old_jasmine_files.each do |file| - File.delete(file) - end - jasmine = File.new("lib/#{jasmine_filename version}", 'w') - jasmine.puts(File.read(sources.shift)) - jasmine.puts %{ +namespace :build do + task :jasmine => 'build:doc' do + require 'json' + sources = jasmine_sources + version = version_hash + old_jasmine_files = Dir.glob('lib/jasmine*.js') + old_jasmine_files.each do |file| + File.delete(file) + end + jasmine = File.new("lib/#{jasmine_filename version}", 'w') + jasmine.puts(File.read(sources.shift)) + jasmine.puts %{ jasmine.version_= { "major": #{version['major']}, "minor": #{version['minor']}, @@ -17,9 +18,22 @@ jasmine.version_= { "revision": #{version['revision']} }; } - sources.each do |source_filename| - jasmine.puts(File.read(source_filename)) + sources.each do |source_filename| + jasmine.puts(File.read(source_filename)) + end end + + desc "Build jasmine documentation" + task :doc do + require 'rubygems' + #sudo gem install ragaskar-jsdoc_helper + require 'jsdoc_helper' + + + JsdocHelper::Rake::Task.new(:lambda_jsdoc) + Rake::Task[:lambda_jsdoc].invoke + end + end def jasmine_sources @@ -38,14 +52,13 @@ end namespace :test do desc "Run continuous integration tests" - require "spec" - require 'spec/rake/spectask' - - task :ci => :build do - Spec::Rake::SpecTask.new(:lambda_ci) do |t| - t.spec_opts = ["--color", "--format", "specdoc"] - t.spec_files = ["spec/jasmine_spec.rb"] - end + task :ci => 'build:jasmine' do + require "spec" + require 'spec/rake/spectask' + Spec::Rake::SpecTask.new(:lambda_ci) do |t| + t.spec_opts = ["--color", "--format", "specdoc"] + t.spec_files = ["spec/jasmine_spec.rb"] + end Rake::Task[:lambda_ci].invoke end diff --git a/doc/files.html b/doc/files.html index b997fff..12dd328 100644 --- a/doc/files.html +++ b/doc/files.html @@ -188,16 +188,16 @@ ul.inheritsList
  • jasmine
  • -
  • jasmine.ActionCollection
  • +
  • jasmine.Block
  • jasmine.Env
  • +
  • jasmine.JsApiReporter
  • +
  • jasmine.MultiReporter
  • jasmine.NestedResults
  • -
  • jasmine.QueuedFunction
  • -
  • jasmine.Reporter
  • jasmine.Runner
  • @@ -219,7 +219,31 @@ ul.inheritsList
    -

    lib/jasmine.js

    +

    lib/jasmine-0.9.0.js

    + +
    + + + + +
    +
    +
    + +
    +

    lib/json2.js

    + +
    + + + + +
    +
    +
    + +
    +

    lib/TrivialReporter.js

    @@ -234,7 +258,7 @@ ul.inheritsList
    - Documentation generated by JsDoc Toolkit 2.3.0 on Thu Jul 09 2009 21:42:19 GMT-0700 (PDT) + Documentation generated by JsDoc Toolkit 2.1.0 on Thu Aug 27 2009 22:13:15 GMT-0700 (PDT)
    \ No newline at end of file diff --git a/doc/index.html b/doc/index.html index c9123ec..29ebb9b 100644 --- a/doc/index.html +++ b/doc/index.html @@ -2,7 +2,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - + JsDoc Reference - Index @@ -188,16 +188,16 @@ ul.inheritsList
  • jasmine
  • -
  • jasmine.ActionCollection
  • +
  • jasmine.Block
  • jasmine.Env
  • +
  • jasmine.JsApiReporter
  • +
  • jasmine.MultiReporter
  • jasmine.NestedResults
  • -
  • jasmine.QueuedFunction
  • -
  • jasmine.Reporter
  • jasmine.Runner
  • @@ -231,7 +231,7 @@ ul.inheritsList
    -

    jasmine.ActionCollection

    +

    jasmine.Block


    @@ -242,6 +242,12 @@ ul.inheritsList
    +
    +

    jasmine.JsApiReporter

    + +
    +
    +

    jasmine.MultiReporter

    @@ -254,12 +260,6 @@ ul.inheritsList

    -
    -

    jasmine.QueuedFunction

    - -
    -
    -

    jasmine.Reporter

    @@ -300,7 +300,7 @@ ul.inheritsList
    - Documentation generated by JsDoc Toolkit 2.3.0 on Thu Jul 09 2009 21:42:19 GMT-0700 (PDT) + Documentation generated by JsDoc Toolkit 2.1.0 on Thu Aug 27 2009 22:13:15 GMT-0700 (PDT)
    \ No newline at end of file diff --git a/doc/symbols/_global_.html b/doc/symbols/_global_.html index e831a25..fae4122 100644 --- a/doc/symbols/_global_.html +++ b/doc/symbols/_global_.html @@ -193,16 +193,16 @@ ul.inheritsList
  • jasmine
  • -
  • jasmine.ActionCollection
  • +
  • jasmine.Block
  • jasmine.Env
  • +
  • jasmine.JsApiReporter
  • +
  • jasmine.MultiReporter
  • jasmine.NestedResults
  • -
  • jasmine.QueuedFunction
  • -
  • jasmine.Reporter
  • jasmine.Runner
  • @@ -389,7 +389,7 @@ ul.inheritsList Used for restoring any state that is hijacked during spec execution.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -430,7 +430,7 @@ Used for restoring any state that is hijacked during spec execution. Used for spec setup, including validating assumptions.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -473,7 +473,7 @@ are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be of setup in some tests.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -527,7 +527,7 @@ It is passed an Object that is the actual value and should chain to one of the m jasmine.Matchers functions.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -568,7 +568,7 @@ jasmine.Matchers functions. // TODO: pending tests
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -619,7 +619,7 @@ jasmine.Matchers functions. Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -658,7 +658,7 @@ jasmine.Matchers functions. Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -725,7 +725,7 @@ spyOn(foo, 'not'); // actual foo.not will not be called, execution stops Waits for a timeout before moving to the next runs()-defined block.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -764,7 +764,7 @@ spyOn(foo, 'not'); // actual foo.not will not be called, execution stops Waits for the latchFunction to return true before proceeding to the next runs()-defined block.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -815,7 +815,7 @@ spyOn(foo, 'not'); // actual foo.not will not be called, execution stops Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -862,7 +862,7 @@ spyOn(foo, 'not'); // actual foo.not will not be called, execution stops A convenience method that allows existing specs to be disabled temporarily during development.
    - Defined in: jasmine.js. + Defined in: jasmine-0.9.0.js. @@ -908,7 +908,7 @@ A convenience method that allows existing specs to be disabled temporarily durin
    - Documentation generated by JsDoc Toolkit 2.3.0 on Thu Jul 09 2009 21:42:18 GMT-0700 (PDT) + Documentation generated by JsDoc Toolkit 2.1.0 on Thu Aug 27 2009 22:13:15 GMT-0700 (PDT)
    diff --git a/doc/symbols/jasmine.QueuedFunction.html b/doc/symbols/jasmine.Block.html similarity index 84% rename from doc/symbols/jasmine.QueuedFunction.html rename to doc/symbols/jasmine.Block.html index f53996b..a864726 100644 --- a/doc/symbols/jasmine.QueuedFunction.html +++ b/doc/symbols/jasmine.Block.html @@ -5,7 +5,7 @@ - JsDoc Reference - jasmine.QueuedFunction + JsDoc Reference - jasmine.Block
      1 jasmine.TrivialReporter = function(doc) {
    +  2   this.document = doc || document;
    +  3   this.suiteDivs = {};
    +  4 };
    +  5 
    +  6 jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
    +  7   var el = document.createElement(type);
    +  8 
    +  9   for (var i = 2; i < arguments.length; i++) {
    + 10     var child = arguments[i];
    + 11 
    + 12     if (typeof child === 'string') {
    + 13       el.appendChild(document.createTextNode(child));
    + 14     } else {
    + 15       el.appendChild(child);
    + 16     }
    + 17   }
    + 18 
    + 19   for (var attr in attrs) {
    + 20     if (attr == 'className') {
    + 21       el.setAttribute('class', attrs[attr]);
    + 22     } else {
    + 23       el[attr] = attrs[attr];
    + 24     }
    + 25   }
    + 26 
    + 27   return el;
    + 28 };
    + 29 
    + 30 jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
    + 31   var suites = runner.getAllSuites();
    + 32 
    + 33   this.runnerDiv = this.createDom('div', { className: 'runner running' }, "Running...");
    + 34   this.document.body.appendChild(this.runnerDiv);
    + 35 
    + 36   for (var i = 0; i < suites.length; i++) {
    + 37     var suite = suites[i];
    + 38     var suiteDiv = this.createDom('div', { className: 'suite' },
    + 39         this.createDom('a', { className: 'runSpec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
    + 40         suite.description);
    + 41     this.suiteDivs[suite.getFullName()] = suiteDiv;
    + 42     var parentDiv = this.document.body;
    + 43     if (suite.parentSuite) {
    + 44       parentDiv = this.suiteDivs[suite.parentSuite.getFullName()];
    + 45     }
    + 46     parentDiv.appendChild(suiteDiv);
    + 47   }
    + 48 };
    + 49 
    + 50 jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
    + 51   var results = runner.getResults();
    + 52   var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
    + 53   this.runnerDiv.setAttribute("class", className);
    + 54   var message = results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
    + 55   this.runnerDiv.replaceChild(this.document.createTextNode(message), this.runnerDiv.firstChild);
    + 56 };
    + 57 
    + 58 jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
    + 59   var results = suite.getResults();
    + 60   var status = results.passed() ? 'passed' : 'failed';
    + 61   if (results.totalCount == 0) { // todo: change this to check results.skipped
    + 62     status = 'skipped';
    + 63   }
    + 64   this.suiteDivs[suite.getFullName()].className += " " + status;
    + 65 };
    + 66 
    + 67 jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
    + 68   var results = spec.getResults();
    + 69   var status = results.passed() ? 'passed' : 'failed';
    + 70   if (results.skipped) {
    + 71     status = 'skipped';
    + 72   }
    + 73   var specDiv = this.createDom('div', { className: 'spec '  + status },
    + 74       this.createDom('a', { className: 'runSpec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
    + 75       spec.getFullName());
    + 76 
    + 77 
    + 78   var resultItems = results.getItems();
    + 79   for (var i = 0; i < resultItems.length; i++) {
    + 80     var result = resultItems[i];
    + 81     if (result.passed && !result.passed()) {
    + 82       var resultMessageDiv = this.createDom('div', {className: 'resultMessage fail'});
    + 83       resultMessageDiv.innerHTML = result.message; // todo: lame; mend
    + 84       specDiv.appendChild(resultMessageDiv);
    + 85       specDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
    + 86     }
    + 87   }
    + 88 
    + 89   this.suiteDivs[spec.suite.getFullName()].appendChild(specDiv);
    + 90 };
    + 91 
    + 92 jasmine.TrivialReporter.prototype.log = function() {
    + 93   console.log.apply(console, arguments);
    + 94 };
    + 95 
    + 96 jasmine.TrivialReporter.prototype.getLocation = function() {
    + 97   return this.document.location;
    + 98 };
    + 99 
    +100 jasmine.TrivialReporter.prototype.specFilter = function(spec) {
    +101   var paramMap = {};
    +102   var params = this.getLocation().search.substring(1).split('&');
    +103   for (var i = 0; i < params.length; i++) {
    +104     var p = params[i].split('=');
    +105     paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
    +106   }
    +107 
    +108   if (!paramMap["spec"]) return true;
    +109   return spec.getFullName().indexOf(paramMap["spec"]) == 0;
    +110 };
    +111 
    +112 //protect against console.log incidents
    +113 if (!("console" in window) || !("firebug" in console)) {
    +114   var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    +115   window.console = {};
    +116   for (var i = 0, len = names.length; i < len; ++i) {
    +117     window.console[names[i]] = function() {
    +118     };
    +119   }
    +120 }
    +121 
    \ No newline at end of file diff --git a/doc/symbols/src/lib_jasmine.js.html b/doc/symbols/src/lib_jasmine-0.9.0.js.html similarity index 63% rename from doc/symbols/src/lib_jasmine.js.html rename to doc/symbols/src/lib_jasmine-0.9.0.js.html index 5edd9e9..fa9b546 100644 --- a/doc/symbols/src/lib_jasmine.js.html +++ b/doc/symbols/src/lib_jasmine-0.9.0.js.html @@ -47,1891 +47,1975 @@ 40 41 jasmine.ExpectationResult = function(passed, message, details) { 42 this.type = 'ExpectationResult'; - 43 this.passed = passed; + 43 this.passed_ = passed; 44 this.message = message; 45 this.details = details; 46 this.trace = new Error(message); // todo: test better 47 }; 48 - 49 /** - 50 * Getter for the Jasmine environment. Ensures one gets created - 51 */ - 52 jasmine.getEnv = function() { - 53 return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); - 54 }; - 55 - 56 /** - 57 * @ignore - 58 * @private - 59 * @param value - 60 * @returns {Boolean} - 61 */ - 62 jasmine.isArray_ = function(value) { - 63 return value && - 64 typeof value === 'object' && - 65 typeof value.length === 'number' && - 66 typeof value.splice === 'function' && - 67 !(value.propertyIsEnumerable('length')); - 68 }; - 69 - 70 /** - 71 * Pretty printer for expecations. Takes any object and turns it into a human-readable string. - 72 * - 73 * @param value {Object} an object to be outputted - 74 * @returns {String} - 75 */ - 76 jasmine.pp = function(value) { - 77 var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); - 78 stringPrettyPrinter.format(value); - 79 return stringPrettyPrinter.string; - 80 }; - 81 - 82 /** - 83 * Returns true if the object is a DOM Node. - 84 * - 85 * @param {Object} obj object to check - 86 * @returns {Boolean} - 87 */ - 88 jasmine.isDomNode = function(obj) { - 89 return obj['nodeType'] > 0; - 90 }; - 91 - 92 /** - 93 * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - 94 * - 95 * @example - 96 * // don't care about which function is passed in, as long as it's a function - 97 * expect(mySpy).wasCalledWith(jasmine.any(Function)); + 49 jasmine.ExpectationResult.prototype.passed = function () { + 50 return this.passed_; + 51 }; + 52 + 53 /** + 54 * Getter for the Jasmine environment. Ensures one gets created + 55 */ + 56 jasmine.getEnv = function() { + 57 return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + 58 }; + 59 + 60 /** + 61 * @ignore + 62 * @private + 63 * @param value + 64 * @returns {Boolean} + 65 */ + 66 jasmine.isArray_ = function(value) { + 67 return value && + 68 typeof value === 'object' && + 69 typeof value.length === 'number' && + 70 typeof value.splice === 'function' && + 71 !(value.propertyIsEnumerable('length')); + 72 }; + 73 + 74 /** + 75 * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + 76 * + 77 * @param value {Object} an object to be outputted + 78 * @returns {String} + 79 */ + 80 jasmine.pp = function(value) { + 81 var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + 82 stringPrettyPrinter.format(value); + 83 return stringPrettyPrinter.string; + 84 }; + 85 + 86 /** + 87 * Returns true if the object is a DOM Node. + 88 * + 89 * @param {Object} obj object to check + 90 * @returns {Boolean} + 91 */ + 92 jasmine.isDomNode = function(obj) { + 93 return obj['nodeType'] > 0; + 94 }; + 95 + 96 /** + 97 * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. 98 * - 99 * @param {Class} clazz -100 * @returns matchable object of the type clazz -101 */ -102 jasmine.any = function(clazz) { -103 return new jasmine.Matchers.Any(clazz); -104 }; -105 -106 /** -107 * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. -108 * -109 * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine -110 * expectation syntax. Spies can be checked if they were called or not and what the calling params were. -111 * -112 * A Spy has the following mehtod: wasCalled, callCount, mostRecentCall, and argsForCall (see docs) -113 * Spies are torn down at the end of every spec. -114 * -115 * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. -116 * -117 * @example -118 * // a stub -119 * var myStub = jasmine.createSpy('myStub'); // can be used anywhere -120 * -121 * // spy example -122 * var foo = { -123 * not: function(bool) { return !bool; } -124 * } -125 * -126 * // actual foo.not will not be called, execution stops -127 * spyOn(foo, 'not'); -128 -129 // foo.not spied upon, execution will continue to implementation -130 * spyOn(foo, 'not').andCallThrough(); -131 * -132 * // fake example -133 * var foo = { -134 * not: function(bool) { return !bool; } -135 * } -136 * -137 * // foo.not(val) will return val -138 * spyOn(foo, 'not').andCallFake(function(value) {return value;}); -139 * -140 * // mock example -141 * foo.not(7 == 7); -142 * expect(foo.not).wasCalled(); -143 * expect(foo.not).wasCalledWith(true); -144 * -145 * @constructor -146 * @see spyOn, jasmine.createSpy, jasmine.createSpyObj -147 * @param {String} name -148 */ -149 jasmine.Spy = function(name) { -150 /** -151 * The name of the spy, if provided. -152 */ -153 this.identity = name || 'unknown'; + 99 * @example +100 * // don't care about which function is passed in, as long as it's a function +101 * expect(mySpy).wasCalledWith(jasmine.any(Function)); +102 * +103 * @param {Class} clazz +104 * @returns matchable object of the type clazz +105 */ +106 jasmine.any = function(clazz) { +107 return new jasmine.Matchers.Any(clazz); +108 }; +109 +110 /** +111 * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. +112 * +113 * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine +114 * expectation syntax. Spies can be checked if they were called or not and what the calling params were. +115 * +116 * A Spy has the following mehtod: wasCalled, callCount, mostRecentCall, and argsForCall (see docs) +117 * Spies are torn down at the end of every spec. +118 * +119 * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. +120 * +121 * @example +122 * // a stub +123 * var myStub = jasmine.createSpy('myStub'); // can be used anywhere +124 * +125 * // spy example +126 * var foo = { +127 * not: function(bool) { return !bool; } +128 * } +129 * +130 * // actual foo.not will not be called, execution stops +131 * spyOn(foo, 'not'); +132 +133 // foo.not spied upon, execution will continue to implementation +134 * spyOn(foo, 'not').andCallThrough(); +135 * +136 * // fake example +137 * var foo = { +138 * not: function(bool) { return !bool; } +139 * } +140 * +141 * // foo.not(val) will return val +142 * spyOn(foo, 'not').andCallFake(function(value) {return value;}); +143 * +144 * // mock example +145 * foo.not(7 == 7); +146 * expect(foo.not).wasCalled(); +147 * expect(foo.not).wasCalledWith(true); +148 * +149 * @constructor +150 * @see spyOn, jasmine.createSpy, jasmine.createSpyObj +151 * @param {String} name +152 */ +153 jasmine.Spy = function(name) { 154 /** -155 * Is this Object a spy? +155 * The name of the spy, if provided. 156 */ -157 this.isSpy = true; +157 this.identity = name || 'unknown'; 158 /** -159 * The acutal function this spy stubs. +159 * Is this Object a spy? 160 */ -161 this.plan = function() {}; +161 this.isSpy = true; 162 /** -163 * Tracking of the most recent call to the spy. -164 * @example -165 * var mySpy = jasmine.createSpy('foo'); -166 * mySpy(1, 2); -167 * mySpy.mostRecentCall.args = [1, 2]; -168 */ -169 this.mostRecentCall = {}; -170 -171 /** -172 * Holds arguments for each call to the spy, indexed by call count -173 * @example -174 * var mySpy = jasmine.createSpy('foo'); -175 * mySpy(1, 2); -176 * mySpy(7, 8); -177 * mySpy.mostRecentCall.args = [7, 8]; -178 * mySpy.argsForCall[0] = [1, 2]; -179 * mySpy.argsForCall[1] = [7, 8]; -180 */ -181 this.argsForCall = []; -182 }; -183 -184 /** -185 * Tells a spy to call through to the actual implemenatation. -186 * -187 * @example -188 * var foo = { -189 * bar: function() { // do some stuff } -190 * } -191 * -192 * // defining a spy on an existing property: foo.bar -193 * spyOn(foo, 'bar').andCallThrough(); -194 */ -195 jasmine.Spy.prototype.andCallThrough = function() { -196 this.plan = this.originalValue; -197 return this; -198 }; -199 -200 /** -201 * For setting the return value of a spy. -202 * -203 * @example -204 * // defining a spy from scratch: foo() returns 'baz' -205 * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); +163 * The acutal function this spy stubs. +164 */ +165 this.plan = function() {}; +166 /** +167 * Tracking of the most recent call to the spy. +168 * @example +169 * var mySpy = jasmine.createSpy('foo'); +170 * mySpy(1, 2); +171 * mySpy.mostRecentCall.args = [1, 2]; +172 */ +173 this.mostRecentCall = {}; +174 +175 /** +176 * Holds arguments for each call to the spy, indexed by call count +177 * @example +178 * var mySpy = jasmine.createSpy('foo'); +179 * mySpy(1, 2); +180 * mySpy(7, 8); +181 * mySpy.mostRecentCall.args = [7, 8]; +182 * mySpy.argsForCall[0] = [1, 2]; +183 * mySpy.argsForCall[1] = [7, 8]; +184 */ +185 this.argsForCall = []; +186 }; +187 +188 /** +189 * Tells a spy to call through to the actual implemenatation. +190 * +191 * @example +192 * var foo = { +193 * bar: function() { // do some stuff } +194 * } +195 * +196 * // defining a spy on an existing property: foo.bar +197 * spyOn(foo, 'bar').andCallThrough(); +198 */ +199 jasmine.Spy.prototype.andCallThrough = function() { +200 this.plan = this.originalValue; +201 return this; +202 }; +203 +204 /** +205 * For setting the return value of a spy. 206 * -207 * // defining a spy on an existing property: foo.bar() returns 'baz' -208 * spyOn(foo, 'bar').andReturn('baz'); -209 * -210 * @param {Object} value -211 */ -212 jasmine.Spy.prototype.andReturn = function(value) { -213 this.plan = function() { -214 return value; -215 }; -216 return this; -217 }; -218 -219 /** -220 * For throwing an exception when a spy is called. -221 * -222 * @example -223 * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' -224 * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); +207 * @example +208 * // defining a spy from scratch: foo() returns 'baz' +209 * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); +210 * +211 * // defining a spy on an existing property: foo.bar() returns 'baz' +212 * spyOn(foo, 'bar').andReturn('baz'); +213 * +214 * @param {Object} value +215 */ +216 jasmine.Spy.prototype.andReturn = function(value) { +217 this.plan = function() { +218 return value; +219 }; +220 return this; +221 }; +222 +223 /** +224 * For throwing an exception when a spy is called. 225 * -226 * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' -227 * spyOn(foo, 'bar').andThrow('baz'); -228 * -229 * @param {String} exceptionMsg -230 */ -231 jasmine.Spy.prototype.andThrow = function(exceptionMsg) { -232 this.plan = function() { -233 throw exceptionMsg; -234 }; -235 return this; -236 }; -237 -238 /** -239 * Calls an alternate implementation when a spy is called. -240 * -241 * @example -242 * var baz = function() { -243 * // do some stuff, return something -244 * } -245 * // defining a spy from scratch: foo() calls the function baz -246 * var foo = jasmine.createSpy('spy on foo').andCall(baz); -247 * -248 * // defining a spy on an existing property: foo.bar() calls an anonymnous function -249 * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); -250 * -251 * @param {Function} fakeFunc -252 */ -253 jasmine.Spy.prototype.andCallFake = function(fakeFunc) { -254 this.plan = fakeFunc; -255 return this; -256 }; -257 -258 /** -259 * Resets all of a spy's the tracking variables so that it can be used again. -260 * -261 * @example -262 * spyOn(foo, 'bar'); -263 * -264 * foo.bar(); -265 * -266 * expect(foo.bar.callCount).toEqual(1); +226 * @example +227 * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' +228 * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); +229 * +230 * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' +231 * spyOn(foo, 'bar').andThrow('baz'); +232 * +233 * @param {String} exceptionMsg +234 */ +235 jasmine.Spy.prototype.andThrow = function(exceptionMsg) { +236 this.plan = function() { +237 throw exceptionMsg; +238 }; +239 return this; +240 }; +241 +242 /** +243 * Calls an alternate implementation when a spy is called. +244 * +245 * @example +246 * var baz = function() { +247 * // do some stuff, return something +248 * } +249 * // defining a spy from scratch: foo() calls the function baz +250 * var foo = jasmine.createSpy('spy on foo').andCall(baz); +251 * +252 * // defining a spy on an existing property: foo.bar() calls an anonymnous function +253 * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); +254 * +255 * @param {Function} fakeFunc +256 */ +257 jasmine.Spy.prototype.andCallFake = function(fakeFunc) { +258 this.plan = fakeFunc; +259 return this; +260 }; +261 +262 /** +263 * Resets all of a spy's the tracking variables so that it can be used again. +264 * +265 * @example +266 * spyOn(foo, 'bar'); 267 * -268 * foo.bar.reset(); +268 * foo.bar(); 269 * -270 * expect(foo.bar.callCount).toEqual(0); -271 */ -272 jasmine.Spy.prototype.reset = function() { -273 this.wasCalled = false; -274 this.callCount = 0; -275 this.argsForCall = []; -276 this.mostRecentCall = {}; -277 }; -278 -279 jasmine.createSpy = function(name) { -280 -281 var spyObj = function() { -282 spyObj.wasCalled = true; -283 spyObj.callCount++; -284 var args = jasmine.util.argsToArray(arguments); -285 //spyObj.mostRecentCall = { -286 // object: this, -287 // args: args -288 //}; -289 spyObj.mostRecentCall.object = this; -290 spyObj.mostRecentCall.args = args; -291 spyObj.argsForCall.push(args); -292 return spyObj.plan.apply(this, arguments); -293 }; -294 -295 var spy = new jasmine.Spy(name); -296 -297 for(var prop in spy) { -298 spyObj[prop] = spy[prop]; -299 } +270 * expect(foo.bar.callCount).toEqual(1); +271 * +272 * foo.bar.reset(); +273 * +274 * expect(foo.bar.callCount).toEqual(0); +275 */ +276 jasmine.Spy.prototype.reset = function() { +277 this.wasCalled = false; +278 this.callCount = 0; +279 this.argsForCall = []; +280 this.mostRecentCall = {}; +281 }; +282 +283 jasmine.createSpy = function(name) { +284 +285 var spyObj = function() { +286 spyObj.wasCalled = true; +287 spyObj.callCount++; +288 var args = jasmine.util.argsToArray(arguments); +289 //spyObj.mostRecentCall = { +290 // object: this, +291 // args: args +292 //}; +293 spyObj.mostRecentCall.object = this; +294 spyObj.mostRecentCall.args = args; +295 spyObj.argsForCall.push(args); +296 return spyObj.plan.apply(this, arguments); +297 }; +298 +299 var spy = new jasmine.Spy(name); 300 -301 spyObj.reset(); -302 -303 return spyObj; -304 }; -305 -306 /** -307 * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something -308 * large in one call. -309 * -310 * @param {String} baseName name of spy class -311 * @param {Array} methodNames array of names of methods to make spies -312 */ -313 jasmine.createSpyObj = function(baseName, methodNames) { -314 var obj = {}; -315 for (var i = 0; i < methodNames.length; i++) { -316 obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); -317 } -318 return obj; -319 }; -320 -321 jasmine.log = function(message) { -322 jasmine.getEnv().currentSpec.getResults().log(message); +301 for(var prop in spy) { +302 spyObj[prop] = spy[prop]; +303 } +304 +305 spyObj.reset(); +306 +307 return spyObj; +308 }; +309 +310 /** +311 * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something +312 * large in one call. +313 * +314 * @param {String} baseName name of spy class +315 * @param {Array} methodNames array of names of methods to make spies +316 */ +317 jasmine.createSpyObj = function(baseName, methodNames) { +318 var obj = {}; +319 for (var i = 0; i < methodNames.length; i++) { +320 obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); +321 } +322 return obj; 323 }; 324 -325 /** -326 * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. -327 * -328 * @example -329 * // spy example -330 * var foo = { -331 * not: function(bool) { return !bool; } -332 * } -333 * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops -334 * -335 * @see jasmine.createSpy -336 * @param obj -337 * @param methodName -338 * @returns a Jasmine spy that can be chained with all spy methods -339 */ -340 var spyOn = function(obj, methodName) { -341 return jasmine.getEnv().currentSpec.spyOn(obj, methodName); -342 }; -343 -344 /** -345 * Creates a Jasmine spec that will be added to the current suite. -346 * -347 * // TODO: pending tests -348 * -349 * @example -350 * it('should be true', function() { -351 * expect(true).toEqual(true); -352 * }); -353 * -354 * @param {String} desc description of this specification -355 * @param {Function} func defines the preconditions and expectations of the spec -356 */ -357 var it = function(desc, func) { -358 return jasmine.getEnv().it(desc, func); -359 }; -360 -361 /** -362 * Creates a <em>disabled</em> Jasmine spec. -363 * -364 * A convenience method that allows existing specs to be disabled temporarily during development. -365 * -366 * @param {String} desc description of this specification -367 * @param {Function} func defines the preconditions and expectations of the spec -368 */ -369 var xit = function(desc, func) { -370 return jasmine.getEnv().xit(desc, func); -371 }; -372 -373 /** -374 * Starts a chain for a Jasmine expectation. -375 * -376 * It is passed an Object that is the actual value and should chain to one of the many -377 * jasmine.Matchers functions. -378 * -379 * @param {Object} actual Actual value to test against and expected value -380 */ -381 var expect = function(actual) { -382 return jasmine.getEnv().currentSpec.expect(actual); -383 }; -384 -385 /** -386 * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. -387 * -388 * @param {Function} func Function that defines part of a jasmine spec. -389 */ -390 var runs = function(func) { -391 jasmine.getEnv().currentSpec.runs(func); -392 }; -393 -394 /** -395 * Waits for a timeout before moving to the next runs()-defined block. -396 * @param {Number} timeout -397 */ -398 var waits = function(timeout) { -399 jasmine.getEnv().currentSpec.waits(timeout); -400 }; -401 -402 /** -403 * Waits for the latchFunction to return true before proceeding to the next runs()-defined block. -404 * -405 * @param {Number} timeout -406 * @param {Function} latchFunction -407 * @param {String} message -408 */ -409 var waitsFor = function(timeout, latchFunction, message) { -410 jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message); -411 }; -412 -413 /** -414 * A function that is called before each spec in a suite. -415 * -416 * Used for spec setup, including validating assumptions. -417 * -418 * @param {Function} beforeEachFunction -419 */ -420 var beforeEach = function(beforeEachFunction) { -421 jasmine.getEnv().beforeEach(beforeEachFunction); -422 }; -423 -424 /** -425 * A function that is called after each spec in a suite. -426 * -427 * Used for restoring any state that is hijacked during spec execution. -428 * -429 * @param {Function} afterEachFunction -430 */ -431 var afterEach = function(afterEachFunction) { -432 jasmine.getEnv().afterEach(afterEachFunction); -433 }; -434 -435 /** -436 * Defines a suite of specifications. -437 * -438 * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared -439 * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization -440 * of setup in some tests. +325 jasmine.log = function(message) { +326 jasmine.getEnv().currentSpec.getResults().log(message); +327 }; +328 +329 /** +330 * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. +331 * +332 * @example +333 * // spy example +334 * var foo = { +335 * not: function(bool) { return !bool; } +336 * } +337 * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops +338 * +339 * @see jasmine.createSpy +340 * @param obj +341 * @param methodName +342 * @returns a Jasmine spy that can be chained with all spy methods +343 */ +344 var spyOn = function(obj, methodName) { +345 return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +346 }; +347 +348 /** +349 * Creates a Jasmine spec that will be added to the current suite. +350 * +351 * // TODO: pending tests +352 * +353 * @example +354 * it('should be true', function() { +355 * expect(true).toEqual(true); +356 * }); +357 * +358 * @param {String} desc description of this specification +359 * @param {Function} func defines the preconditions and expectations of the spec +360 */ +361 var it = function(desc, func) { +362 return jasmine.getEnv().it(desc, func); +363 }; +364 +365 /** +366 * Creates a <em>disabled</em> Jasmine spec. +367 * +368 * A convenience method that allows existing specs to be disabled temporarily during development. +369 * +370 * @param {String} desc description of this specification +371 * @param {Function} func defines the preconditions and expectations of the spec +372 */ +373 var xit = function(desc, func) { +374 return jasmine.getEnv().xit(desc, func); +375 }; +376 +377 /** +378 * Starts a chain for a Jasmine expectation. +379 * +380 * It is passed an Object that is the actual value and should chain to one of the many +381 * jasmine.Matchers functions. +382 * +383 * @param {Object} actual Actual value to test against and expected value +384 */ +385 var expect = function(actual) { +386 return jasmine.getEnv().currentSpec.expect(actual); +387 }; +388 +389 /** +390 * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. +391 * +392 * @param {Function} func Function that defines part of a jasmine spec. +393 */ +394 var runs = function(func) { +395 jasmine.getEnv().currentSpec.runs(func); +396 }; +397 +398 /** +399 * Waits for a timeout before moving to the next runs()-defined block. +400 * @param {Number} timeout +401 */ +402 var waits = function(timeout) { +403 jasmine.getEnv().currentSpec.waits(timeout); +404 }; +405 +406 /** +407 * Waits for the latchFunction to return true before proceeding to the next runs()-defined block. +408 * +409 * @param {Number} timeout +410 * @param {Function} latchFunction +411 * @param {String} message +412 */ +413 var waitsFor = function(timeout, latchFunction, message) { +414 jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message); +415 }; +416 +417 /** +418 * A function that is called before each spec in a suite. +419 * +420 * Used for spec setup, including validating assumptions. +421 * +422 * @param {Function} beforeEachFunction +423 */ +424 var beforeEach = function(beforeEachFunction) { +425 jasmine.getEnv().beforeEach(beforeEachFunction); +426 }; +427 +428 /** +429 * A function that is called after each spec in a suite. +430 * +431 * Used for restoring any state that is hijacked during spec execution. +432 * +433 * @param {Function} afterEachFunction +434 */ +435 var afterEach = function(afterEachFunction) { +436 jasmine.getEnv().afterEach(afterEachFunction); +437 }; +438 +439 /** +440 * Defines a suite of specifications. 441 * -442 * @example -443 * // TODO: a simple suite -444 * -445 * // TODO: a simple suite with a nested describe block -446 * -447 * @param {String} description A string, usually the class under test. -448 * @param {Function} specDefinitions function that defines several specs. -449 */ -450 var describe = function(description, specDefinitions) { -451 return jasmine.getEnv().describe(description, specDefinitions); -452 }; -453 -454 /** -455 * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. -456 * -457 * @param {String} description A string, usually the class under test. -458 * @param {Function} specDefinitions function that defines several specs. -459 */ -460 var xdescribe = function(description, specDefinitions) { -461 return jasmine.getEnv().xdescribe(description, specDefinitions); -462 }; -463 -464 -465 jasmine.XmlHttpRequest = XMLHttpRequest; -466 -467 // Provide the XMLHttpRequest class for IE 5.x-6.x: -468 if (typeof XMLHttpRequest == "undefined") jasmine.XmlHttpRequest = function() { -469 try { -470 return new ActiveXObject("Msxml2.XMLHTTP.6.0"); -471 } catch(e) { -472 } +442 * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared +443 * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization +444 * of setup in some tests. +445 * +446 * @example +447 * // TODO: a simple suite +448 * +449 * // TODO: a simple suite with a nested describe block +450 * +451 * @param {String} description A string, usually the class under test. +452 * @param {Function} specDefinitions function that defines several specs. +453 */ +454 var describe = function(description, specDefinitions) { +455 return jasmine.getEnv().describe(description, specDefinitions); +456 }; +457 +458 /** +459 * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. +460 * +461 * @param {String} description A string, usually the class under test. +462 * @param {Function} specDefinitions function that defines several specs. +463 */ +464 var xdescribe = function(description, specDefinitions) { +465 return jasmine.getEnv().xdescribe(description, specDefinitions); +466 }; +467 +468 +469 jasmine.XmlHttpRequest = XMLHttpRequest; +470 +471 // Provide the XMLHttpRequest class for IE 5.x-6.x: +472 if (typeof XMLHttpRequest == "undefined") jasmine.XmlHttpRequest = function() { 473 try { -474 return new ActiveXObject("Msxml2.XMLHTTP.3.0"); +474 return new ActiveXObject("Msxml2.XMLHTTP.6.0"); 475 } catch(e) { 476 } 477 try { -478 return new ActiveXObject("Msxml2.XMLHTTP"); +478 return new ActiveXObject("Msxml2.XMLHTTP.3.0"); 479 } catch(e) { 480 } 481 try { -482 return new ActiveXObject("Microsoft.XMLHTTP"); +482 return new ActiveXObject("Msxml2.XMLHTTP"); 483 } catch(e) { 484 } -485 throw new Error("This browser does not support XMLHttpRequest."); -486 }; -487 -488 /** -489 * Adds suite files to an HTML document so that they are executed, thus adding them to the current -490 * Jasmine environment. -491 * -492 * @param {String} url path to the file to include -493 * @param {Boolean} opt_global -494 */ -495 jasmine.include = function(url, opt_global) { -496 if (opt_global) { -497 document.write('<script type="text/javascript" src="' + url + '"></' + 'script>'); -498 } else { -499 var xhr; -500 try { -501 xhr = new jasmine.XmlHttpRequest(); -502 xhr.open("GET", url, false); -503 xhr.send(null); -504 } catch(e) { -505 throw new Error("couldn't fetch " + url + ": " + e); -506 } -507 -508 return eval(xhr.responseText); -509 } -510 }; -511 /** -512 * @namespace -513 */ -514 jasmine.util = {}; +485 try { +486 return new ActiveXObject("Microsoft.XMLHTTP"); +487 } catch(e) { +488 } +489 throw new Error("This browser does not support XMLHttpRequest."); +490 }; +491 +492 /** +493 * Adds suite files to an HTML document so that they are executed, thus adding them to the current +494 * Jasmine environment. +495 * +496 * @param {String} url path to the file to include +497 * @param {Boolean} opt_global +498 */ +499 jasmine.include = function(url, opt_global) { +500 if (opt_global) { +501 document.write('<script type="text/javascript" src="' + url + '"></' + 'script>'); +502 } else { +503 var xhr; +504 try { +505 xhr = new jasmine.XmlHttpRequest(); +506 xhr.open("GET", url, false); +507 xhr.send(null); +508 } catch(e) { +509 throw new Error("couldn't fetch " + url + ": " + e); +510 } +511 +512 return eval(xhr.responseText); +513 } +514 }; 515 -516 /** -517 * Declare that a child class inherite it's prototype from the parent class. -518 * -519 * @private -520 * @param {Function} childClass -521 * @param {Function} parentClass -522 */ -523 jasmine.util.inherit = function(childClass, parentClass) { -524 var subclass = function() { -525 }; -526 subclass.prototype = parentClass.prototype; -527 childClass.prototype = new subclass; -528 }; -529 -530 jasmine.util.formatException = function(e) { -531 var lineNumber; -532 if (e.line) { -533 lineNumber = e.line; -534 } -535 else if (e.lineNumber) { -536 lineNumber = e.lineNumber; -537 } -538 -539 var file; +516 jasmine.version_= { +517 "major": 0, +518 "minor": 9, +519 "build": 0, +520 "revision": 1 +521 }; +522 /** +523 * @namespace +524 */ +525 jasmine.util = {}; +526 +527 /** +528 * Declare that a child class inherite it's prototype from the parent class. +529 * +530 * @private +531 * @param {Function} childClass +532 * @param {Function} parentClass +533 */ +534 jasmine.util.inherit = function(childClass, parentClass) { +535 var subclass = function() { +536 }; +537 subclass.prototype = parentClass.prototype; +538 childClass.prototype = new subclass; +539 }; 540 -541 if (e.sourceURL) { -542 file = e.sourceURL; -543 } -544 else if (e.fileName) { -545 file = e.fileName; -546 } -547 -548 var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); +541 jasmine.util.formatException = function(e) { +542 var lineNumber; +543 if (e.line) { +544 lineNumber = e.line; +545 } +546 else if (e.lineNumber) { +547 lineNumber = e.lineNumber; +548 } 549 -550 if (file && lineNumber) { -551 message += ' in ' + file + ' (line ' + lineNumber + ')'; -552 } -553 -554 return message; -555 }; -556 -557 jasmine.util.htmlEscape = function(str) { -558 if (!str) return str; -559 return str.replace(/&/g, '&') -560 .replace(/</g, '<') -561 .replace(/>/g, '>'); -562 }; -563 -564 jasmine.util.argsToArray = function(args) { -565 var arrayOfArgs = []; -566 for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); -567 return arrayOfArgs; -568 }; -569 -570 /** -571 * Environment for Jasmine -572 * -573 * @constructor -574 */ -575 jasmine.Env = function() { -576 this.currentSpec = null; -577 this.currentSuite = null; -578 this.currentRunner = new jasmine.Runner(this); -579 this.currentlyRunningTests = false; +550 var file; +551 +552 if (e.sourceURL) { +553 file = e.sourceURL; +554 } +555 else if (e.fileName) { +556 file = e.fileName; +557 } +558 +559 var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); +560 +561 if (file && lineNumber) { +562 message += ' in ' + file + ' (line ' + lineNumber + ')'; +563 } +564 +565 return message; +566 }; +567 +568 jasmine.util.htmlEscape = function(str) { +569 if (!str) return str; +570 return str.replace(/&/g, '&') +571 .replace(/</g, '<') +572 .replace(/>/g, '>'); +573 }; +574 +575 jasmine.util.argsToArray = function(args) { +576 var arrayOfArgs = []; +577 for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); +578 return arrayOfArgs; +579 }; 580 -581 this.reporter = new jasmine.MultiReporter(); -582 -583 this.updateInterval = 0; -584 this.lastUpdate = 0; -585 this.specFilter = function() { -586 return true; -587 }; -588 -589 this.nextSpecId_ = 0; -590 this.equalityTesters_ = []; -591 }; -592 +581 /** +582 * Environment for Jasmine +583 * +584 * @constructor +585 */ +586 jasmine.Env = function() { +587 this.currentSpec = null; +588 this.currentSuite = null; +589 this.currentRunner = new jasmine.Runner(this); +590 this.currentlyRunningTests = false; +591 +592 this.reporter = new jasmine.MultiReporter(); 593 -594 jasmine.Env.prototype.setTimeout = jasmine.setTimeout; -595 jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; -596 jasmine.Env.prototype.setInterval = jasmine.setInterval; -597 jasmine.Env.prototype.clearInterval = jasmine.clearInterval; -598 -599 /** -600 * Register a reporter to receive status updates from Jasmine. -601 * @param {jasmine.Reporter} reporter An object which will receive status updates. -602 */ -603 jasmine.Env.prototype.addReporter = function(reporter) { -604 this.reporter.addReporter(reporter); -605 }; -606 -607 jasmine.Env.prototype.execute = function() { -608 this.currentRunner.execute(); -609 }; +594 this.updateInterval = 0; +595 this.lastUpdate = 0; +596 this.specFilter = function() { +597 return true; +598 }; +599 +600 this.nextSpecId_ = 0; +601 this.nextSuiteId_ = 0; +602 this.equalityTesters_ = []; +603 }; +604 +605 +606 jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +607 jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +608 jasmine.Env.prototype.setInterval = jasmine.setInterval; +609 jasmine.Env.prototype.clearInterval = jasmine.clearInterval; 610 -611 jasmine.Env.prototype.describe = function(description, specDefinitions) { -612 var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); -613 -614 var parentSuite = this.currentSuite; -615 if (parentSuite) { -616 parentSuite.specs.push(suite); -617 } else { -618 this.currentRunner.suites.push(suite); -619 } -620 -621 this.currentSuite = suite; -622 -623 specDefinitions.call(suite); -624 -625 this.currentSuite = parentSuite; +611 jasmine.Env.prototype.version = function () { +612 if (jasmine.version_) { +613 return jasmine.version_; +614 } else { +615 throw new Error('Version not set'); +616 } +617 }; +618 +619 /** +620 * Register a reporter to receive status updates from Jasmine. +621 * @param {jasmine.Reporter} reporter An object which will receive status updates. +622 */ +623 jasmine.Env.prototype.addReporter = function(reporter) { +624 this.reporter.addReporter(reporter); +625 }; 626 -627 return suite; -628 }; -629 -630 jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { -631 this.currentSuite.beforeEach(beforeEachFunction); -632 }; +627 jasmine.Env.prototype.execute = function() { +628 this.currentRunner.execute(); +629 }; +630 +631 jasmine.Env.prototype.describe = function(description, specDefinitions) { +632 var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); 633 -634 jasmine.Env.prototype.afterEach = function(afterEachFunction) { -635 this.currentSuite.afterEach(afterEachFunction); -636 }; -637 -638 jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { -639 return { -640 execute: function() { -641 } -642 }; -643 }; +634 var parentSuite = this.currentSuite; +635 if (parentSuite) { +636 parentSuite.add(suite); +637 } else { +638 this.currentRunner.add(suite); +639 } +640 +641 this.currentSuite = suite; +642 +643 specDefinitions.call(suite); 644 -645 jasmine.Env.prototype.it = function(description, func) { -646 var spec = new jasmine.Spec(this, this.currentSuite, description); -647 this.currentSuite.specs.push(spec); -648 this.currentSpec = spec; +645 this.currentSuite = parentSuite; +646 +647 return suite; +648 }; 649 -650 if (func) { -651 spec.addToQueue(func); -652 } +650 jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { +651 this.currentSuite.beforeEach(beforeEachFunction); +652 }; 653 -654 return spec; -655 }; -656 -657 jasmine.Env.prototype.xit = function(desc, func) { -658 return { -659 id: this.nextSpecId_++, -660 runs: function() { +654 jasmine.Env.prototype.afterEach = function(afterEachFunction) { +655 this.currentSuite.afterEach(afterEachFunction); +656 }; +657 +658 jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { +659 return { +660 execute: function() { 661 } 662 }; 663 }; 664 -665 jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { -666 if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { -667 return true; -668 } +665 jasmine.Env.prototype.it = function(description, func) { +666 var spec = new jasmine.Spec(this, this.currentSuite, description); +667 this.currentSuite.add(spec); +668 this.currentSpec = spec; 669 -670 a.__Jasmine_been_here_before__ = b; -671 b.__Jasmine_been_here_before__ = a; -672 -673 var hasKey = function(obj, keyName) { -674 return obj != null && obj[keyName] !== undefined; -675 }; +670 if (func) { +671 spec.runs(func); +672 } +673 +674 return spec; +675 }; 676 -677 for (var property in b) { -678 if (!hasKey(a, property) && hasKey(b, property)) { -679 mismatchKeys.push("expected has key '" + property + "', but missing from <b>actual</b>."); -680 } -681 } -682 for (property in a) { -683 if (!hasKey(b, property) && hasKey(a, property)) { -684 mismatchKeys.push("<b>expected</b> missing key '" + property + "', but present in actual."); -685 } -686 } -687 for (property in b) { -688 if (property == '__Jasmine_been_here_before__') continue; -689 if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { -690 mismatchValues.push("'" + property + "' was<br /><br />'" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "'<br /><br />in expected, but was<br /><br />'" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "'<br /><br />in actual.<br />"); -691 } -692 } -693 -694 if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { -695 mismatchValues.push("arrays were not the same length"); -696 } -697 -698 delete a.__Jasmine_been_here_before__; -699 delete b.__Jasmine_been_here_before__; -700 return (mismatchKeys.length == 0 && mismatchValues.length == 0); -701 }; -702 -703 jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { -704 mismatchKeys = mismatchKeys || []; -705 mismatchValues = mismatchValues || []; -706 -707 if (a === b) return true; -708 -709 if (a === undefined || a === null || b === undefined || b === null) { -710 return (a == undefined && b == undefined); -711 } -712 -713 if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { -714 return a === b; -715 } -716 -717 if (a instanceof Date && b instanceof Date) { -718 return a.getTime() == b.getTime(); -719 } -720 -721 if (a instanceof jasmine.Matchers.Any) { -722 return a.matches(b); -723 } -724 -725 if (b instanceof jasmine.Matchers.Any) { -726 return b.matches(a); -727 } +677 jasmine.Env.prototype.xit = function(desc, func) { +678 return { +679 id: this.nextSpecId_++, +680 runs: function() { +681 } +682 }; +683 }; +684 +685 jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { +686 if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { +687 return true; +688 } +689 +690 a.__Jasmine_been_here_before__ = b; +691 b.__Jasmine_been_here_before__ = a; +692 +693 var hasKey = function(obj, keyName) { +694 return obj != null && obj[keyName] !== undefined; +695 }; +696 +697 for (var property in b) { +698 if (!hasKey(a, property) && hasKey(b, property)) { +699 mismatchKeys.push("expected has key '" + property + "', but missing from <b>actual</b>."); +700 } +701 } +702 for (property in a) { +703 if (!hasKey(b, property) && hasKey(a, property)) { +704 mismatchKeys.push("<b>expected</b> missing key '" + property + "', but present in actual."); +705 } +706 } +707 for (property in b) { +708 if (property == '__Jasmine_been_here_before__') continue; +709 if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { +710 mismatchValues.push("'" + property + "' was<br /><br />'" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "'<br /><br />in expected, but was<br /><br />'" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "'<br /><br />in actual.<br />"); +711 } +712 } +713 +714 if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { +715 mismatchValues.push("arrays were not the same length"); +716 } +717 +718 delete a.__Jasmine_been_here_before__; +719 delete b.__Jasmine_been_here_before__; +720 return (mismatchKeys.length == 0 && mismatchValues.length == 0); +721 }; +722 +723 jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { +724 mismatchKeys = mismatchKeys || []; +725 mismatchValues = mismatchValues || []; +726 +727 if (a === b) return true; 728 -729 if (typeof a === "object" && typeof b === "object") { -730 return this.compareObjects_(a, b, mismatchKeys, mismatchValues); +729 if (a === undefined || a === null || b === undefined || b === null) { +730 return (a == undefined && b == undefined); 731 } 732 -733 for (var i = 0; i < this.equalityTesters_.length; i++) { -734 var equalityTester = this.equalityTesters_[i]; -735 var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); -736 if (result !== undefined) return result; -737 } -738 -739 //Straight check -740 return (a === b); -741 }; -742 -743 jasmine.Env.prototype.contains_ = function(haystack, needle) { -744 if (jasmine.isArray_(haystack)) { -745 for (var i = 0; i < haystack.length; i++) { -746 if (this.equals_(haystack[i], needle)) return true; -747 } -748 return false; -749 } -750 return haystack.indexOf(needle) >= 0; -751 }; +733 if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { +734 return a === b; +735 } +736 +737 if (a instanceof Date && b instanceof Date) { +738 return a.getTime() == b.getTime(); +739 } +740 +741 if (a instanceof jasmine.Matchers.Any) { +742 return a.matches(b); +743 } +744 +745 if (b instanceof jasmine.Matchers.Any) { +746 return b.matches(a); +747 } +748 +749 if (typeof a === "object" && typeof b === "object") { +750 return this.compareObjects_(a, b, mismatchKeys, mismatchValues); +751 } 752 -753 jasmine.Env.prototype.addEqualityTester = function(equalityTester) { -754 this.equalityTesters_.push(equalityTester); -755 }; -756 /** -757 * base for Runner & Suite: allows for a queue of functions to get executed, allowing for -758 * any one action to complete, including asynchronous calls, before going to the next -759 * action. -760 * -761 * @constructor -762 * @param {jasmine.Env} env -763 */ -764 jasmine.ActionCollection = function(env) { -765 this.env = env; -766 this.actions = []; -767 this.index = 0; -768 this.finished = false; -769 }; -770 -771 /** -772 * Marks the collection as done & calls the finish callback, if there is one -773 */ -774 jasmine.ActionCollection.prototype.finish = function() { -775 if (this.finishCallback) { -776 this.finishCallback(); -777 } -778 this.finished = true; -779 }; -780 -781 /** -782 * Starts executing the queue of functions/actions. -783 */ -784 jasmine.ActionCollection.prototype.execute = function() { -785 if (this.actions.length > 0) { -786 this.next(); -787 } -788 }; -789 -790 /** -791 * Gets the current action. -792 */ -793 jasmine.ActionCollection.prototype.getCurrentAction = function() { -794 return this.actions[this.index]; -795 }; -796 -797 /** -798 * Executes the next queued function/action. If there are no more in the queue, calls #finish. -799 */ -800 jasmine.ActionCollection.prototype.next = function() { -801 if (this.index >= this.actions.length) { -802 this.finish(); -803 return; -804 } -805 -806 var currentAction = this.getCurrentAction(); -807 -808 currentAction.execute(this); -809 -810 if (currentAction.afterCallbacks) { -811 for (var i = 0; i < currentAction.afterCallbacks.length; i++) { -812 try { -813 currentAction.afterCallbacks[i](); -814 } catch (e) { -815 alert(e); -816 } -817 } -818 } -819 -820 this.waitForDone(currentAction); -821 }; -822 -823 jasmine.ActionCollection.prototype.waitForDone = function(action) { -824 var self = this; -825 var afterExecute = function afterExecute() { -826 self.index++; -827 self.next(); -828 }; -829 -830 if (action.finished) { -831 var now = new Date().getTime(); -832 if (this.env.updateInterval && now - this.env.lastUpdate > this.env.updateInterval) { -833 this.env.lastUpdate = now; -834 this.env.setTimeout(afterExecute, 0); -835 } else { -836 afterExecute(); -837 } -838 return; -839 } -840 -841 var id = this.env.setInterval(function() { -842 if (action.finished) { -843 self.env.clearInterval(id); -844 afterExecute(); -845 } -846 }, 150); +753 for (var i = 0; i < this.equalityTesters_.length; i++) { +754 var equalityTester = this.equalityTesters_[i]; +755 var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); +756 if (result !== undefined) return result; +757 } +758 +759 //Straight check +760 return (a === b); +761 }; +762 +763 jasmine.Env.prototype.contains_ = function(haystack, needle) { +764 if (jasmine.isArray_(haystack)) { +765 for (var i = 0; i < haystack.length; i++) { +766 if (this.equals_(haystack[i], needle)) return true; +767 } +768 return false; +769 } +770 return haystack.indexOf(needle) >= 0; +771 }; +772 +773 jasmine.Env.prototype.addEqualityTester = function(equalityTester) { +774 this.equalityTesters_.push(equalityTester); +775 }; +776 /** No-op base class for Jasmine reporters. +777 * +778 * @constructor +779 */ +780 jasmine.Reporter = function() { +781 }; +782 +783 //noinspection JSUnusedLocalSymbols +784 jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +785 }; +786 +787 //noinspection JSUnusedLocalSymbols +788 jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +789 }; +790 +791 //noinspection JSUnusedLocalSymbols +792 jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +793 }; +794 +795 //noinspection JSUnusedLocalSymbols +796 jasmine.Reporter.prototype.reportSpecResults = function(spec) { +797 }; +798 +799 //noinspection JSUnusedLocalSymbols +800 jasmine.Reporter.prototype.log = function(str) { +801 }; +802 +803 /** +804 * Blocks are functions with executable code that make up a spec. +805 * +806 * @constructor +807 * @param {jasmine.Env} env +808 * @param {Function} func +809 * @param {jasmine.Spec} spec +810 */ +811 jasmine.Block = function(env, func, spec) { +812 this.env = env; +813 this.func = func; +814 this.spec = spec; +815 }; +816 +817 jasmine.Block.prototype.execute = function(onComplete) { +818 try { +819 this.func.apply(this.spec); +820 } catch (e) { +821 this.fail(e); +822 } +823 onComplete(); +824 }; +825 +826 jasmine.Block.prototype.fail = function(e) { +827 this.spec.results.addResult(new jasmine.ExpectationResult(false, jasmine.util.formatException(e), null)); +828 }; +829 /** JavaScript API reporter. +830 * +831 * @constructor +832 */ +833 jasmine.JsApiReporter = function() { +834 this.started = false; +835 this.finished = false; +836 this.suites = []; +837 this.results = {}; +838 }; +839 +840 jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { +841 this.started = true; +842 +843 for (var i = 0; i < runner.suites.length; i++) { +844 var suite = runner.suites[i]; +845 this.suites.push(this.summarize_(suite)); +846 } 847 }; -848 /** No-op base class for Jasmine reporters. -849 * -850 * @constructor -851 */ -852 jasmine.Reporter = function() { -853 }; -854 -855 //noinspection JSUnusedLocalSymbols -856 jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { -857 }; -858 -859 //noinspection JSUnusedLocalSymbols -860 jasmine.Reporter.prototype.reportRunnerResults = function(runner) { -861 }; +848 +849 jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { +850 var summary = { +851 id: suiteOrSpec.id, +852 name: suiteOrSpec.description, +853 type: suiteOrSpec instanceof jasmine.Suite ? 'suite' : 'spec', +854 children: [] +855 }; +856 +857 if (suiteOrSpec.specs) { +858 for (var i = 0; i < suiteOrSpec.specs.length; i++) { +859 summary.children.push(this.summarize_(suiteOrSpec.specs[i])); +860 } +861 } 862 -863 //noinspection JSUnusedLocalSymbols -864 jasmine.Reporter.prototype.reportSuiteResults = function(suite) { -865 }; -866 -867 //noinspection JSUnusedLocalSymbols -868 jasmine.Reporter.prototype.reportSpecResults = function(spec) { +863 return summary; +864 }; +865 +866 //noinspection JSUnusedLocalSymbols +867 jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { +868 this.finished = true; 869 }; 870 871 //noinspection JSUnusedLocalSymbols -872 jasmine.Reporter.prototype.log = function (str) { +872 jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { 873 }; 874 -875 jasmine.Matchers = function(env, actual, results) { -876 this.env = env; -877 this.actual = actual; -878 this.passing_message = 'Passed.'; -879 this.results = results || new jasmine.NestedResults(); -880 }; -881 -882 jasmine.Matchers.pp = function(str) { -883 return jasmine.util.htmlEscape(jasmine.pp(str)); -884 }; -885 -886 jasmine.Matchers.prototype.getResults = function() { -887 return this.results; -888 }; -889 -890 jasmine.Matchers.prototype.report = function(result, failing_message, details) { -891 this.results.addResult(new jasmine.ExpectationResult(result, result ? this.passing_message : failing_message, details)); -892 return result; -893 }; -894 -895 /** -896 * Matcher that compares the actual to the expected using ===. -897 * -898 * @param expected -899 */ -900 jasmine.Matchers.prototype.toBe = function(expected) { -901 return this.report(this.actual === expected, 'Expected<br /><br />' + jasmine.Matchers.pp(expected) -902 + '<br /><br />to be the same object as<br /><br />' + jasmine.Matchers.pp(this.actual) -903 + '<br />'); -904 }; -905 -906 /** -907 * Matcher that compares the actual to the expected using !== -908 * @param expected -909 */ -910 jasmine.Matchers.prototype.toNotBe = function(expected) { -911 return this.report(this.actual !== expected, 'Expected<br /><br />' + jasmine.Matchers.pp(expected) -912 + '<br /><br />to be a different object from actual, but they were the same.'); -913 }; -914 -915 /** -916 * Matcher that compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. -917 * -918 * @param expected -919 */ -920 jasmine.Matchers.prototype.toEqual = function(expected) { -921 var mismatchKeys = []; -922 var mismatchValues = []; -923 -924 var formatMismatches = function(name, array) { -925 if (array.length == 0) return ''; -926 var errorOutput = '<br /><br />Different ' + name + ':<br />'; -927 for (var i = 0; i < array.length; i++) { -928 errorOutput += array[i] + '<br />'; -929 } -930 return errorOutput; -931 }; -932 -933 return this.report(this.env.equals_(this.actual, expected, mismatchKeys, mismatchValues), -934 'Expected<br /><br />' + jasmine.Matchers.pp(expected) -935 + '<br /><br />but got<br /><br />' + jasmine.Matchers.pp(this.actual) -936 + '<br />' -937 + formatMismatches('Keys', mismatchKeys) -938 + formatMismatches('Values', mismatchValues), { -939 matcherName: 'toEqual', expected: expected, actual: this.actual -940 }); -941 }; -942 /** @deprecated */ -943 jasmine.Matchers.prototype.should_equal = jasmine.Matchers.prototype.toEqual; +875 //noinspection JSUnusedLocalSymbols +876 jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { +877 this.results[spec.id] = { +878 messages: spec.results.getItems(), +879 result: spec.results.failedCount > 0 ? "failed" : "passed" +880 }; +881 }; +882 +883 //noinspection JSUnusedLocalSymbols +884 jasmine.JsApiReporter.prototype.log = function(str) { +885 }; +886 +887 jasmine.Matchers = function(env, actual, results) { +888 this.env = env; +889 this.actual = actual; +890 this.passing_message = 'Passed.'; +891 this.results = results || new jasmine.NestedResults(); +892 }; +893 +894 jasmine.Matchers.pp = function(str) { +895 return jasmine.util.htmlEscape(jasmine.pp(str)); +896 }; +897 +898 jasmine.Matchers.prototype.getResults = function() { +899 return this.results; +900 }; +901 +902 jasmine.Matchers.prototype.report = function(result, failing_message, details) { +903 this.results.addResult(new jasmine.ExpectationResult(result, result ? this.passing_message : failing_message, details)); +904 return result; +905 }; +906 +907 /** +908 * Matcher that compares the actual to the expected using ===. +909 * +910 * @param expected +911 */ +912 jasmine.Matchers.prototype.toBe = function(expected) { +913 return this.report(this.actual === expected, 'Expected<br /><br />' + jasmine.Matchers.pp(expected) +914 + '<br /><br />to be the same object as<br /><br />' + jasmine.Matchers.pp(this.actual) +915 + '<br />'); +916 }; +917 +918 /** +919 * Matcher that compares the actual to the expected using !== +920 * @param expected +921 */ +922 jasmine.Matchers.prototype.toNotBe = function(expected) { +923 return this.report(this.actual !== expected, 'Expected<br /><br />' + jasmine.Matchers.pp(expected) +924 + '<br /><br />to be a different object from actual, but they were the same.'); +925 }; +926 +927 /** +928 * Matcher that compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. +929 * +930 * @param expected +931 */ +932 jasmine.Matchers.prototype.toEqual = function(expected) { +933 var mismatchKeys = []; +934 var mismatchValues = []; +935 +936 var formatMismatches = function(name, array) { +937 if (array.length == 0) return ''; +938 var errorOutput = '<br /><br />Different ' + name + ':<br />'; +939 for (var i = 0; i < array.length; i++) { +940 errorOutput += array[i] + '<br />'; +941 } +942 return errorOutput; +943 }; 944 -945 /** -946 * Matcher that compares the actual to the expected using the ! of jasmine.Matchers.toEqual -947 * @param expected -948 */ -949 jasmine.Matchers.prototype.toNotEqual = function(expected) { -950 return this.report(!this.env.equals_(this.actual, expected), -951 'Expected ' + jasmine.Matchers.pp(expected) + ' to not equal ' + jasmine.Matchers.pp(this.actual) + ', but it does.'); -952 }; -953 /** @deprecated */ -954 jasmine.Matchers.prototype.should_not_equal = jasmine.Matchers.prototype.toNotEqual; -955 -956 /** -957 * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes -958 * a pattern or a String. -959 * -960 * @param reg_exp -961 */ -962 jasmine.Matchers.prototype.toMatch = function(reg_exp) { -963 return this.report((new RegExp(reg_exp).test(this.actual)), -964 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to match ' + reg_exp + '.'); -965 }; -966 /** @deprecated */ -967 jasmine.Matchers.prototype.should_match = jasmine.Matchers.prototype.toMatch; -968 -969 /** -970 * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch -971 * @param reg_exp -972 */ -973 jasmine.Matchers.prototype.toNotMatch = function(reg_exp) { -974 return this.report((!new RegExp(reg_exp).test(this.actual)), -975 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to not match ' + reg_exp + '.'); -976 }; -977 /** @deprecated */ -978 jasmine.Matchers.prototype.should_not_match = jasmine.Matchers.prototype.toNotMatch; -979 -980 /** -981 * Matcher that compares the acutal to undefined. -982 */ -983 jasmine.Matchers.prototype.toBeDefined = function() { -984 return this.report((this.actual !== undefined), -985 'Expected a value to be defined but it was undefined.'); -986 }; -987 /** @deprecated */ -988 jasmine.Matchers.prototype.should_be_defined = jasmine.Matchers.prototype.toBeDefined; -989 -990 /** -991 * Matcher that compares the actual to null. -992 * -993 */ -994 jasmine.Matchers.prototype.toBeNull = function() { -995 return this.report((this.actual === null), -996 'Expected a value to be null but it was ' + jasmine.Matchers.pp(this.actual) + '.'); -997 }; -998 /** @deprecated */ -999 jasmine.Matchers.prototype.should_be_null = jasmine.Matchers.prototype.toBeNull; -1000 -1001 /** -1002 * Matcher that boolean not-nots the actual. -1003 */ -1004 jasmine.Matchers.prototype.toBeTruthy = function() { -1005 return this.report(!!this.actual, -1006 'Expected a value to be truthy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); -1007 }; -1008 /** @deprecated */ -1009 jasmine.Matchers.prototype.should_be_truthy = jasmine.Matchers.prototype.toBeTruthy; -1010 -1011 /** -1012 * Matcher that boolean nots the actual. -1013 */ -1014 jasmine.Matchers.prototype.toBeFalsy = function() { -1015 return this.report(!this.actual, -1016 'Expected a value to be falsy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); -1017 }; -1018 /** @deprecated */ -1019 jasmine.Matchers.prototype.should_be_falsy = jasmine.Matchers.prototype.toBeFalsy; -1020 -1021 /** -1022 * Matcher that checks to see if the acutal, a Jasmine spy, was called. -1023 */ -1024 jasmine.Matchers.prototype.wasCalled = function() { -1025 if (!this.actual || !this.actual.isSpy) { -1026 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); -1027 } -1028 if (arguments.length > 0) { -1029 return this.report(false, 'wasCalled matcher does not take arguments'); -1030 } -1031 return this.report((this.actual.wasCalled), -1032 'Expected spy "' + this.actual.identity + '" to have been called, but it was not.'); -1033 }; -1034 /** @deprecated */ -1035 jasmine.Matchers.prototype.was_called = jasmine.Matchers.prototype.wasCalled; -1036 -1037 /** -1038 * Matcher that checks to see if the acutal, a Jasmine spy, was not called. -1039 */ -1040 jasmine.Matchers.prototype.wasNotCalled = function() { -1041 if (!this.actual || !this.actual.isSpy) { -1042 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); -1043 } -1044 return this.report((!this.actual.wasCalled), -1045 'Expected spy "' + this.actual.identity + '" to not have been called, but it was.'); -1046 }; -1047 /** @deprecated */ -1048 jasmine.Matchers.prototype.was_not_called = jasmine.Matchers.prototype.wasNotCalled; -1049 -1050 /** -1051 * Matcher that checks to see if the acutal, a Jasmine spy, was called with a set of parameters. -1052 * -1053 * @example -1054 * -1055 */ -1056 jasmine.Matchers.prototype.wasCalledWith = function() { -1057 if (!this.actual || !this.actual.isSpy) { -1058 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.', { -1059 matcherName: 'wasCalledWith' -1060 }); -1061 } -1062 -1063 var args = jasmine.util.argsToArray(arguments); -1064 -1065 return this.report(this.env.contains_(this.actual.argsForCall, args), -1066 'Expected ' + jasmine.Matchers.pp(this.actual.argsForCall) + ' to contain ' + jasmine.Matchers.pp(args) + ', but it does not.', { -1067 matcherName: 'wasCalledWith', expected: args, actual: this.actual.argsForCall -1068 }); -1069 }; -1070 -1071 /** -1072 * Matcher that checks that the expected item is an element in the actual Array. -1073 * -1074 * @param {Object} item -1075 */ -1076 jasmine.Matchers.prototype.toContain = function(item) { -1077 return this.report(this.env.contains_(this.actual, item), -1078 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to contain ' + jasmine.Matchers.pp(item) + ', but it does not.', { -1079 matcherName: 'toContain', expected: item, actual: this.actual +945 return this.report(this.env.equals_(this.actual, expected, mismatchKeys, mismatchValues), +946 'Expected<br /><br />' + jasmine.Matchers.pp(expected) +947 + '<br /><br />but got<br /><br />' + jasmine.Matchers.pp(this.actual) +948 + '<br />' +949 + formatMismatches('Keys', mismatchKeys) +950 + formatMismatches('Values', mismatchValues), { +951 matcherName: 'toEqual', expected: expected, actual: this.actual +952 }); +953 }; +954 /** @deprecated */ +955 jasmine.Matchers.prototype.should_equal = jasmine.Matchers.prototype.toEqual; +956 +957 /** +958 * Matcher that compares the actual to the expected using the ! of jasmine.Matchers.toEqual +959 * @param expected +960 */ +961 jasmine.Matchers.prototype.toNotEqual = function(expected) { +962 return this.report(!this.env.equals_(this.actual, expected), +963 'Expected ' + jasmine.Matchers.pp(expected) + ' to not equal ' + jasmine.Matchers.pp(this.actual) + ', but it does.'); +964 }; +965 /** @deprecated */ +966 jasmine.Matchers.prototype.should_not_equal = jasmine.Matchers.prototype.toNotEqual; +967 +968 /** +969 * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes +970 * a pattern or a String. +971 * +972 * @param reg_exp +973 */ +974 jasmine.Matchers.prototype.toMatch = function(reg_exp) { +975 return this.report((new RegExp(reg_exp).test(this.actual)), +976 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to match ' + reg_exp + '.'); +977 }; +978 /** @deprecated */ +979 jasmine.Matchers.prototype.should_match = jasmine.Matchers.prototype.toMatch; +980 +981 /** +982 * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch +983 * @param reg_exp +984 */ +985 jasmine.Matchers.prototype.toNotMatch = function(reg_exp) { +986 return this.report((!new RegExp(reg_exp).test(this.actual)), +987 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to not match ' + reg_exp + '.'); +988 }; +989 /** @deprecated */ +990 jasmine.Matchers.prototype.should_not_match = jasmine.Matchers.prototype.toNotMatch; +991 +992 /** +993 * Matcher that compares the acutal to undefined. +994 */ +995 jasmine.Matchers.prototype.toBeDefined = function() { +996 return this.report((this.actual !== undefined), +997 'Expected a value to be defined but it was undefined.'); +998 }; +999 /** @deprecated */ +1000 jasmine.Matchers.prototype.should_be_defined = jasmine.Matchers.prototype.toBeDefined; +1001 +1002 /** +1003 * Matcher that compares the actual to null. +1004 * +1005 */ +1006 jasmine.Matchers.prototype.toBeNull = function() { +1007 return this.report((this.actual === null), +1008 'Expected a value to be null but it was ' + jasmine.Matchers.pp(this.actual) + '.'); +1009 }; +1010 /** @deprecated */ +1011 jasmine.Matchers.prototype.should_be_null = jasmine.Matchers.prototype.toBeNull; +1012 +1013 /** +1014 * Matcher that boolean not-nots the actual. +1015 */ +1016 jasmine.Matchers.prototype.toBeTruthy = function() { +1017 return this.report(!!this.actual, +1018 'Expected a value to be truthy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); +1019 }; +1020 /** @deprecated */ +1021 jasmine.Matchers.prototype.should_be_truthy = jasmine.Matchers.prototype.toBeTruthy; +1022 +1023 /** +1024 * Matcher that boolean nots the actual. +1025 */ +1026 jasmine.Matchers.prototype.toBeFalsy = function() { +1027 return this.report(!this.actual, +1028 'Expected a value to be falsy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); +1029 }; +1030 /** @deprecated */ +1031 jasmine.Matchers.prototype.should_be_falsy = jasmine.Matchers.prototype.toBeFalsy; +1032 +1033 /** +1034 * Matcher that checks to see if the acutal, a Jasmine spy, was called. +1035 */ +1036 jasmine.Matchers.prototype.wasCalled = function() { +1037 if (!this.actual || !this.actual.isSpy) { +1038 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); +1039 } +1040 if (arguments.length > 0) { +1041 return this.report(false, 'wasCalled matcher does not take arguments'); +1042 } +1043 return this.report((this.actual.wasCalled), +1044 'Expected spy "' + this.actual.identity + '" to have been called, but it was not.'); +1045 }; +1046 /** @deprecated */ +1047 jasmine.Matchers.prototype.was_called = jasmine.Matchers.prototype.wasCalled; +1048 +1049 /** +1050 * Matcher that checks to see if the acutal, a Jasmine spy, was not called. +1051 */ +1052 jasmine.Matchers.prototype.wasNotCalled = function() { +1053 if (!this.actual || !this.actual.isSpy) { +1054 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); +1055 } +1056 return this.report((!this.actual.wasCalled), +1057 'Expected spy "' + this.actual.identity + '" to not have been called, but it was.'); +1058 }; +1059 /** @deprecated */ +1060 jasmine.Matchers.prototype.was_not_called = jasmine.Matchers.prototype.wasNotCalled; +1061 +1062 /** +1063 * Matcher that checks to see if the acutal, a Jasmine spy, was called with a set of parameters. +1064 * +1065 * @example +1066 * +1067 */ +1068 jasmine.Matchers.prototype.wasCalledWith = function() { +1069 if (!this.actual || !this.actual.isSpy) { +1070 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.', { +1071 matcherName: 'wasCalledWith' +1072 }); +1073 } +1074 +1075 var args = jasmine.util.argsToArray(arguments); +1076 +1077 return this.report(this.env.contains_(this.actual.argsForCall, args), +1078 'Expected ' + jasmine.Matchers.pp(this.actual.argsForCall) + ' to contain ' + jasmine.Matchers.pp(args) + ', but it does not.', { +1079 matcherName: 'wasCalledWith', expected: args, actual: this.actual.argsForCall 1080 }); 1081 }; 1082 1083 /** -1084 * Matcher that checks that the expected item is NOT an element in the actual Array. +1084 * Matcher that checks that the expected item is an element in the actual Array. 1085 * 1086 * @param {Object} item 1087 */ -1088 jasmine.Matchers.prototype.toNotContain = function(item) { -1089 return this.report(!this.env.contains_(this.actual, item), -1090 'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.'); -1091 }; -1092 -1093 /** -1094 * Matcher that checks that the expected exception was thrown by the actual. -1095 * -1096 * @param {String} expectedException -1097 */ -1098 jasmine.Matchers.prototype.toThrow = function(expectedException) { -1099 var exception = null; -1100 try { -1101 this.actual(); -1102 } catch (e) { -1103 exception = e; -1104 } -1105 if (expectedException !== undefined) { -1106 if (exception == null) { -1107 return this.report(false, "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it did not."); -1108 } -1109 return this.report( -1110 this.env.equals_( -1111 exception.message || exception, -1112 expectedException.message || expectedException), -1113 "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it threw " + jasmine.Matchers.pp(exception) + "."); -1114 } else { -1115 return this.report(exception != null, "Expected function to throw an exception, but it did not."); -1116 } -1117 }; -1118 -1119 jasmine.Matchers.Any = function(expectedClass) { -1120 this.expectedClass = expectedClass; -1121 }; -1122 -1123 jasmine.Matchers.Any.prototype.matches = function(other) { -1124 if (this.expectedClass == String) { -1125 return typeof other == 'string' || other instanceof String; +1088 jasmine.Matchers.prototype.toContain = function(item) { +1089 return this.report(this.env.contains_(this.actual, item), +1090 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to contain ' + jasmine.Matchers.pp(item) + ', but it does not.', { +1091 matcherName: 'toContain', expected: item, actual: this.actual +1092 }); +1093 }; +1094 +1095 /** +1096 * Matcher that checks that the expected item is NOT an element in the actual Array. +1097 * +1098 * @param {Object} item +1099 */ +1100 jasmine.Matchers.prototype.toNotContain = function(item) { +1101 return this.report(!this.env.contains_(this.actual, item), +1102 'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.'); +1103 }; +1104 +1105 jasmine.Matchers.prototype.toBeLessThan = function(expected) { +1106 return this.report(this.actual < expected, +1107 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to be less than ' + jasmine.Matchers.pp(expected) + ', but it was not.'); +1108 }; +1109 +1110 jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { +1111 return this.report(this.actual > expected, +1112 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to be greater than ' + jasmine.Matchers.pp(expected) + ', but it was not.'); +1113 }; +1114 +1115 /** +1116 * Matcher that checks that the expected exception was thrown by the actual. +1117 * +1118 * @param {String} expectedException +1119 */ +1120 jasmine.Matchers.prototype.toThrow = function(expectedException) { +1121 var exception = null; +1122 try { +1123 this.actual(); +1124 } catch (e) { +1125 exception = e; 1126 } -1127 -1128 if (this.expectedClass == Number) { -1129 return typeof other == 'number' || other instanceof Number; -1130 } -1131 -1132 if (this.expectedClass == Function) { -1133 return typeof other == 'function' || other instanceof Function; -1134 } -1135 -1136 if (this.expectedClass == Object) { -1137 return typeof other == 'object'; +1127 if (expectedException !== undefined) { +1128 if (exception == null) { +1129 return this.report(false, "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it did not."); +1130 } +1131 return this.report( +1132 this.env.equals_( +1133 exception.message || exception, +1134 expectedException.message || expectedException), +1135 "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it threw " + jasmine.Matchers.pp(exception) + "."); +1136 } else { +1137 return this.report(exception != null, "Expected function to throw an exception, but it did not."); 1138 } -1139 -1140 return other instanceof this.expectedClass; -1141 }; -1142 -1143 jasmine.Matchers.Any.prototype.toString = function() { -1144 return '<jasmine.any(' + this.expectedClass + ')>'; -1145 }; -1146 -1147 // Mock setTimeout, clearTimeout -1148 // Contributed by Pivotal Computer Systems, www.pivotalsf.com -1149 -1150 jasmine.FakeTimer = function() { -1151 this.reset(); -1152 -1153 var self = this; -1154 self.setTimeout = function(funcToCall, millis) { -1155 self.timeoutsMade++; -1156 self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); -1157 return self.timeoutsMade; -1158 }; -1159 -1160 self.setInterval = function(funcToCall, millis) { -1161 self.timeoutsMade++; -1162 self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); -1163 return self.timeoutsMade; -1164 }; -1165 -1166 self.clearTimeout = function(timeoutKey) { -1167 self.scheduledFunctions[timeoutKey] = undefined; -1168 }; -1169 -1170 self.clearInterval = function(timeoutKey) { -1171 self.scheduledFunctions[timeoutKey] = undefined; -1172 }; -1173 -1174 }; -1175 -1176 jasmine.FakeTimer.prototype.reset = function() { -1177 this.timeoutsMade = 0; -1178 this.scheduledFunctions = {}; -1179 this.nowMillis = 0; -1180 }; -1181 -1182 jasmine.FakeTimer.prototype.tick = function(millis) { -1183 var oldMillis = this.nowMillis; -1184 var newMillis = oldMillis + millis; -1185 this.runFunctionsWithinRange(oldMillis, newMillis); -1186 this.nowMillis = newMillis; -1187 }; -1188 -1189 jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { -1190 var scheduledFunc; -1191 var funcsToRun = []; -1192 for (var timeoutKey in this.scheduledFunctions) { -1193 scheduledFunc = this.scheduledFunctions[timeoutKey]; -1194 if (scheduledFunc != undefined && -1195 scheduledFunc.runAtMillis >= oldMillis && -1196 scheduledFunc.runAtMillis <= nowMillis) { -1197 funcsToRun.push(scheduledFunc); -1198 this.scheduledFunctions[timeoutKey] = undefined; -1199 } -1200 } -1201 -1202 if (funcsToRun.length > 0) { -1203 funcsToRun.sort(function(a, b) { -1204 return a.runAtMillis - b.runAtMillis; -1205 }); -1206 for (var i = 0; i < funcsToRun.length; ++i) { -1207 try { -1208 var funcToRun = funcsToRun[i]; -1209 this.nowMillis = funcToRun.runAtMillis; -1210 funcToRun.funcToCall(); -1211 if (funcToRun.recurring) { -1212 this.scheduleFunction(funcToRun.timeoutKey, -1213 funcToRun.funcToCall, -1214 funcToRun.millis, -1215 true); -1216 } -1217 } catch(e) { -1218 } -1219 } -1220 this.runFunctionsWithinRange(oldMillis, nowMillis); -1221 } -1222 }; -1223 -1224 jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { -1225 this.scheduledFunctions[timeoutKey] = { -1226 runAtMillis: this.nowMillis + millis, -1227 funcToCall: funcToCall, -1228 recurring: recurring, -1229 timeoutKey: timeoutKey, -1230 millis: millis -1231 }; -1232 }; -1233 -1234 -1235 jasmine.Clock = { -1236 defaultFakeTimer: new jasmine.FakeTimer(), -1237 -1238 reset: function() { -1239 jasmine.Clock.assertInstalled(); -1240 jasmine.Clock.defaultFakeTimer.reset(); -1241 }, -1242 -1243 tick: function(millis) { -1244 jasmine.Clock.assertInstalled(); -1245 jasmine.Clock.defaultFakeTimer.tick(millis); -1246 }, -1247 -1248 runFunctionsWithinRange: function(oldMillis, nowMillis) { -1249 jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); -1250 }, -1251 -1252 scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { -1253 jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); -1254 }, -1255 -1256 useMock: function() { -1257 var spec = jasmine.getEnv().currentSpec; -1258 spec.after(jasmine.Clock.uninstallMock); -1259 -1260 jasmine.Clock.installMock(); -1261 }, -1262 -1263 installMock: function() { -1264 jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; -1265 }, -1266 -1267 uninstallMock: function() { -1268 jasmine.Clock.assertInstalled(); -1269 jasmine.Clock.installed = jasmine.Clock.real; -1270 }, -1271 -1272 real: { -1273 setTimeout: window.setTimeout, -1274 clearTimeout: window.clearTimeout, -1275 setInterval: window.setInterval, -1276 clearInterval: window.clearInterval -1277 }, -1278 -1279 assertInstalled: function() { -1280 if (jasmine.Clock.installed != jasmine.Clock.defaultFakeTimer) { -1281 throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); -1282 } -1283 }, -1284 -1285 installed: null -1286 }; -1287 jasmine.Clock.installed = jasmine.Clock.real; -1288 -1289 window.setTimeout = function(funcToCall, millis) { -1290 return jasmine.Clock.installed.setTimeout.apply(this, arguments); -1291 }; -1292 -1293 window.setInterval = function(funcToCall, millis) { -1294 return jasmine.Clock.installed.setInterval.apply(this, arguments); -1295 }; -1296 -1297 window.clearTimeout = function(timeoutKey) { -1298 return jasmine.Clock.installed.clearTimeout.apply(this, arguments); -1299 }; -1300 -1301 window.clearInterval = function(timeoutKey) { -1302 return jasmine.Clock.installed.clearInterval.apply(this, arguments); -1303 }; -1304 -1305 /** -1306 * @constructor -1307 */ -1308 jasmine.MultiReporter = function() { -1309 this.subReporters_ = []; -1310 }; -1311 jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); -1312 -1313 jasmine.MultiReporter.prototype.addReporter = function(reporter) { -1314 this.subReporters_.push(reporter); -1315 }; -1316 -1317 (function() { -1318 var functionNames = ["reportRunnerStarting", "reportRunnerResults", "reportSuiteResults", "reportSpecResults", "log"]; -1319 for (var i = 0; i < functionNames.length; i++) { -1320 var functionName = functionNames[i]; -1321 jasmine.MultiReporter.prototype[functionName] = (function(functionName) { -1322 return function() { -1323 for (var j = 0; j < this.subReporters_.length; j++) { -1324 var subReporter = this.subReporters_[j]; -1325 if (subReporter[functionName]) { -1326 subReporter[functionName].apply(subReporter, arguments); -1327 } -1328 } -1329 }; -1330 })(functionName); -1331 } -1332 })(); -1333 /** -1334 * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults -1335 * -1336 * @constructor -1337 */ -1338 jasmine.NestedResults = function() { -1339 /** -1340 * The total count of results -1341 */ -1342 this.totalCount = 0; -1343 /** -1344 * Number of passed results -1345 */ -1346 this.passedCount = 0; -1347 /** -1348 * Number of failed results -1349 */ -1350 this.failedCount = 0; -1351 /** -1352 * Was this suite/spec skipped? -1353 */ -1354 this.skipped = false; -1355 /** -1356 * @ignore -1357 */ -1358 this.items_ = []; -1359 }; -1360 -1361 /** -1362 * Roll up the result counts. -1363 * -1364 * @param result -1365 */ -1366 jasmine.NestedResults.prototype.rollupCounts = function(result) { -1367 this.totalCount += result.totalCount; -1368 this.passedCount += result.passedCount; -1369 this.failedCount += result.failedCount; -1370 }; -1371 -1372 /** -1373 * Tracks a result's message. -1374 * @param message -1375 */ -1376 jasmine.NestedResults.prototype.log = function(message) { -1377 this.items_.push(new jasmine.MessageResult(message)); -1378 }; -1379 -1380 /** -1381 * Getter for the results: message & results. -1382 */ -1383 jasmine.NestedResults.prototype.getItems = function() { -1384 return this.items_; -1385 }; -1386 -1387 /** -1388 * Adds a result, tracking counts (total, passed, & failed) -1389 * @param {jasmine.ExpectationResult|jasmine.NestedResults} result -1390 */ -1391 jasmine.NestedResults.prototype.addResult = function(result) { -1392 if (result.type != 'MessageResult') { -1393 if (result.items_) { -1394 this.rollupCounts(result); -1395 } else { -1396 this.totalCount++; -1397 if (result.passed) { -1398 this.passedCount++; -1399 } else { -1400 this.failedCount++; -1401 } -1402 } -1403 } -1404 this.items_.push(result); -1405 }; -1406 -1407 /** -1408 * @returns {Boolean} True if <b>everything</b> below passed -1409 */ -1410 jasmine.NestedResults.prototype.passed = function() { -1411 return this.passedCount === this.totalCount; -1412 }; -1413 /** -1414 * Base class for pretty printing for expectation results. -1415 */ -1416 jasmine.PrettyPrinter = function() { -1417 this.ppNestLevel_ = 0; -1418 }; -1419 -1420 /** -1421 * Formats a value in a nice, human-readable string. -1422 * -1423 * @param value -1424 * @returns {String} -1425 */ -1426 jasmine.PrettyPrinter.prototype.format = function(value) { -1427 if (this.ppNestLevel_ > 40) { -1428 // return '(jasmine.pp nested too deeply!)'; -1429 throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); -1430 } -1431 -1432 this.ppNestLevel_++; -1433 try { -1434 if (value === undefined) { -1435 this.emitScalar('undefined'); -1436 } else if (value === null) { -1437 this.emitScalar('null'); -1438 } else if (value.navigator && value.frames && value.setTimeout) { -1439 this.emitScalar('<window>'); -1440 } else if (value instanceof jasmine.Matchers.Any) { -1441 this.emitScalar(value.toString()); -1442 } else if (typeof value === 'string') { -1443 this.emitScalar("'" + value + "'"); -1444 } else if (typeof value === 'function') { -1445 this.emitScalar('Function'); -1446 } else if (typeof value.nodeType === 'number') { -1447 this.emitScalar('HTMLNode'); -1448 } else if (value instanceof Date) { -1449 this.emitScalar('Date(' + value + ')'); -1450 } else if (value.__Jasmine_been_here_before__) { -1451 this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>'); -1452 } else if (jasmine.isArray_(value) || typeof value == 'object') { -1453 value.__Jasmine_been_here_before__ = true; -1454 if (jasmine.isArray_(value)) { -1455 this.emitArray(value); -1456 } else { -1457 this.emitObject(value); -1458 } -1459 delete value.__Jasmine_been_here_before__; -1460 } else { -1461 this.emitScalar(value.toString()); +1139 }; +1140 +1141 jasmine.Matchers.Any = function(expectedClass) { +1142 this.expectedClass = expectedClass; +1143 }; +1144 +1145 jasmine.Matchers.Any.prototype.matches = function(other) { +1146 if (this.expectedClass == String) { +1147 return typeof other == 'string' || other instanceof String; +1148 } +1149 +1150 if (this.expectedClass == Number) { +1151 return typeof other == 'number' || other instanceof Number; +1152 } +1153 +1154 if (this.expectedClass == Function) { +1155 return typeof other == 'function' || other instanceof Function; +1156 } +1157 +1158 if (this.expectedClass == Object) { +1159 return typeof other == 'object'; +1160 } +1161 +1162 return other instanceof this.expectedClass; +1163 }; +1164 +1165 jasmine.Matchers.Any.prototype.toString = function() { +1166 return '<jasmine.any(' + this.expectedClass + ')>'; +1167 }; +1168 +1169 /** +1170 * @constructor +1171 */ +1172 jasmine.MultiReporter = function() { +1173 this.subReporters_ = []; +1174 }; +1175 jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); +1176 +1177 jasmine.MultiReporter.prototype.addReporter = function(reporter) { +1178 this.subReporters_.push(reporter); +1179 }; +1180 +1181 (function() { +1182 var functionNames = ["reportRunnerStarting", "reportRunnerResults", "reportSuiteResults", "reportSpecResults", "log"]; +1183 for (var i = 0; i < functionNames.length; i++) { +1184 var functionName = functionNames[i]; +1185 jasmine.MultiReporter.prototype[functionName] = (function(functionName) { +1186 return function() { +1187 for (var j = 0; j < this.subReporters_.length; j++) { +1188 var subReporter = this.subReporters_[j]; +1189 if (subReporter[functionName]) { +1190 subReporter[functionName].apply(subReporter, arguments); +1191 } +1192 } +1193 }; +1194 })(functionName); +1195 } +1196 })(); +1197 /** +1198 * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults +1199 * +1200 * @constructor +1201 */ +1202 jasmine.NestedResults = function() { +1203 /** +1204 * The total count of results +1205 */ +1206 this.totalCount = 0; +1207 /** +1208 * Number of passed results +1209 */ +1210 this.passedCount = 0; +1211 /** +1212 * Number of failed results +1213 */ +1214 this.failedCount = 0; +1215 /** +1216 * Was this suite/spec skipped? +1217 */ +1218 this.skipped = false; +1219 /** +1220 * @ignore +1221 */ +1222 this.items_ = []; +1223 }; +1224 +1225 /** +1226 * Roll up the result counts. +1227 * +1228 * @param result +1229 */ +1230 jasmine.NestedResults.prototype.rollupCounts = function(result) { +1231 this.totalCount += result.totalCount; +1232 this.passedCount += result.passedCount; +1233 this.failedCount += result.failedCount; +1234 }; +1235 +1236 /** +1237 * Tracks a result's message. +1238 * @param message +1239 */ +1240 jasmine.NestedResults.prototype.log = function(message) { +1241 this.items_.push(new jasmine.MessageResult(message)); +1242 }; +1243 +1244 /** +1245 * Getter for the results: message & results. +1246 */ +1247 jasmine.NestedResults.prototype.getItems = function() { +1248 return this.items_; +1249 }; +1250 +1251 /** +1252 * Adds a result, tracking counts (total, passed, & failed) +1253 * @param {jasmine.ExpectationResult|jasmine.NestedResults} result +1254 */ +1255 jasmine.NestedResults.prototype.addResult = function(result) { +1256 if (result.type != 'MessageResult') { +1257 if (result.items_) { +1258 this.rollupCounts(result); +1259 } else { +1260 this.totalCount++; +1261 if (result.passed()) { +1262 this.passedCount++; +1263 } else { +1264 this.failedCount++; +1265 } +1266 } +1267 } +1268 this.items_.push(result); +1269 }; +1270 +1271 /** +1272 * @returns {Boolean} True if <b>everything</b> below passed +1273 */ +1274 jasmine.NestedResults.prototype.passed = function() { +1275 return this.passedCount === this.totalCount; +1276 }; +1277 /** +1278 * Base class for pretty printing for expectation results. +1279 */ +1280 jasmine.PrettyPrinter = function() { +1281 this.ppNestLevel_ = 0; +1282 }; +1283 +1284 /** +1285 * Formats a value in a nice, human-readable string. +1286 * +1287 * @param value +1288 * @returns {String} +1289 */ +1290 jasmine.PrettyPrinter.prototype.format = function(value) { +1291 if (this.ppNestLevel_ > 40) { +1292 // return '(jasmine.pp nested too deeply!)'; +1293 throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); +1294 } +1295 +1296 this.ppNestLevel_++; +1297 try { +1298 if (value === undefined) { +1299 this.emitScalar('undefined'); +1300 } else if (value === null) { +1301 this.emitScalar('null'); +1302 } else if (value.navigator && value.frames && value.setTimeout) { +1303 this.emitScalar('<window>'); +1304 } else if (value instanceof jasmine.Matchers.Any) { +1305 this.emitScalar(value.toString()); +1306 } else if (typeof value === 'string') { +1307 this.emitString(value); +1308 } else if (typeof value === 'function') { +1309 this.emitScalar('Function'); +1310 } else if (typeof value.nodeType === 'number') { +1311 this.emitScalar('HTMLNode'); +1312 } else if (value instanceof Date) { +1313 this.emitScalar('Date(' + value + ')'); +1314 } else if (value.__Jasmine_been_here_before__) { +1315 this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>'); +1316 } else if (jasmine.isArray_(value) || typeof value == 'object') { +1317 value.__Jasmine_been_here_before__ = true; +1318 if (jasmine.isArray_(value)) { +1319 this.emitArray(value); +1320 } else { +1321 this.emitObject(value); +1322 } +1323 delete value.__Jasmine_been_here_before__; +1324 } else { +1325 this.emitScalar(value.toString()); +1326 } +1327 } finally { +1328 this.ppNestLevel_--; +1329 } +1330 }; +1331 +1332 jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { +1333 for (var property in obj) { +1334 if (property == '__Jasmine_been_here_before__') continue; +1335 fn(property, obj.__lookupGetter__(property) != null); +1336 } +1337 }; +1338 +1339 jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +1340 jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +1341 jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +1342 jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; +1343 +1344 jasmine.StringPrettyPrinter = function() { +1345 jasmine.PrettyPrinter.call(this); +1346 +1347 this.string = ''; +1348 }; +1349 jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); +1350 +1351 jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { +1352 this.append(value); +1353 }; +1354 +1355 jasmine.StringPrettyPrinter.prototype.emitString = function(value) { +1356 this.append("'" + value + "'"); +1357 }; +1358 +1359 jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { +1360 this.append('[ '); +1361 for (var i = 0; i < array.length; i++) { +1362 if (i > 0) { +1363 this.append(', '); +1364 } +1365 this.format(array[i]); +1366 } +1367 this.append(' ]'); +1368 }; +1369 +1370 jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { +1371 var self = this; +1372 this.append('{ '); +1373 var first = true; +1374 +1375 this.iterateObject(obj, function(property, isGetter) { +1376 if (first) { +1377 first = false; +1378 } else { +1379 self.append(', '); +1380 } +1381 +1382 self.append(property); +1383 self.append(' : '); +1384 if (isGetter) { +1385 self.append('<getter>'); +1386 } else { +1387 self.format(obj[property]); +1388 } +1389 }); +1390 +1391 this.append(' }'); +1392 }; +1393 +1394 jasmine.StringPrettyPrinter.prototype.append = function(value) { +1395 this.string += value; +1396 }; +1397 jasmine.Queue = function(env) { +1398 this.env = env; +1399 this.blocks = []; +1400 this.running = false; +1401 this.index = 0; +1402 this.offset = 0; +1403 }; +1404 +1405 jasmine.Queue.prototype.addBefore = function (block) { +1406 this.blocks.unshift(block); +1407 }; +1408 +1409 jasmine.Queue.prototype.add = function(block) { +1410 this.blocks.push(block); +1411 }; +1412 +1413 jasmine.Queue.prototype.insertNext = function (block) { +1414 this.blocks.splice((this.index + this.offset + 1), 0, block); +1415 this.offset++; +1416 }; +1417 +1418 jasmine.Queue.prototype.start = function(onComplete) { +1419 var self = this; +1420 self.running = true; +1421 self.onComplete = onComplete; +1422 if (self.blocks[0]) { +1423 self.blocks[0].execute(function () { +1424 self._next(); +1425 }); +1426 } else { +1427 self.finish(); +1428 } +1429 }; +1430 +1431 jasmine.Queue.prototype.isRunning = function () { +1432 return this.running; +1433 }; +1434 +1435 jasmine.Queue.prototype._next = function () { +1436 var self = this; +1437 self.env.setTimeout(function () { +1438 self.offset = 0; +1439 self.index++; +1440 if (self.index < self.blocks.length) { +1441 self.blocks[self.index].execute(function () { +1442 self._next(); +1443 }); +1444 } else { +1445 self.finish(); +1446 } +1447 }, 0); +1448 }; +1449 +1450 jasmine.Queue.prototype.finish = function () { +1451 this.running = false; +1452 if (this.onComplete) { +1453 this.onComplete(); +1454 } +1455 }; +1456 +1457 jasmine.Queue.prototype.getResults = function () { +1458 var results = new jasmine.NestedResults(); +1459 for (var i = 0; i < this.blocks.length; i++) { +1460 if (this.blocks[i].getResults) { +1461 results.addResult(this.blocks[i].getResults()); 1462 } -1463 } finally { -1464 this.ppNestLevel_--; -1465 } -1466 }; +1463 } +1464 return results; +1465 }; +1466 1467 -1468 jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { -1469 for (var property in obj) { -1470 if (property == '__Jasmine_been_here_before__') continue; -1471 fn(property, obj.__lookupGetter__(property) != null); -1472 } -1473 }; -1474 -1475 jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; -1476 jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; -1477 jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; -1478 -1479 jasmine.StringPrettyPrinter = function() { -1480 jasmine.PrettyPrinter.call(this); -1481 -1482 this.string = ''; -1483 }; -1484 jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); -1485 -1486 jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { -1487 this.append(value); -1488 }; -1489 -1490 jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { -1491 this.append('[ '); -1492 for (var i = 0; i < array.length; i++) { -1493 if (i > 0) { -1494 this.append(', '); +1468 /* JasmineReporters.reporter +1469 * Base object that will get called whenever a Spec, Suite, or Runner is done. It is up to +1470 * descendants of this object to do something with the results (see json_reporter.js) +1471 */ +1472 jasmine.Reporters = {}; +1473 +1474 jasmine.Reporters.reporter = function(callbacks) { +1475 var that = { +1476 callbacks: callbacks || {}, +1477 +1478 doCallback: function(callback, results) { +1479 if (callback) { +1480 callback(results); +1481 } +1482 }, +1483 +1484 reportRunnerResults: function(runner) { +1485 that.doCallback(that.callbacks.runnerCallback, runner); +1486 }, +1487 reportSuiteResults: function(suite) { +1488 that.doCallback(that.callbacks.suiteCallback, suite); +1489 }, +1490 reportSpecResults: function(spec) { +1491 that.doCallback(that.callbacks.specCallback, spec); +1492 }, +1493 log: function (str) { +1494 if (console && console.log) console.log(str); 1495 } -1496 this.format(array[i]); -1497 } -1498 this.append(' ]'); +1496 }; +1497 +1498 return that; 1499 }; 1500 -1501 jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { -1502 var self = this; -1503 this.append('{ '); -1504 var first = true; -1505 -1506 this.iterateObject(obj, function(property, isGetter) { -1507 if (first) { -1508 first = false; -1509 } else { -1510 self.append(', '); -1511 } -1512 -1513 self.append(property); -1514 self.append(' : '); -1515 if (isGetter) { -1516 self.append('<getter>'); -1517 } else { -1518 self.format(obj[property]); -1519 } -1520 }); -1521 -1522 this.append(' }'); -1523 }; -1524 -1525 jasmine.StringPrettyPrinter.prototype.append = function(value) { -1526 this.string += value; -1527 }; -1528 /** -1529 * QueuedFunction is how ActionCollections' actions are implemented -1530 * -1531 * @constructor -1532 * @param {jasmine.Env} env -1533 * @param {Function} func -1534 * @param {Number} timeout -1535 * @param {Function} latchFunction -1536 * @param {jasmine.Spec} spec -1537 */ -1538 jasmine.QueuedFunction = function(env, func, timeout, latchFunction, spec) { -1539 this.env = env; -1540 this.func = func; -1541 this.timeout = timeout; -1542 this.latchFunction = latchFunction; -1543 this.spec = spec; -1544 -1545 this.totalTimeSpentWaitingForLatch = 0; -1546 this.latchTimeoutIncrement = 100; -1547 }; -1548 -1549 jasmine.QueuedFunction.prototype.next = function() { -1550 this.spec.finish(); // default value is to be done after one function -1551 }; -1552 -1553 jasmine.QueuedFunction.prototype.safeExecute = function() { -1554 this.env.reporter.log('>> Jasmine Running ' + this.spec.suite.description + ' ' + this.spec.description + '...'); -1555 -1556 try { -1557 this.func.apply(this.spec); -1558 } catch (e) { -1559 this.fail(e); -1560 } -1561 }; +1501 /** +1502 * Runner +1503 * +1504 * @constructor +1505 * @param {jasmine.Env} env +1506 */ +1507 jasmine.Runner = function(env) { +1508 var self = this; +1509 self.env = env; +1510 self.queue = new jasmine.Queue(env); +1511 self.suites = []; +1512 }; +1513 +1514 jasmine.Runner.prototype.execute = function() { +1515 var self = this; +1516 if (self.env.reporter.reportRunnerStarting) { +1517 self.env.reporter.reportRunnerStarting(this); +1518 } +1519 self.queue.start(function () { +1520 self.finishCallback(); +1521 }); +1522 }; +1523 +1524 jasmine.Runner.prototype.finishCallback = function() { +1525 this.env.reporter.reportRunnerResults(this); +1526 }; +1527 +1528 jasmine.Runner.prototype.addSuite = function(suite) { +1529 this.suites.push(suite); +1530 }; +1531 +1532 jasmine.Runner.prototype.add = function(block) { +1533 if (block instanceof jasmine.Suite) { +1534 this.addSuite(block); +1535 } +1536 this.queue.add(block); +1537 }; +1538 +1539 +1540 jasmine.Runner.prototype.getAllSuites = function() { +1541 return this.suites; +1542 }; +1543 +1544 jasmine.Runner.prototype.getResults = function() { +1545 return this.queue.getResults(); +1546 }; +1547 /** +1548 * Internal representation of a Jasmine specification, or test. +1549 * +1550 * @constructor +1551 * @param {jasmine.Env} env +1552 * @param {jasmine.Suite} suite +1553 * @param {String} description +1554 */ +1555 jasmine.Spec = function(env, suite, description) { +1556 var spec = this; +1557 spec.id = env.nextSpecId_++; +1558 spec.env = env; +1559 spec.suite = suite; +1560 spec.description = description; +1561 spec.queue = new jasmine.Queue(env); 1562 -1563 jasmine.QueuedFunction.prototype.execute = function() { -1564 var self = this; -1565 var executeNow = function() { -1566 self.safeExecute(); -1567 self.next(); -1568 }; -1569 -1570 var executeLater = function() { -1571 self.env.setTimeout(executeNow, self.timeout); -1572 }; -1573 -1574 var executeNowOrLater = function() { -1575 var latchFunctionResult; -1576 -1577 try { -1578 latchFunctionResult = self.latchFunction.apply(self.spec); -1579 } catch (e) { -1580 self.fail(e); -1581 self.next(); -1582 return; -1583 } +1563 spec.afterCallbacks = []; +1564 spec.spies_ = []; +1565 +1566 spec.results = new jasmine.NestedResults(); +1567 spec.results.description = description; +1568 spec.matchersClass = null; +1569 }; +1570 +1571 jasmine.Spec.prototype.getFullName = function() { +1572 return this.suite.getFullName() + ' ' + this.description + '.'; +1573 }; +1574 +1575 jasmine.Spec.prototype.getResults = function() { +1576 return this.results; +1577 }; +1578 +1579 jasmine.Spec.prototype.runs = function (func) { +1580 var block = new jasmine.Block(this.env, func, this); +1581 this.addToQueue(block); +1582 return this; +1583 }; 1584 -1585 if (latchFunctionResult) { -1586 executeNow(); -1587 } else if (self.totalTimeSpentWaitingForLatch >= self.timeout) { -1588 var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.latchFunction.description || 'something to happen'); -1589 self.fail({ -1590 name: 'timeout', -1591 message: message -1592 }); -1593 self.next(); -1594 } else { -1595 self.totalTimeSpentWaitingForLatch += self.latchTimeoutIncrement; -1596 self.env.setTimeout(executeNowOrLater, self.latchTimeoutIncrement); -1597 } -1598 }; -1599 -1600 if (this.latchFunction !== undefined) { -1601 executeNowOrLater(); -1602 } else if (this.timeout > 0) { -1603 executeLater(); -1604 } else { -1605 executeNow(); -1606 } -1607 }; -1608 -1609 jasmine.QueuedFunction.prototype.fail = function(e) { -1610 this.spec.results.addResult(new jasmine.ExpectationResult(false, jasmine.util.formatException(e), null)); -1611 }; -1612 /* JasmineReporters.reporter -1613 * Base object that will get called whenever a Spec, Suite, or Runner is done. It is up to -1614 * descendants of this object to do something with the results (see json_reporter.js) -1615 */ -1616 jasmine.Reporters = {}; -1617 -1618 jasmine.Reporters.reporter = function(callbacks) { -1619 var that = { -1620 callbacks: callbacks || {}, -1621 -1622 doCallback: function(callback, results) { -1623 if (callback) { -1624 callback(results); -1625 } -1626 }, +1585 jasmine.Spec.prototype.addToQueue = function (block) { +1586 if (this.queue.isRunning()) { +1587 this.queue.insertNext(block); +1588 } else { +1589 this.queue.add(block); +1590 } +1591 }; +1592 +1593 /** +1594 * @private +1595 * @deprecated +1596 */ +1597 jasmine.Spec.prototype.expects_that = function(actual) { +1598 return this.expect(actual); +1599 }; +1600 +1601 /** +1602 * @private +1603 */ +1604 jasmine.Spec.prototype.expect = function(actual) { +1605 return new (this.getMatchersClass_())(this.env, actual, this.results); +1606 }; +1607 +1608 jasmine.Spec.prototype.waits = function(timeout) { +1609 var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); +1610 this.addToQueue(waitsFunc); +1611 return this; +1612 }; +1613 +1614 jasmine.Spec.prototype.waitsFor = function(timeout, latchFunction, timeoutMessage) { +1615 var waitsForFunc = new jasmine.WaitsForBlock(this.env, timeout, latchFunction, timeoutMessage, this); +1616 this.addToQueue(waitsForFunc); +1617 return this; +1618 }; +1619 +1620 jasmine.Spec.prototype.failWithException = function (e) { +1621 this.results.addResult(new jasmine.ExpectationResult(false, jasmine.util.formatException(e), null)); +1622 }; +1623 +1624 jasmine.Spec.prototype.getMatchersClass_ = function() { +1625 return this.matchersClass || jasmine.Matchers; +1626 }; 1627 -1628 reportRunnerResults: function(runner) { -1629 that.doCallback(that.callbacks.runnerCallback, runner); -1630 }, -1631 reportSuiteResults: function(suite) { -1632 that.doCallback(that.callbacks.suiteCallback, suite); -1633 }, -1634 reportSpecResults: function(spec) { -1635 that.doCallback(that.callbacks.specCallback, spec); -1636 }, -1637 log: function (str) { -1638 if (console && console.log) console.log(str); -1639 } -1640 }; -1641 -1642 return that; -1643 }; -1644 -1645 /** -1646 * Runner -1647 * -1648 * @constructor -1649 * @param {jasmine.Env} env -1650 */ -1651 jasmine.Runner = function(env) { -1652 jasmine.ActionCollection.call(this, env); +1628 jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { +1629 var parent = this.getMatchersClass_(); +1630 var newMatchersClass = function() { +1631 parent.apply(this, arguments); +1632 }; +1633 jasmine.util.inherit(newMatchersClass, parent); +1634 for (var method in matchersPrototype) { +1635 newMatchersClass.prototype[method] = matchersPrototype[method]; +1636 } +1637 this.matchersClass = newMatchersClass; +1638 }; +1639 +1640 jasmine.Spec.prototype.finishCallback = function() { +1641 this.env.reporter.reportSpecResults(this); +1642 }; +1643 +1644 jasmine.Spec.prototype.finish = function(onComplete) { +1645 this.removeAllSpies(); +1646 this.finishCallback(); +1647 if (onComplete) { +1648 onComplete(); +1649 } +1650 }; +1651 +1652 jasmine.Spec.prototype.after = function(doAfter, test) { 1653 -1654 this.suites = this.actions; -1655 }; -1656 jasmine.util.inherit(jasmine.Runner, jasmine.ActionCollection); -1657 -1658 jasmine.Runner.prototype.execute = function() { -1659 if (this.env.reporter.reportRunnerStarting) { -1660 this.env.reporter.reportRunnerStarting(this); -1661 } -1662 jasmine.ActionCollection.prototype.execute.call(this); -1663 }; -1664 -1665 jasmine.Runner.prototype.finishCallback = function() { -1666 this.env.reporter.reportRunnerResults(this); -1667 }; -1668 -1669 jasmine.Runner.prototype.getResults = function() { -1670 var results = new jasmine.NestedResults(); -1671 for (var i = 0; i < this.suites.length; i++) { -1672 results.rollupCounts(this.suites[i].getResults()); -1673 } -1674 return results; -1675 }; -1676 /** -1677 * Internal representation of a Jasmine specification, or test. -1678 * -1679 * @constructor -1680 * @param {jasmine.Env} env -1681 * @param {jasmine.Suite} suite -1682 * @param {String} description -1683 */ -1684 jasmine.Spec = function(env, suite, description) { -1685 this.id = env.nextSpecId_++; -1686 this.env = env; -1687 this.suite = suite; -1688 this.description = description; -1689 this.queue = []; -1690 this.currentTimeout = 0; -1691 this.currentLatchFunction = undefined; -1692 this.finished = false; -1693 this.afterCallbacks = []; -1694 this.spies_ = []; -1695 -1696 this.results = new jasmine.NestedResults(); -1697 this.results.description = description; -1698 this.runs = this.addToQueue; -1699 this.matchersClass = null; -1700 }; -1701 -1702 jasmine.Spec.prototype.getFullName = function() { -1703 return this.suite.getFullName() + ' ' + this.description + '.'; -1704 }; -1705 -1706 jasmine.Spec.prototype.getResults = function() { -1707 return this.results; -1708 }; -1709 -1710 jasmine.Spec.prototype.addToQueue = function(func) { -1711 var queuedFunction = new jasmine.QueuedFunction(this.env, func, this.currentTimeout, this.currentLatchFunction, this); -1712 this.queue.push(queuedFunction); -1713 -1714 if (this.queue.length > 1) { -1715 var previousQueuedFunction = this.queue[this.queue.length - 2]; -1716 previousQueuedFunction.next = function() { -1717 queuedFunction.execute(); -1718 }; -1719 } -1720 -1721 this.resetTimeout(); -1722 return this; -1723 }; +1654 if (this.queue.isRunning()) { +1655 this.queue.add(new jasmine.Block(this.env, doAfter, this)); +1656 } else { +1657 this.afterCallbacks.unshift(doAfter); +1658 } +1659 }; +1660 +1661 jasmine.Spec.prototype.execute = function(onComplete) { +1662 var spec = this; +1663 if (!spec.env.specFilter(spec)) { +1664 spec.results.skipped = true; +1665 spec.finish(onComplete); +1666 return; +1667 } +1668 this.env.reporter.log('>> Jasmine Running ' + this.suite.description + ' ' + this.description + '...'); +1669 +1670 spec.env.currentSpec = spec; +1671 spec.env.currentlyRunningTests = true; +1672 +1673 spec.addBeforesAndAftersToQueue(); +1674 +1675 spec.queue.start(function () { +1676 spec.finish(onComplete); +1677 }); +1678 spec.env.currentlyRunningTests = false; +1679 }; +1680 +1681 jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { +1682 for (var suite = this.suite; suite; suite = suite.parentSuite) { +1683 if (suite.beforeQueue) { +1684 for (var i = 0; i < suite.beforeQueue.length; i++) +1685 this.queue.addBefore(new jasmine.Block(this.env, suite.beforeQueue[i], this)); +1686 } +1687 } +1688 for (i = 0; i < this.afterCallbacks.length; i++) { +1689 this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); +1690 } +1691 for (suite = this.suite; suite; suite = suite.parentSuite) { +1692 if (suite.afterQueue) { +1693 for (var j = 0; j < suite.afterQueue.length; j++) +1694 this.queue.add(new jasmine.Block(this.env, suite.afterQueue[j], this)); +1695 } +1696 } +1697 }; +1698 +1699 jasmine.Spec.prototype.explodes = function() { +1700 throw 'explodes function should not have been called'; +1701 }; +1702 +1703 jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { +1704 if (obj == undefined) { +1705 throw "spyOn could not find an object to spy upon for " + methodName + "()"; +1706 } +1707 +1708 if (!ignoreMethodDoesntExist && obj[methodName] === undefined) { +1709 throw methodName + '() method does not exist'; +1710 } +1711 +1712 if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { +1713 throw new Error(methodName + ' has already been spied upon'); +1714 } +1715 +1716 var spyObj = jasmine.createSpy(methodName); +1717 +1718 this.spies_.push(spyObj); +1719 spyObj.baseObj = obj; +1720 spyObj.methodName = methodName; +1721 spyObj.originalValue = obj[methodName]; +1722 +1723 obj[methodName] = spyObj; 1724 -1725 /** -1726 * @private -1727 * @deprecated -1728 */ -1729 jasmine.Spec.prototype.expects_that = function(actual) { -1730 return this.expect(actual); -1731 }; -1732 -1733 /** -1734 * @private -1735 */ -1736 jasmine.Spec.prototype.expect = function(actual) { -1737 return new (this.getMatchersClass_())(this.env, actual, this.results); -1738 }; -1739 -1740 /** -1741 * @private -1742 */ -1743 jasmine.Spec.prototype.waits = function(timeout) { -1744 this.currentTimeout = timeout; -1745 this.currentLatchFunction = undefined; -1746 return this; -1747 }; -1748 -1749 /** -1750 * @private -1751 */ -1752 jasmine.Spec.prototype.waitsFor = function(timeout, latchFunction, message) { -1753 this.currentTimeout = timeout; -1754 this.currentLatchFunction = latchFunction; -1755 this.currentLatchFunction.description = message; -1756 return this; -1757 }; -1758 -1759 jasmine.Spec.prototype.getMatchersClass_ = function() { -1760 return this.matchersClass || jasmine.Matchers; -1761 }; -1762 -1763 jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { -1764 var parent = this.getMatchersClass_(); -1765 var newMatchersClass = function() { -1766 parent.apply(this, arguments); -1767 }; -1768 jasmine.util.inherit(newMatchersClass, parent); -1769 for (var method in matchersPrototype) { -1770 newMatchersClass.prototype[method] = matchersPrototype[method]; -1771 } -1772 this.matchersClass = newMatchersClass; -1773 }; -1774 -1775 jasmine.Spec.prototype.resetTimeout = function() { -1776 this.currentTimeout = 0; -1777 this.currentLatchFunction = undefined; -1778 }; -1779 -1780 jasmine.Spec.prototype.finishCallback = function() { -1781 this.env.reporter.reportSpecResults(this); -1782 }; -1783 -1784 jasmine.Spec.prototype.finish = function() { -1785 this.safeExecuteAfters(); +1725 return spyObj; +1726 }; +1727 +1728 jasmine.Spec.prototype.removeAllSpies = function() { +1729 for (var i = 0; i < this.spies_.length; i++) { +1730 var spy = this.spies_[i]; +1731 spy.baseObj[spy.methodName] = spy.originalValue; +1732 } +1733 this.spies_ = []; +1734 }; +1735 +1736 /** +1737 * Internal representation of a Jasmine suite. +1738 * +1739 * @constructor +1740 * @param {jasmine.Env} env +1741 * @param {String} description +1742 * @param {Function} specDefinitions +1743 * @param {jasmine.Suite} parentSuite +1744 */ +1745 jasmine.Suite = function(env, description, specDefinitions, parentSuite) { +1746 var self = this; +1747 self.id = env.nextSuiteId_++; +1748 self.description = description; +1749 self.queue = new jasmine.Queue(env); +1750 self.parentSuite = parentSuite; +1751 self.env = env; +1752 self.beforeQueue = []; +1753 self.afterQueue = []; +1754 self.specs = []; +1755 }; +1756 +1757 jasmine.Suite.prototype.getFullName = function() { +1758 var fullName = this.description; +1759 for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { +1760 fullName = parentSuite.description + ' ' + fullName; +1761 } +1762 return fullName; +1763 }; +1764 +1765 jasmine.Suite.prototype.finish = function(onComplete) { +1766 this.env.reporter.reportSuiteResults(this); +1767 this.finished = true; +1768 if (typeof(onComplete) == 'function') { +1769 onComplete(); +1770 } +1771 }; +1772 +1773 jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { +1774 beforeEachFunction.typeName = 'beforeEach'; +1775 this.beforeQueue.push(beforeEachFunction); +1776 }; +1777 +1778 jasmine.Suite.prototype.afterEach = function(afterEachFunction) { +1779 afterEachFunction.typeName = 'afterEach'; +1780 this.afterQueue.push(afterEachFunction); +1781 }; +1782 +1783 jasmine.Suite.prototype.getResults = function() { +1784 return this.queue.getResults(); +1785 }; 1786 -1787 this.removeAllSpies(); -1788 this.finishCallback(); -1789 this.finished = true; -1790 }; -1791 -1792 jasmine.Spec.prototype.after = function(doAfter) { -1793 this.afterCallbacks.unshift(doAfter); -1794 }; -1795 -1796 jasmine.Spec.prototype.execute = function() { -1797 if (!this.env.specFilter(this)) { -1798 this.results.skipped = true; -1799 this.finishCallback(); -1800 this.finished = true; -1801 return; -1802 } -1803 -1804 this.env.currentSpec = this; -1805 this.env.currentlyRunningTests = true; -1806 -1807 this.safeExecuteBefores(); -1808 -1809 if (this.queue[0]) { -1810 this.queue[0].execute(); -1811 } else { -1812 this.finish(); -1813 } -1814 this.env.currentlyRunningTests = false; -1815 }; -1816 -1817 jasmine.Spec.prototype.safeExecuteBefores = function() { -1818 var befores = []; -1819 for (var suite = this.suite; suite; suite = suite.parentSuite) { -1820 if (suite.beforeEachFunction) befores.push(suite.beforeEachFunction); -1821 } -1822 -1823 while (befores.length) { -1824 this.safeExecuteBeforeOrAfter(befores.pop()); -1825 } -1826 }; +1787 jasmine.Suite.prototype.add = function(block) { +1788 if (block instanceof jasmine.Suite) { +1789 this.env.currentRunner.addSuite(block); +1790 } +1791 this.specs.push(block); +1792 this.queue.add(block); +1793 }; +1794 +1795 jasmine.Suite.prototype.specCount = function(block) { +1796 return this.specs.length; +1797 }; +1798 +1799 jasmine.Suite.prototype.execute = function(onComplete) { +1800 var self = this; +1801 this.queue.start(function () { +1802 self.finish(onComplete); +1803 }); +1804 }; +1805 jasmine.WaitsBlock = function(env, timeout, spec) { +1806 this.timeout = timeout; +1807 jasmine.Block.call(this, env, null, spec); +1808 }; +1809 +1810 jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); +1811 +1812 jasmine.WaitsBlock.prototype.execute = function (onComplete) { +1813 this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); +1814 this.env.setTimeout(function () { +1815 onComplete(); +1816 }, this.timeout); +1817 }; +1818 jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { +1819 this.timeout = timeout; +1820 this.latchFunction = latchFunction; +1821 this.message = message; +1822 this.totalTimeSpentWaitingForLatch = 0; +1823 jasmine.Block.call(this, env, null, spec); +1824 }; +1825 +1826 jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); 1827 -1828 jasmine.Spec.prototype.safeExecuteAfters = function() { -1829 for (var suite = this.suite; suite; suite = suite.parentSuite) { -1830 if (suite.afterEachFunction) this.safeExecuteBeforeOrAfter(suite.afterEachFunction); -1831 } -1832 }; -1833 -1834 jasmine.Spec.prototype.safeExecuteBeforeOrAfter = function(func) { -1835 try { -1836 func.apply(this); -1837 } catch (e) { -1838 this.results.addResult(new jasmine.ExpectationResult(false, func.typeName + '() fail: ' + jasmine.util.formatException(e), null)); -1839 } -1840 }; +1828 jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 100; +1829 +1830 jasmine.WaitsForBlock.prototype.execute = function (onComplete) { +1831 var self = this; +1832 self.env.reporter.log('>> Jasmine waiting for ' + (self.message || 'something to happen')); +1833 var latchFunctionResult; +1834 try { +1835 latchFunctionResult = self.latchFunction.apply(self.spec); +1836 } catch (e) { +1837 self.fail(e); +1838 onComplete(); +1839 return; +1840 } 1841 -1842 jasmine.Spec.prototype.explodes = function() { -1843 throw 'explodes function should not have been called'; -1844 }; -1845 -1846 jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { -1847 if (obj == undefined) { -1848 throw "spyOn could not find an object to spy upon for " + methodName + "()"; -1849 } -1850 -1851 if (!ignoreMethodDoesntExist && obj[methodName] === undefined) { -1852 throw methodName + '() method does not exist'; -1853 } -1854 -1855 if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { -1856 throw new Error(methodName + ' has already been spied upon'); -1857 } -1858 -1859 var spyObj = jasmine.createSpy(methodName); -1860 -1861 this.spies_.push(spyObj); -1862 spyObj.baseObj = obj; -1863 spyObj.methodName = methodName; -1864 spyObj.originalValue = obj[methodName]; -1865 -1866 obj[methodName] = spyObj; -1867 -1868 return spyObj; -1869 }; -1870 -1871 jasmine.Spec.prototype.removeAllSpies = function() { -1872 for (var i = 0; i < this.spies_.length; i++) { -1873 var spy = this.spies_[i]; -1874 spy.baseObj[spy.methodName] = spy.originalValue; -1875 } -1876 this.spies_ = []; -1877 }; -1878 -1879 /** -1880 * Internal representation of a Jasmine suite. -1881 * -1882 * @constructor -1883 * @param {jasmine.Env} env -1884 * @param {String} description -1885 * @param {Function} specDefinitions -1886 * @param {jasmine.Suite} parentSuite -1887 */ -1888 jasmine.Suite = function(env, description, specDefinitions, parentSuite) { -1889 jasmine.ActionCollection.call(this, env); -1890 -1891 this.description = description; -1892 this.specs = this.actions; -1893 this.parentSuite = parentSuite; -1894 -1895 this.beforeEachFunction = null; -1896 this.afterEachFunction = null; -1897 }; -1898 jasmine.util.inherit(jasmine.Suite, jasmine.ActionCollection); -1899 -1900 jasmine.Suite.prototype.getFullName = function() { -1901 var fullName = this.description; -1902 for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { -1903 fullName = parentSuite.description + ' ' + fullName; -1904 } -1905 return fullName; -1906 }; -1907 -1908 jasmine.Suite.prototype.finishCallback = function() { -1909 this.env.reporter.reportSuiteResults(this); -1910 }; -1911 -1912 jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { -1913 beforeEachFunction.typeName = 'beforeEach'; -1914 this.beforeEachFunction = beforeEachFunction; -1915 }; -1916 -1917 jasmine.Suite.prototype.afterEach = function(afterEachFunction) { -1918 afterEachFunction.typeName = 'afterEach'; -1919 this.afterEachFunction = afterEachFunction; -1920 }; -1921 -1922 jasmine.Suite.prototype.getResults = function() { -1923 var results = new jasmine.NestedResults(); -1924 for (var i = 0; i < this.specs.length; i++) { -1925 results.rollupCounts(this.specs[i].getResults()); -1926 } -1927 return results; -1928 }; -1929 -1930 \ No newline at end of file +1842 if (latchFunctionResult) { +1843 onComplete(); +1844 } else if (self.totalTimeSpentWaitingForLatch >= self.timeout) { +1845 var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.message || 'something to happen'); +1846 self.fail({ +1847 name: 'timeout', +1848 message: message +1849 }); +1850 self.spec._next(); +1851 } else { +1852 self.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; +1853 self.env.setTimeout(function () { self.execute(onComplete); }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); +1854 } +1855 }; +1856 // Mock setTimeout, clearTimeout +1857 // Contributed by Pivotal Computer Systems, www.pivotalsf.com +1858 +1859 jasmine.FakeTimer = function() { +1860 this.reset(); +1861 +1862 var self = this; +1863 self.setTimeout = function(funcToCall, millis) { +1864 self.timeoutsMade++; +1865 self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); +1866 return self.timeoutsMade; +1867 }; +1868 +1869 self.setInterval = function(funcToCall, millis) { +1870 self.timeoutsMade++; +1871 self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); +1872 return self.timeoutsMade; +1873 }; +1874 +1875 self.clearTimeout = function(timeoutKey) { +1876 self.scheduledFunctions[timeoutKey] = undefined; +1877 }; +1878 +1879 self.clearInterval = function(timeoutKey) { +1880 self.scheduledFunctions[timeoutKey] = undefined; +1881 }; +1882 +1883 }; +1884 +1885 jasmine.FakeTimer.prototype.reset = function() { +1886 this.timeoutsMade = 0; +1887 this.scheduledFunctions = {}; +1888 this.nowMillis = 0; +1889 }; +1890 +1891 jasmine.FakeTimer.prototype.tick = function(millis) { +1892 var oldMillis = this.nowMillis; +1893 var newMillis = oldMillis + millis; +1894 this.runFunctionsWithinRange(oldMillis, newMillis); +1895 this.nowMillis = newMillis; +1896 }; +1897 +1898 jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { +1899 var scheduledFunc; +1900 var funcsToRun = []; +1901 for (var timeoutKey in this.scheduledFunctions) { +1902 scheduledFunc = this.scheduledFunctions[timeoutKey]; +1903 if (scheduledFunc != undefined && +1904 scheduledFunc.runAtMillis >= oldMillis && +1905 scheduledFunc.runAtMillis <= nowMillis) { +1906 funcsToRun.push(scheduledFunc); +1907 this.scheduledFunctions[timeoutKey] = undefined; +1908 } +1909 } +1910 +1911 if (funcsToRun.length > 0) { +1912 funcsToRun.sort(function(a, b) { +1913 return a.runAtMillis - b.runAtMillis; +1914 }); +1915 for (var i = 0; i < funcsToRun.length; ++i) { +1916 try { +1917 var funcToRun = funcsToRun[i]; +1918 this.nowMillis = funcToRun.runAtMillis; +1919 funcToRun.funcToCall(); +1920 if (funcToRun.recurring) { +1921 this.scheduleFunction(funcToRun.timeoutKey, +1922 funcToRun.funcToCall, +1923 funcToRun.millis, +1924 true); +1925 } +1926 } catch(e) { +1927 } +1928 } +1929 this.runFunctionsWithinRange(oldMillis, nowMillis); +1930 } +1931 }; +1932 +1933 jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { +1934 this.scheduledFunctions[timeoutKey] = { +1935 runAtMillis: this.nowMillis + millis, +1936 funcToCall: funcToCall, +1937 recurring: recurring, +1938 timeoutKey: timeoutKey, +1939 millis: millis +1940 }; +1941 }; +1942 +1943 +1944 jasmine.Clock = { +1945 defaultFakeTimer: new jasmine.FakeTimer(), +1946 +1947 reset: function() { +1948 jasmine.Clock.assertInstalled(); +1949 jasmine.Clock.defaultFakeTimer.reset(); +1950 }, +1951 +1952 tick: function(millis) { +1953 jasmine.Clock.assertInstalled(); +1954 jasmine.Clock.defaultFakeTimer.tick(millis); +1955 }, +1956 +1957 runFunctionsWithinRange: function(oldMillis, nowMillis) { +1958 jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); +1959 }, +1960 +1961 scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { +1962 jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); +1963 }, +1964 +1965 useMock: function() { +1966 var spec = jasmine.getEnv().currentSpec; +1967 spec.after(jasmine.Clock.uninstallMock); +1968 +1969 jasmine.Clock.installMock(); +1970 }, +1971 +1972 installMock: function() { +1973 jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; +1974 }, +1975 +1976 uninstallMock: function() { +1977 jasmine.Clock.assertInstalled(); +1978 jasmine.Clock.installed = jasmine.Clock.real; +1979 }, +1980 +1981 real: { +1982 setTimeout: window.setTimeout, +1983 clearTimeout: window.clearTimeout, +1984 setInterval: window.setInterval, +1985 clearInterval: window.clearInterval +1986 }, +1987 +1988 assertInstalled: function() { +1989 if (jasmine.Clock.installed != jasmine.Clock.defaultFakeTimer) { +1990 throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); +1991 } +1992 }, +1993 +1994 installed: null +1995 }; +1996 jasmine.Clock.installed = jasmine.Clock.real; +1997 +1998 window.setTimeout = function(funcToCall, millis) { +1999 return jasmine.Clock.installed.setTimeout.apply(this, arguments); +2000 }; +2001 +2002 window.setInterval = function(funcToCall, millis) { +2003 return jasmine.Clock.installed.setInterval.apply(this, arguments); +2004 }; +2005 +2006 window.clearTimeout = function(timeoutKey) { +2007 return jasmine.Clock.installed.clearTimeout.apply(this, arguments); +2008 }; +2009 +2010 window.clearInterval = function(timeoutKey) { +2011 return jasmine.Clock.installed.clearInterval.apply(this, arguments); +2012 }; +2013 +2014 \ No newline at end of file diff --git a/doc/symbols/src/lib_json2.js.html b/doc/symbols/src/lib_json2.js.html new file mode 100644 index 0000000..59b08d2 --- /dev/null +++ b/doc/symbols/src/lib_json2.js.html @@ -0,0 +1,486 @@ +
      1 /*
    +  2     http://www.JSON.org/json2.js
    +  3     2008-11-19
    +  4 
    +  5     Public Domain.
    +  6 
    +  7     NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
    +  8 
    +  9     See http://www.JSON.org/js.html
    + 10 
    + 11     This file creates a global JSON object containing two methods: stringify
    + 12     and parse.
    + 13 
    + 14         JSON.stringify(value, replacer, space)
    + 15             value       any JavaScript value, usually an object or array.
    + 16 
    + 17             replacer    an optional parameter that determines how object
    + 18                         values are stringified for objects. It can be a
    + 19                         function or an array of strings.
    + 20 
    + 21             space       an optional parameter that specifies the indentation
    + 22                         of nested structures. If it is omitted, the text will
    + 23                         be packed without extra whitespace. If it is a number,
    + 24                         it will specify the number of spaces to indent at each
    + 25                         level. If it is a string (such as '\t' or ' '),
    + 26                         it contains the characters used to indent at each level.
    + 27 
    + 28             This method produces a JSON text from a JavaScript value.
    + 29 
    + 30             When an object value is found, if the object contains a toJSON
    + 31             method, its toJSON method will be called and the result will be
    + 32             stringified. A toJSON method does not serialize: it returns the
    + 33             value represented by the name/value pair that should be serialized,
    + 34             or undefined if nothing should be serialized. The toJSON method
    + 35             will be passed the key associated with the value, and this will be
    + 36             bound to the object holding the key.
    + 37 
    + 38             For example, this would serialize Dates as ISO strings.
    + 39 
    + 40                 Date.prototype.toJSON = function (key) {
    + 41                     function f(n) {
    + 42                         // Format integers to have at least two digits.
    + 43                         return n < 10 ? '0' + n : n;
    + 44                     }
    + 45 
    + 46                     return this.getUTCFullYear()   + '-' +
    + 47                          f(this.getUTCMonth() + 1) + '-' +
    + 48                          f(this.getUTCDate())      + 'T' +
    + 49                          f(this.getUTCHours())     + ':' +
    + 50                          f(this.getUTCMinutes())   + ':' +
    + 51                          f(this.getUTCSeconds())   + 'Z';
    + 52                 };
    + 53 
    + 54             You can provide an optional replacer method. It will be passed the
    + 55             key and value of each member, with this bound to the containing
    + 56             object. The value that is returned from your method will be
    + 57             serialized. If your method returns undefined, then the member will
    + 58             be excluded from the serialization.
    + 59 
    + 60             If the replacer parameter is an array of strings, then it will be
    + 61             used to select the members to be serialized. It filters the results
    + 62             such that only members with keys listed in the replacer array are
    + 63             stringified.
    + 64 
    + 65             Values that do not have JSON representations, such as undefined or
    + 66             functions, will not be serialized. Such values in objects will be
    + 67             dropped; in arrays they will be replaced with null. You can use
    + 68             a replacer function to replace those with JSON values.
    + 69             JSON.stringify(undefined) returns undefined.
    + 70 
    + 71             The optional space parameter produces a stringification of the
    + 72             value that is filled with line breaks and indentation to make it
    + 73             easier to read.
    + 74 
    + 75             If the space parameter is a non-empty string, then that string will
    + 76             be used for indentation. If the space parameter is a number, then
    + 77             the indentation will be that many spaces.
    + 78 
    + 79             Example:
    + 80 
    + 81             text = JSON.stringify(['e', {pluribus: 'unum'}]);
    + 82             // text is '["e",{"pluribus":"unum"}]'
    + 83 
    + 84 
    + 85             text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
    + 86             // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
    + 87 
    + 88             text = JSON.stringify([new Date()], function (key, value) {
    + 89                 return this[key] instanceof Date ?
    + 90                     'Date(' + this[key] + ')' : value;
    + 91             });
    + 92             // text is '["Date(---current time---)"]'
    + 93 
    + 94 
    + 95         JSON.parse(text, reviver)
    + 96             This method parses a JSON text to produce an object or array.
    + 97             It can throw a SyntaxError exception.
    + 98 
    + 99             The optional reviver parameter is a function that can filter and
    +100             transform the results. It receives each of the keys and values,
    +101             and its return value is used instead of the original value.
    +102             If it returns what it received, then the structure is not modified.
    +103             If it returns undefined then the member is deleted.
    +104 
    +105             Example:
    +106 
    +107             // Parse the text. Values that look like ISO date strings will
    +108             // be converted to Date objects.
    +109 
    +110             myData = JSON.parse(text, function (key, value) {
    +111                 var a;
    +112                 if (typeof value === 'string') {
    +113                     a =
    +114 /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
    +115                     if (a) {
    +116                         return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
    +117                             +a[5], +a[6]));
    +118                     }
    +119                 }
    +120                 return value;
    +121             });
    +122 
    +123             myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
    +124                 var d;
    +125                 if (typeof value === 'string' &&
    +126                         value.slice(0, 5) === 'Date(' &&
    +127                         value.slice(-1) === ')') {
    +128                     d = new Date(value.slice(5, -1));
    +129                     if (d) {
    +130                         return d;
    +131                     }
    +132                 }
    +133                 return value;
    +134             });
    +135 
    +136 
    +137     This is a reference implementation. You are free to copy, modify, or
    +138     redistribute.
    +139 
    +140     This code should be minified before deployment.
    +141     See http://javascript.crockford.com/jsmin.html
    +142 
    +143     USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    +144     NOT CONTROL.
    +145 */
    +146 
    +147 /*jslint evil: true */
    +148 
    +149 /*global JSON */
    +150 
    +151 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    +152     call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    +153     getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    +154     lastIndex, length, parse, prototype, push, replace, slice, stringify,
    +155     test, toJSON, toString, valueOf
    +156 */
    +157 
    +158 // Create a JSON object only if one does not already exist. We create the
    +159 // methods in a closure to avoid creating global variables.
    +160 
    +161 if (!this.JSON) {
    +162     JSON = {};
    +163 }
    +164 (function () {
    +165 
    +166     function f(n) {
    +167         // Format integers to have at least two digits.
    +168         return n < 10 ? '0' + n : n;
    +169     }
    +170 
    +171     if (typeof Date.prototype.toJSON !== 'function') {
    +172 
    +173         Date.prototype.toJSON = function (key) {
    +174 
    +175             return this.getUTCFullYear()   + '-' +
    +176                  f(this.getUTCMonth() + 1) + '-' +
    +177                  f(this.getUTCDate())      + 'T' +
    +178                  f(this.getUTCHours())     + ':' +
    +179                  f(this.getUTCMinutes())   + ':' +
    +180                  f(this.getUTCSeconds())   + 'Z';
    +181         };
    +182 
    +183         String.prototype.toJSON =
    +184         Number.prototype.toJSON =
    +185         Boolean.prototype.toJSON = function (key) {
    +186             return this.valueOf();
    +187         };
    +188     }
    +189 
    +190     var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
    +191         escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
    +192         gap,
    +193         indent,
    +194         meta = {    // table of character substitutions
    +195             '\b': '\\b',
    +196             '\t': '\\t',
    +197             '\n': '\\n',
    +198             '\f': '\\f',
    +199             '\r': '\\r',
    +200             '"' : '\\"',
    +201             '\\': '\\\\'
    +202         },
    +203         rep;
    +204 
    +205 
    +206     function quote(string) {
    +207 
    +208 // If the string contains no control characters, no quote characters, and no
    +209 // backslash characters, then we can safely slap some quotes around it.
    +210 // Otherwise we must also replace the offending characters with safe escape
    +211 // sequences.
    +212 
    +213         escapable.lastIndex = 0;
    +214         return escapable.test(string) ?
    +215             '"' + string.replace(escapable, function (a) {
    +216                 var c = meta[a];
    +217                 return typeof c === 'string' ? c :
    +218                     '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
    +219             }) + '"' :
    +220             '"' + string + '"';
    +221     }
    +222 
    +223 
    +224     function str(key, holder) {
    +225 
    +226 // Produce a string from holder[key].
    +227 
    +228         var i,          // The loop counter.
    +229             k,          // The member key.
    +230             v,          // The member value.
    +231             length,
    +232             mind = gap,
    +233             partial,
    +234             value = holder[key];
    +235 
    +236 // If the value has a toJSON method, call it to obtain a replacement value.
    +237 
    +238         if (value && typeof value === 'object' &&
    +239                 typeof value.toJSON === 'function') {
    +240             value = value.toJSON(key);
    +241         }
    +242 
    +243 // If we were called with a replacer function, then call the replacer to
    +244 // obtain a replacement value.
    +245 
    +246         if (typeof rep === 'function') {
    +247             value = rep.call(holder, key, value);
    +248         }
    +249 
    +250 // What happens next depends on the value's type.
    +251 
    +252         switch (typeof value) {
    +253         case 'string':
    +254             return quote(value);
    +255 
    +256         case 'number':
    +257 
    +258 // JSON numbers must be finite. Encode non-finite numbers as null.
    +259 
    +260             return isFinite(value) ? String(value) : 'null';
    +261 
    +262         case 'boolean':
    +263         case 'null':
    +264 
    +265 // If the value is a boolean or null, convert it to a string. Note:
    +266 // typeof null does not produce 'null'. The case is included here in
    +267 // the remote chance that this gets fixed someday.
    +268 
    +269             return String(value);
    +270 
    +271 // If the type is 'object', we might be dealing with an object or an array or
    +272 // null.
    +273 
    +274         case 'object':
    +275 
    +276 // Due to a specification blunder in ECMAScript, typeof null is 'object',
    +277 // so watch out for that case.
    +278 
    +279             if (!value) {
    +280                 return 'null';
    +281             }
    +282 
    +283 // Make an array to hold the partial results of stringifying this object value.
    +284 
    +285             gap += indent;
    +286             partial = [];
    +287 
    +288 // Is the value an array?
    +289 
    +290             if (Object.prototype.toString.apply(value) === '[object Array]') {
    +291 
    +292 // The value is an array. Stringify every element. Use null as a placeholder
    +293 // for non-JSON values.
    +294 
    +295                 length = value.length;
    +296                 for (i = 0; i < length; i += 1) {
    +297                     partial[i] = str(i, value) || 'null';
    +298                 }
    +299 
    +300 // Join all of the elements together, separated with commas, and wrap them in
    +301 // brackets.
    +302 
    +303                 v = partial.length === 0 ? '[]' :
    +304                     gap ? '[\n' + gap +
    +305                             partial.join(',\n' + gap) + '\n' +
    +306                                 mind + ']' :
    +307                           '[' + partial.join(',') + ']';
    +308                 gap = mind;
    +309                 return v;
    +310             }
    +311 
    +312 // If the replacer is an array, use it to select the members to be stringified.
    +313 
    +314             if (rep && typeof rep === 'object') {
    +315                 length = rep.length;
    +316                 for (i = 0; i < length; i += 1) {
    +317                     k = rep[i];
    +318                     if (typeof k === 'string') {
    +319                         v = str(k, value);
    +320                         if (v) {
    +321                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
    +322                         }
    +323                     }
    +324                 }
    +325             } else {
    +326 
    +327 // Otherwise, iterate through all of the keys in the object.
    +328 
    +329                 for (k in value) {
    +330                     if (Object.hasOwnProperty.call(value, k)) {
    +331                         v = str(k, value);
    +332                         if (v) {
    +333                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
    +334                         }
    +335                     }
    +336                 }
    +337             }
    +338 
    +339 // Join all of the member texts together, separated with commas,
    +340 // and wrap them in braces.
    +341 
    +342             v = partial.length === 0 ? '{}' :
    +343                 gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
    +344                         mind + '}' : '{' + partial.join(',') + '}';
    +345             gap = mind;
    +346             return v;
    +347         }
    +348     }
    +349 
    +350 // If the JSON object does not yet have a stringify method, give it one.
    +351 
    +352     if (typeof JSON.stringify !== 'function') {
    +353         JSON.stringify = function (value, replacer, space) {
    +354 
    +355 // The stringify method takes a value and an optional replacer, and an optional
    +356 // space parameter, and returns a JSON text. The replacer can be a function
    +357 // that can replace values, or an array of strings that will select the keys.
    +358 // A default replacer method can be provided. Use of the space parameter can
    +359 // produce text that is more easily readable.
    +360 
    +361             var i;
    +362             gap = '';
    +363             indent = '';
    +364 
    +365 // If the space parameter is a number, make an indent string containing that
    +366 // many spaces.
    +367 
    +368             if (typeof space === 'number') {
    +369                 for (i = 0; i < space; i += 1) {
    +370                     indent += ' ';
    +371                 }
    +372 
    +373 // If the space parameter is a string, it will be used as the indent string.
    +374 
    +375             } else if (typeof space === 'string') {
    +376                 indent = space;
    +377             }
    +378 
    +379 // If there is a replacer, it must be a function or an array.
    +380 // Otherwise, throw an error.
    +381 
    +382             rep = replacer;
    +383             if (replacer && typeof replacer !== 'function' &&
    +384                     (typeof replacer !== 'object' ||
    +385                      typeof replacer.length !== 'number')) {
    +386                 throw new Error('JSON.stringify');
    +387             }
    +388 
    +389 // Make a fake root object containing our value under the key of ''.
    +390 // Return the result of stringifying the value.
    +391 
    +392             return str('', {'': value});
    +393         };
    +394     }
    +395 
    +396 
    +397 // If the JSON object does not yet have a parse method, give it one.
    +398 
    +399     if (typeof JSON.parse !== 'function') {
    +400         JSON.parse = function (text, reviver) {
    +401 
    +402 // The parse method takes a text and an optional reviver function, and returns
    +403 // a JavaScript value if the text is a valid JSON text.
    +404 
    +405             var j;
    +406 
    +407             function walk(holder, key) {
    +408 
    +409 // The walk method is used to recursively walk the resulting structure so
    +410 // that modifications can be made.
    +411 
    +412                 var k, v, value = holder[key];
    +413                 if (value && typeof value === 'object') {
    +414                     for (k in value) {
    +415                         if (Object.hasOwnProperty.call(value, k)) {
    +416                             v = walk(value, k);
    +417                             if (v !== undefined) {
    +418                                 value[k] = v;
    +419                             } else {
    +420                                 delete value[k];
    +421                             }
    +422                         }
    +423                     }
    +424                 }
    +425                 return reviver.call(holder, key, value);
    +426             }
    +427 
    +428 
    +429 // Parsing happens in four stages. In the first stage, we replace certain
    +430 // Unicode characters with escape sequences. JavaScript handles many characters
    +431 // incorrectly, either silently deleting them, or treating them as line endings.
    +432 
    +433             cx.lastIndex = 0;
    +434             if (cx.test(text)) {
    +435                 text = text.replace(cx, function (a) {
    +436                     return '\\u' +
    +437                         ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
    +438                 });
    +439             }
    +440 
    +441 // In the second stage, we run the text against regular expressions that look
    +442 // for non-JSON patterns. We are especially concerned with '()' and 'new'
    +443 // because they can cause invocation, and '=' because it can cause mutation.
    +444 // But just to be safe, we want to reject all unexpected forms.
    +445 
    +446 // We split the second stage into 4 regexp operations in order to work around
    +447 // crippling inefficiencies in IE's and Safari's regexp engines. First we
    +448 // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
    +449 // replace all simple value tokens with ']' characters. Third, we delete all
    +450 // open brackets that follow a colon or comma or that begin the text. Finally,
    +451 // we look to see that the remaining characters are only whitespace or ']' or
    +452 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
    +453 
    +454             if (/^[\],:{}\s]*$/.
    +455 test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
    +456 replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
    +457 replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
    +458 
    +459 // In the third stage we use the eval function to compile the text into a
    +460 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
    +461 // in JavaScript: it can begin a block or an object literal. We wrap the text
    +462 // in parens to eliminate the ambiguity.
    +463 
    +464                 j = eval('(' + text + ')');
    +465 
    +466 // In the optional fourth stage, we recursively walk the new structure, passing
    +467 // each name/value pair to a reviver function for possible transformation.
    +468 
    +469                 return typeof reviver === 'function' ?
    +470                     walk({'': j}, '') : j;
    +471             }
    +472 
    +473 // If the text is not JSON parseable, then a SyntaxError is thrown.
    +474 
    +475             throw new SyntaxError('JSON.parse');
    +476         };
    +477     }
    +478 })();
    +479 
    \ No newline at end of file