From 9d95483de69cbc6cd2686b1c1dcf3a6144b9d75a Mon Sep 17 00:00:00 2001 From: ragaskar Date: Thu, 28 May 2009 20:02:15 -0700 Subject: [PATCH] Refactored into class files. Meta-tests and runner for jasmine. Stack traces available for Firefox and supported browsers. Experimental pretty print matcher support. Many other new features --- example/example.html | 4 +- example/example.js | 2 +- lib/TrivialReporter.js | 61 ++ lib/json_reporter.js | 51 +- runner.html | 72 ++ src/ActionCollection.js | 80 ++ src/Env.js | 176 ++++ src/Matchers.js | 209 +++++ src/NestedResults.js | 49 + src/PrettyPrinter.js | 106 +++ src/QueuedFunction.js | 86 ++ src/Reporters.js | 33 + src/Runner.js | 26 + src/Spec.js | 175 ++++ src/Suite.js | 53 ++ src/base.js | 213 +++++ src/util.js | 50 ++ test/JsonReporterTest.js | 53 ++ test/MatchersTest.js | 301 +++++++ test/NestedResultsTest.js | 41 + test/PrettyPrintTest.js | 62 ++ test/ReporterTest.js | 58 ++ test/RunnerTest.js | 98 ++ test/SpecRunningTest.js | 712 +++++++++++++++ test/SpyTest.js | 187 ++++ test/bootstrap.html | 14 +- test/bootstrap.js | 1779 +++---------------------------------- test/mock-ajax.js | 57 ++ test/mock-timeout.js | 158 ++++ 29 files changed, 3249 insertions(+), 1717 deletions(-) create mode 100644 lib/TrivialReporter.js create mode 100644 runner.html create mode 100644 src/ActionCollection.js create mode 100644 src/Env.js create mode 100644 src/Matchers.js create mode 100644 src/NestedResults.js create mode 100644 src/PrettyPrinter.js create mode 100644 src/QueuedFunction.js create mode 100644 src/Reporters.js create mode 100644 src/Runner.js create mode 100644 src/Spec.js create mode 100644 src/Suite.js create mode 100755 src/base.js create mode 100644 src/util.js create mode 100644 test/JsonReporterTest.js create mode 100644 test/MatchersTest.js create mode 100644 test/NestedResultsTest.js create mode 100644 test/PrettyPrintTest.js create mode 100644 test/ReporterTest.js create mode 100644 test/RunnerTest.js create mode 100644 test/SpecRunningTest.js create mode 100644 test/SpyTest.js create mode 100644 test/mock-ajax.js create mode 100755 test/mock-timeout.js diff --git a/example/example.html b/example/example.html index 1776bfb..000eb99 100644 --- a/example/example.html +++ b/example/example.html @@ -13,10 +13,10 @@
diff --git a/example/example.js b/example/example.js index 1c72179..4c03804 100644 --- a/example/example.js +++ b/example/example.js @@ -1,7 +1,7 @@ describe('one suite description', function () { it('should be a test', function() { runs(function () { - this.expects_that(true).should_equal(true); + expect(true).toEqual(true); }); }); }); \ No newline at end of file diff --git a/lib/TrivialReporter.js b/lib/TrivialReporter.js new file mode 100644 index 0000000..14c35ea --- /dev/null +++ b/lib/TrivialReporter.js @@ -0,0 +1,61 @@ +jasmine.TrivialReporter = function() { +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + el.appendChild(child); + } + } + + for (var attr in attrs) { + if (attr == 'className') { + el.setAttribute('class', attrs[attr]); + } else { + if (attr.indexOf('x-') == 0) { + el.setAttribute(attr, attrs[attr]); + } else { + el[attr] = attrs[attr]; + } + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + console.log(runner); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + console.log(suite); +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var specDiv = this.createDom('div', { + className: spec.getResults().passed() ? 'spec passed' : 'spec failed' + }, spec.getFullName()); + + var resultItems = spec.getResults().getItems(); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + if (!result.passed) { + var resultMessageDiv = this.createDom('div', {className: 'resultMessage'}); + resultMessageDiv.innerHTML = result.message; // todo: lame; mend + specDiv.appendChild(resultMessageDiv); + specDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + + document.body.appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + console.log.apply(console, arguments); +}; diff --git a/lib/json_reporter.js b/lib/json_reporter.js index 07ab322..36fd4c3 100644 --- a/lib/json_reporter.js +++ b/lib/json_reporter.js @@ -1,62 +1,35 @@ /* - * JasmineReporters.JSON -- + * jasmine.Reporters.JSON -- * Basic reporter that keeps a JSON string of the most recent Spec, Suite or Runner * result. Calling application can then do whatever it wants/needs with the string; */ -Jasmine.Reporters.JSON = function () { +jasmine.Reporters.JSON = function () { var toJSON = function(object){ return JSON.stringify(object); }; - var that = Jasmine.Reporters.reporter(); + var that = jasmine.Reporters.reporter(); that.specJSON = ''; that.suiteJSON = ''; that.runnerJSON = ''; - var saveSpecResults = function (results) { - that.specJSON = toJSON(results); + var saveSpecResults = function (spec) { + that.specJSON = toJSON(spec.getResults()); }; that.reportSpecResults = saveSpecResults; - var saveSuiteResults = function (results) { - that.suiteJSON = toJSON(results); + var saveSuiteResults = function (suite) { + that.suiteJSON = toJSON(suite.getResults()); }; that.reportSuiteResults = saveSuiteResults; - var saveRunnerResults = function (results) { - that.runnerJSON = toJSON(results); + var saveRunnerResults = function (runner) { + that.runnerJSON = toJSON(runner.getResults()); }; that.reportRunnerResults = saveRunnerResults; + this.log = function (str) { + console.log(str); + }; that.toJSON = toJSON; return that; }; - -Jasmine.Reporters.domWriter = function (elementId) { - var that = { - element: document.getElementById(elementId), - - write: function (text) { - if (that.element) { - that.element.innerHTML += text; - } - } - }; - - that.element.innerHTML = ''; - - return that; -}; - -Jasmine.Reporters.JSONtoDOM = function (elementId) { - var that = Jasmine.Reporters.JSON(); - - that.domWriter = Jasmine.Reporters.domWriter(elementId); - - var writeRunnerResults = function (results) { - that.domWriter.write(that.toJSON(results)); - }; - - that.reportRunnerResults = writeRunnerResults; - - return that; -}; diff --git a/runner.html b/runner.html new file mode 100644 index 0000000..ba53236 --- /dev/null +++ b/runner.html @@ -0,0 +1,72 @@ + + + + Jasmine Test Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ActionCollection.js b/src/ActionCollection.js new file mode 100644 index 0000000..1589c02 --- /dev/null +++ b/src/ActionCollection.js @@ -0,0 +1,80 @@ +/** + * base for Runner & Suite: allows for a queue of functions to get executed, allowing for + * any one action to complete, including asynchronous calls, before going to the next + * action. + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.ActionCollection = function(env) { + this.env = env; + this.actions = []; + this.index = 0; + this.finished = false; +}; + +jasmine.ActionCollection.prototype.finish = function() { + if (this.finishCallback) { + this.finishCallback(); + } + this.finished = true; +}; + +jasmine.ActionCollection.prototype.execute = function() { + if (this.actions.length > 0) { + this.next(); + } +}; + +jasmine.ActionCollection.prototype.getCurrentAction = function() { + return this.actions[this.index]; +}; + +jasmine.ActionCollection.prototype.next = function() { + if (this.index >= this.actions.length) { + this.finish(); + return; + } + + var currentAction = this.getCurrentAction(); + + currentAction.execute(this); + + if (currentAction.afterCallbacks) { + for (var i = 0; i < currentAction.afterCallbacks.length; i++) { + try { + currentAction.afterCallbacks[i](); + } catch (e) { + alert(e); + } + } + } + + this.waitForDone(currentAction); +}; + +jasmine.ActionCollection.prototype.waitForDone = function(action) { + var self = this; + var afterExecute = function afterExecute() { + self.index++; + self.next(); + }; + + if (action.finished) { + var now = new Date().getTime(); + if (this.env.updateInterval && now - this.env.lastUpdate > this.env.updateInterval) { + this.env.lastUpdate = now; + this.env.setTimeout(afterExecute, 0); + } else { + afterExecute(); + } + return; + } + + var id = this.env.setInterval(function() { + if (action.finished) { + self.env.clearInterval(id); + afterExecute(); + } + }, 150); +}; diff --git a/src/Env.js b/src/Env.js new file mode 100644 index 0000000..268ed88 --- /dev/null +++ b/src/Env.js @@ -0,0 +1,176 @@ +/** + * Env + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner = new jasmine.Runner(this); + this.currentlyRunningTests = false; + + this.updateInterval = 0; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.equalityTesters_ = []; +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +jasmine.Env.prototype.execute = function() { + this.currentRunner.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.specs.push(suite); + } else { + this.currentRunner.suites.push(suite); + } + + this.currentSuite = suite; + + specDefinitions.call(suite); + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + this.currentSuite.beforeEach(beforeEachFunction); +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + this.currentSuite.afterEach(afterEachFunction); +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.specs.push(spec); + this.currentSpec = spec; + + if (func) { + spec.addToQueue(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId_++, + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was

'" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "'

in expected, but was

'" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "'

in actual.
"); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length == 0 && mismatchValues.length == 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + if (a === b) return true; + + if (a === undefined || a === null || b === undefined || b === null) { + return (a == undefined && b == undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a instanceof jasmine.Matchers.Any) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.Any) { + return b.matches(a); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== undefined) return result; + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; diff --git a/src/Matchers.js b/src/Matchers.js new file mode 100644 index 0000000..206dd68 --- /dev/null +++ b/src/Matchers.js @@ -0,0 +1,209 @@ +/* + * jasmine.Matchers methods; add your own by extending jasmine.Matchers.prototype - don't forget to write a test + * + */ + +jasmine.Matchers = function(env, actual, results) { + this.env = env; + this.actual = actual; + this.passing_message = 'Passed.'; + this.results = results || new jasmine.NestedResults(); +}; + +jasmine.Matchers.pp = function(str) { + return jasmine.util.htmlEscape(jasmine.pp(str)); +}; + +jasmine.Matchers.prototype.getResults = function() { + return this.results; +}; + +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + this.results.addResult(new jasmine.ExpectationResult(result, result ? this.passing_message : failing_message, details)); + return result; +}; + +jasmine.Matchers.prototype.toBe = function(expected) { + return this.report(this.actual === expected, 'Expected

' + jasmine.Matchers.pp(expected) + + '

to be the same object as

' + jasmine.Matchers.pp(this.actual) + + '
'); +}; + +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.report(this.actual !== expected, 'Expected

' + jasmine.Matchers.pp(expected) + + '

to be a different object from actual, but they were the same.'); +}; + +jasmine.Matchers.prototype.toEqual = function(expected) { + var mismatchKeys = []; + var mismatchValues = []; + + var formatMismatches = function(name, array) { + if (array.length == 0) return ''; + var errorOutput = '

Different ' + name + ':
'; + for (var i = 0; i < array.length; i++) { + errorOutput += array[i] + '
'; + } + return errorOutput; + }; + + return this.report(this.env.equals_(this.actual, expected, mismatchKeys, mismatchValues), + 'Expected

' + jasmine.Matchers.pp(expected) + + '

but got

' + jasmine.Matchers.pp(this.actual) + + '
' + + formatMismatches('Keys', mismatchKeys) + + formatMismatches('Values', mismatchValues), { + matcherName: 'toEqual', expected: expected, actual: this.actual + }); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_equal = jasmine.Matchers.prototype.toEqual; + +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return this.report((this.actual !== expected), + 'Expected ' + jasmine.Matchers.pp(expected) + ' to not equal ' + jasmine.Matchers.pp(this.actual) + ', but it does.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_not_equal = jasmine.Matchers.prototype.toNotEqual; + +jasmine.Matchers.prototype.toMatch = function(reg_exp) { + return this.report((new RegExp(reg_exp).test(this.actual)), + 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to match ' + reg_exp + '.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_match = jasmine.Matchers.prototype.toMatch; + +jasmine.Matchers.prototype.toNotMatch = function(reg_exp) { + return this.report((!new RegExp(reg_exp).test(this.actual)), + 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to not match ' + reg_exp + '.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_not_match = jasmine.Matchers.prototype.toNotMatch; + +jasmine.Matchers.prototype.toBeDefined = function() { + return this.report((this.actual !== undefined), + 'Expected a value to be defined but it was undefined.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_be_defined = jasmine.Matchers.prototype.toBeDefined; + +jasmine.Matchers.prototype.toBeNull = function() { + return this.report((this.actual === null), + 'Expected a value to be null but it was ' + jasmine.Matchers.pp(this.actual) + '.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_be_null = jasmine.Matchers.prototype.toBeNull; + +jasmine.Matchers.prototype.toBeTruthy = function() { + return this.report(!!this.actual, + 'Expected a value to be truthy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_be_truthy = jasmine.Matchers.prototype.toBeTruthy; + +jasmine.Matchers.prototype.toBeFalsy = function() { + return this.report(!this.actual, + 'Expected a value to be falsy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.should_be_falsy = jasmine.Matchers.prototype.toBeFalsy; + +jasmine.Matchers.prototype.wasCalled = function() { + if (!this.actual || !this.actual.isSpy) { + return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); + } + if (arguments.length > 0) { + return this.report(false, 'wasCalled matcher does not take arguments'); + } + return this.report((this.actual.wasCalled), + 'Expected spy "' + this.actual.identity + '" to have been called, but it was not.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.was_called = jasmine.Matchers.prototype.wasCalled; + +jasmine.Matchers.prototype.wasNotCalled = function() { + if (!this.actual || !this.actual.isSpy) { + return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); + } + return this.report((!this.actual.wasCalled), + 'Expected spy "' + this.actual.identity + '" to not have been called, but it was.'); +}; +/** @deprecated */ +jasmine.Matchers.prototype.was_not_called = jasmine.Matchers.prototype.wasNotCalled; + +jasmine.Matchers.prototype.wasCalledWith = function() { + if (!this.actual || !this.actual.isSpy) { + return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.', { + matcherName: 'wasCalledWith' + }); + } + + var args = jasmine.util.argsToArray(arguments); + + return this.report(this.env.contains_(this.actual.argsForCall, args), + 'Expected ' + jasmine.Matchers.pp(this.actual.argsForCall) + ' to contain ' + jasmine.Matchers.pp(args) + ', but it does not.', { + matcherName: 'wasCalledWith', expected: args, actual: this.actual.argsForCall + }); +}; + +jasmine.Matchers.prototype.toContain = function(expected) { + return this.report(this.env.contains_(this.actual, expected), + 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to contain ' + jasmine.Matchers.pp(expected) + ', but it does not.', { + matcherName: 'toContain', expected: expected, actual: this.actual + }); +}; + +jasmine.Matchers.prototype.toNotContain = function(item) { + return this.report(!this.env.contains_(this.actual, item), + 'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.'); +}; + +jasmine.Matchers.prototype.toThrow = function(expectedException) { + var exception = null; + try { + this.actual(); + } catch (e) { + exception = e; + } + if (expectedException !== undefined) { + if (exception == null) { + return this.report(false, "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it did not."); + } + return this.report( + this.env.equals_( + exception.message || exception, + expectedException.message || expectedException), + "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it threw " + jasmine.Matchers.pp(exception) + "."); + } else { + return this.report(exception != null, "Expected function to throw an exception, but it did not."); + } +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.matches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.toString = function() { + return ''; +}; + diff --git a/src/NestedResults.js b/src/NestedResults.js new file mode 100644 index 0000000..46c4ec1 --- /dev/null +++ b/src/NestedResults.js @@ -0,0 +1,49 @@ +/** + * Holds results; allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + this.totalCount = 0; + this.passedCount = 0; + this.failedCount = 0; + this.skipped = false; + this.items_ = []; +}; + +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +jasmine.NestedResults.prototype.log = function(message) { + this.items_.push(new jasmine.MessageResult(message)); +}; + +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'MessageResult') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; diff --git a/src/PrettyPrinter.js b/src/PrettyPrinter.js new file mode 100644 index 0000000..ff66ee6 --- /dev/null +++ b/src/PrettyPrinter.js @@ -0,0 +1,106 @@ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +jasmine.PrettyPrinter.prototype.format = function(value) { + if (this.ppNestLevel_ > 40) { + // return '(jasmine.pp nested too deeply!)'; + throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); + } + + this.ppNestLevel_++; + try { + if (value === undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value.navigator && value.frames && value.setTimeout) { + this.emitScalar(''); + } else if (value instanceof jasmine.Matchers.Any) { + this.emitScalar(value.toString()); + } else if (typeof value === 'string') { + this.emitScalar("'" + value + "'"); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__(property) != null); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; diff --git a/src/QueuedFunction.js b/src/QueuedFunction.js new file mode 100644 index 0000000..f2fc777 --- /dev/null +++ b/src/QueuedFunction.js @@ -0,0 +1,86 @@ +/** + * QueuedFunction is how ActionCollections' actions are implemented + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {Number} timeout + * @param {Function} latchFunction + * @param {jasmine.Spec} spec + */ +jasmine.QueuedFunction = function(env, func, timeout, latchFunction, spec) { + this.env = env; + this.func = func; + this.timeout = timeout; + this.latchFunction = latchFunction; + this.spec = spec; + + this.totalTimeSpentWaitingForLatch = 0; + this.latchTimeoutIncrement = 100; +}; + +jasmine.QueuedFunction.prototype.next = function() { + this.spec.finish(); // default value is to be done after one function +}; + +jasmine.QueuedFunction.prototype.safeExecute = function() { + if (this.env.reporter) { + this.env.reporter.log('>> Jasmine Running ' + this.spec.suite.description + ' ' + this.spec.description + '...'); + } + + try { + this.func.apply(this.spec); + } catch (e) { + this.fail(e); + } +}; + +jasmine.QueuedFunction.prototype.execute = function() { + var self = this; + var executeNow = function() { + self.safeExecute(); + self.next(); + }; + + var executeLater = function() { + self.env.setTimeout(executeNow, self.timeout); + }; + + var executeNowOrLater = function() { + var latchFunctionResult; + + try { + latchFunctionResult = self.latchFunction.apply(self.spec); + } catch (e) { + self.fail(e); + self.next(); + return; + } + + if (latchFunctionResult) { + executeNow(); + } else if (self.totalTimeSpentWaitingForLatch >= self.timeout) { + var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.latchFunction.description || 'something to happen'); + self.fail({ + name: 'timeout', + message: message + }); + self.next(); + } else { + self.totalTimeSpentWaitingForLatch += self.latchTimeoutIncrement; + self.env.setTimeout(executeNowOrLater, self.latchTimeoutIncrement); + } + }; + + if (this.latchFunction !== undefined) { + executeNowOrLater(); + } else if (this.timeout > 0) { + executeLater(); + } else { + executeNow(); + } +}; + +jasmine.QueuedFunction.prototype.fail = function(e) { + this.spec.results.addResult(new jasmine.ExpectationResult(false, jasmine.util.formatException(e), null)); +}; diff --git a/src/Reporters.js b/src/Reporters.js new file mode 100644 index 0000000..066ac64 --- /dev/null +++ b/src/Reporters.js @@ -0,0 +1,33 @@ +/* JasmineReporters.reporter + * Base object that will get called whenever a Spec, Suite, or Runner is done. It is up to + * descendants of this object to do something with the results (see json_reporter.js) + */ +jasmine.Reporters = {}; + +jasmine.Reporters.reporter = function(callbacks) { + var that = { + callbacks: callbacks || {}, + + doCallback: function(callback, results) { + if (callback) { + callback(results); + } + }, + + reportRunnerResults: function(runner) { + that.doCallback(that.callbacks.runnerCallback, runner); + }, + reportSuiteResults: function(suite) { + that.doCallback(that.callbacks.suiteCallback, suite); + }, + reportSpecResults: function(spec) { + that.doCallback(that.callbacks.specCallback, spec); + }, + log: function (str) { + if (console && console.log) console.log(str); + } + }; + + return that; +}; + diff --git a/src/Runner.js b/src/Runner.js new file mode 100644 index 0000000..22a1996 --- /dev/null +++ b/src/Runner.js @@ -0,0 +1,26 @@ +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + jasmine.ActionCollection.call(this, env); + + this.suites = this.actions; +}; +jasmine.util.inherit(jasmine.Runner, jasmine.ActionCollection); + +jasmine.Runner.prototype.finishCallback = function() { + if (this.env.reporter) { + this.env.reporter.reportRunnerResults(this); + } +}; + +jasmine.Runner.prototype.getResults = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.suites.length; i++) { + results.rollupCounts(this.suites[i].getResults()); + } + return results; +}; diff --git a/src/Spec.js b/src/Spec.js new file mode 100644 index 0000000..eca17e7 --- /dev/null +++ b/src/Spec.js @@ -0,0 +1,175 @@ +/** + * Spec + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + this.id = env.nextSpecId_++; + this.env = env; + this.suite = suite; + this.description = description; + this.queue = []; + this.currentTimeout = 0; + this.currentLatchFunction = undefined; + this.finished = false; + this.afterCallbacks = []; + this.spies_ = []; + + this.results = new jasmine.NestedResults(); + this.results.description = description; + this.runs = this.addToQueue; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + +jasmine.Spec.prototype.getResults = function() { + return this.results; +}; + +jasmine.Spec.prototype.addToQueue = function(func) { + var queuedFunction = new jasmine.QueuedFunction(this.env, func, this.currentTimeout, this.currentLatchFunction, this); + this.queue.push(queuedFunction); + + if (this.queue.length > 1) { + var previousQueuedFunction = this.queue[this.queue.length - 2]; + previousQueuedFunction.next = function() { + queuedFunction.execute(); + }; + } + + this.resetTimeout(); + return this; +}; + +/** @deprecated */ +jasmine.Spec.prototype.expects_that = function(actual) { + return this.expect(actual); +}; + +jasmine.Spec.prototype.expect = function(actual) { + return new jasmine.Matchers(this.env, actual, this.results); +}; + +jasmine.Spec.prototype.waits = function(timeout) { + this.currentTimeout = timeout; + this.currentLatchFunction = undefined; + return this; +}; + +jasmine.Spec.prototype.waitsFor = function(timeout, latchFunction, message) { + this.currentTimeout = timeout; + this.currentLatchFunction = latchFunction; + this.currentLatchFunction.description = message; + return this; +}; + +jasmine.Spec.prototype.resetTimeout = function() { + this.currentTimeout = 0; + this.currentLatchFunction = undefined; +}; + +jasmine.Spec.prototype.finishCallback = function() { + if (this.env.reporter) { + this.env.reporter.reportSpecResults(this); + } +}; + +jasmine.Spec.prototype.finish = function() { + this.safeExecuteAfters(); + + this.removeAllSpies(); + this.finishCallback(); + this.finished = true; +}; + +jasmine.Spec.prototype.after = function(doAfter) { + this.afterCallbacks.unshift(doAfter); +}; + +jasmine.Spec.prototype.execute = function() { + if (!this.env.specFilter(this)) { + this.results.skipped = true; + this.finishCallback(); + this.finished = true; + return; + } + + this.env.currentSpec = this; + this.env.currentlyRunningTests = true; + + this.safeExecuteBefores(); + + if (this.queue[0]) { + this.queue[0].execute(); + } else { + this.finish(); + } + this.env.currentlyRunningTests = false; +}; + +jasmine.Spec.prototype.safeExecuteBefores = function() { + var befores = []; + for (var suite = this.suite; suite; suite = suite.parentSuite) { + if (suite.beforeEachFunction) befores.push(suite.beforeEachFunction); + } + + while (befores.length) { + this.safeExecuteBeforeOrAfter(befores.pop()); + } +}; + +jasmine.Spec.prototype.safeExecuteAfters = function() { + for (var suite = this.suite; suite; suite = suite.parentSuite) { + if (suite.afterEachFunction) this.safeExecuteBeforeOrAfter(suite.afterEachFunction); + } +}; + +jasmine.Spec.prototype.safeExecuteBeforeOrAfter = function(func) { + try { + func.apply(this); + } catch (e) { + this.results.addResult(new jasmine.ExpectationResult(false, func.typeName + '() fail: ' + jasmine.util.formatException(e), null)); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + diff --git a/src/Suite.js b/src/Suite.js new file mode 100644 index 0000000..7d26e6b --- /dev/null +++ b/src/Suite.js @@ -0,0 +1,53 @@ +/** + * Description + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + jasmine.ActionCollection.call(this, env); + + this.description = description; + this.specs = this.actions; + this.parentSuite = parentSuite; + + this.beforeEachFunction = null; + this.afterEachFunction = null; +}; +jasmine.util.inherit(jasmine.Suite, jasmine.ActionCollection); + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finishCallback = function() { + if (this.env.reporter) { + this.env.reporter.reportSuiteResults(this); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.beforeEachFunction = beforeEachFunction; +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.afterEachFunction = afterEachFunction; +}; + +jasmine.Suite.prototype.getResults = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.specs.length; i++) { + results.rollupCounts(this.specs[i].getResults()); + } + return results; +}; + diff --git a/src/base.js b/src/base.js new file mode 100755 index 0000000..d63cca3 --- /dev/null +++ b/src/base.js @@ -0,0 +1,213 @@ +/* + * Jasmine internal classes & objects + */ + +/** @namespace */ +var jasmine = {}; + +/** @deprecated use jasmine (lowercase because it's a package name) instead */ +var Jasmine = jasmine; + +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + return function() { + return original.apply(base, arguments); + }; +}; + +jasmine.setTimeout = jasmine.bindOriginal_(window, 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(window, 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(window, 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(window, 'clearInterval'); + +jasmine.MessageResult = function(text) { + this.type = 'MessageResult'; + this.text = text; + this.trace = new Error(); // todo: test better +}; + +jasmine.ExpectationResult = function(passed, message, details) { + this.type = 'ExpectationResult'; + this.passed = passed; + this.message = message; + this.details = details; + this.trace = new Error(message); // todo: test better +}; + +jasmine.getEnv = function() { + return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); +}; + +jasmine.isArray_ = function(value) { + return value && + typeof value === 'object' && + typeof value.length === 'number' && + typeof value.splice === 'function' && + !(value.propertyIsEnumerable('length')); +}; + +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +jasmine.isDomNode = function(obj) { + return obj['nodeType'] > 0; +}; + +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + + +jasmine.createSpy = function(name) { + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall = { + object: this, + args: args + }; + spyObj.argsForCall.push(args); + return spyObj.plan.apply(this, arguments); + }; + + spyObj.identity = name || 'unknown'; + spyObj.isSpy = true; + + spyObj.plan = function() { + }; + + spyObj.andCallThrough = function() { + spyObj.plan = spyObj.originalValue; + return spyObj; + }; + spyObj.andReturn = function(value) { + spyObj.plan = function() { + return value; + }; + return spyObj; + }; + spyObj.andThrow = function(exceptionMsg) { + spyObj.plan = function() { + throw exceptionMsg; + }; + return spyObj; + }; + spyObj.andCallFake = function(fakeFunc) { + spyObj.plan = fakeFunc; + return spyObj; + }; + spyObj.reset = function() { + spyObj.wasCalled = false; + spyObj.callCount = 0; + spyObj.argsForCall = []; + spyObj.mostRecentCall = {}; + }; + spyObj.reset(); + + return spyObj; +}; + +jasmine.createSpyObj = function(baseName, methodNames) { + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +jasmine.log = function(message) { + jasmine.getEnv().currentSpec.getResults().log(message); +}; + +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; + +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; + +//this mirrors the spec syntax so you can define a spec description that will not run. +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; + +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; + +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; + +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; + +var waitsFor = function(timeout, latchFunction, message) { + jasmine.getEnv().currentSpec.waitsFor(timeout, latchFunction, message); +}; + +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; + +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; + +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; + +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; + +jasmine.XmlHttpRequest = XMLHttpRequest; + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +if (typeof XMLHttpRequest == "undefined") jasmine.XmlHttpRequest = function() { + try { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + } catch(e) { + } + try { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + } catch(e) { + } + try { + return new ActiveXObject("Msxml2.XMLHTTP"); + } catch(e) { + } + try { + return new ActiveXObject("Microsoft.XMLHTTP"); + } catch(e) { + } + throw new Error("This browser does not support XMLHttpRequest."); +}; + +jasmine.include = function(url, opt_global) { + if (opt_global) { + document.write(' - + + + + + + + + + + + + + diff --git a/test/bootstrap.js b/test/bootstrap.js index 7c5d655..a8d46db 100755 --- a/test/bootstrap.js +++ b/test/bootstrap.js @@ -53,1236 +53,32 @@ Reporter.prototype.summary = function () { var reporter = new Reporter(); -var testMatchersComparisons = function () { - var expected = new Jasmine.Matchers(true); - reporter.test(expected.toEqual(true), - 'expect(true).toEqual(true) returned false'); - - expected = new Jasmine.Matchers({foo:'bar'}); - reporter.test(!expected.toEqual(null), - 'expect({foo:\'bar\'}).toEqual(null) returned true'); - - var functionA = function () { - return 'hi'; - }; - var functionB = function () { - return 'hi'; - }; - expected = new Jasmine.Matchers({foo:functionA}); - reporter.test(expected.toEqual({foo:functionB}), - 'expect({foo: function () { return \'hi\' };})' + - '.toEqual({foo: function () { return \'hi\' };}) ' + - 'returned true, but returned false'); - - expected = new Jasmine.Matchers(false); - reporter.test(!(expected.toEqual(true)), - 'expect(false).toEqual(true) returned true'); - - var nodeA = document.createElement('div'); - var nodeB = document.createElement('div'); - expected = new Jasmine.Matchers(nodeA); - reporter.test((expected.toEqual(nodeA)), - 'expect(nodeA).toEqual(nodeA) returned false'); - - expected = new Jasmine.Matchers(nodeA); - reporter.test(!(expected.toEqual(nodeB)), - 'expect(nodeA).toEqual(nodeB) returned true'); - - - expected = new Jasmine.Matchers(true); - reporter.test(expected.toNotEqual(false), - 'expect(true).toNotEqual(false) returned false'); - - expected = new Jasmine.Matchers(true); - reporter.test(!(expected.toNotEqual(true)), - 'expect(true).toNotEqual(false) returned true'); - - expected = new Jasmine.Matchers('foobarbel'); - reporter.test((expected.toMatch(/bar/)), - 'expect(forbarbel).toMatch(/bar/) returned false'); - - expected = new Jasmine.Matchers('foobazbel'); - reporter.test(!(expected.toMatch(/bar/)), - 'expect(forbazbel).toMatch(/bar/) returned true'); - - expected = new Jasmine.Matchers('foobarbel'); - reporter.test((expected.toMatch("bar")), - 'expect(forbarbel).toMatch(/bar/) returned false'); - - expected = new Jasmine.Matchers('foobazbel'); - reporter.test(!(expected.toMatch("bar")), - 'expect(forbazbel).toMatch(/bar/) returned true'); - - expected = new Jasmine.Matchers('foobarbel'); - reporter.test(!(expected.toNotMatch(/bar/)), - 'expect(forbarbel).toNotMatch(/bar/) returned false'); - - expected = new Jasmine.Matchers('foobazbel'); - reporter.test((expected.toNotMatch(/bar/)), - 'expect(forbazbel).toNotMatch(/bar/) returned true'); - - expected = new Jasmine.Matchers('foobarbel'); - reporter.test(!(expected.toNotMatch("bar")), - 'expect(forbarbel).toNotMatch("bar") returned false'); - - expected = new Jasmine.Matchers('foobazbel'); - reporter.test((expected.toNotMatch("bar")), - 'expect(forbazbel).toNotMatch("bar") returned true'); - - expected = new Jasmine.Matchers('foo'); - reporter.test(expected.toBeDefined(), - 'expect(foo).toBeDefined() returned true'); - - expected = new Jasmine.Matchers(undefined); - reporter.test(! expected.toBeDefined(), - 'expect(undefined).toBeDefined() returned false'); - - expected = new Jasmine.Matchers(null); - reporter.test(expected.toBeNull(), - 'expect(null).toBeNull() should be true'); - - expected = new Jasmine.Matchers(undefined); - reporter.test(! expected.toBeNull(), - 'expect(undefined).toBeNull() should be false'); - - expected = new Jasmine.Matchers("foo"); - reporter.test(! expected.toBeNull(), - 'expect("foo").toBeNull() should be false'); - - expected = new Jasmine.Matchers(false); - reporter.test(expected.toBeFalsy(), - 'expect(false).toBeFalsy() should be true'); - - expected = new Jasmine.Matchers(true); - reporter.test(!expected.toBeFalsy(), - 'expect(true).toBeFalsy() should be false'); - - expected = new Jasmine.Matchers(undefined); - reporter.test(expected.toBeFalsy(), - 'expect(undefined).toBeFalsy() should be true'); - - expected = new Jasmine.Matchers(0); - reporter.test(expected.toBeFalsy(), - 'expect(0).toBeFalsy() should be true'); - - expected = new Jasmine.Matchers(""); - reporter.test(expected.toBeFalsy(), - 'expect("").toBeFalsy() should be true'); - - expected = new Jasmine.Matchers(false); - reporter.test(!expected.toBeTruthy(), - 'expect(false).toBeTruthy() should be false'); - - expected = new Jasmine.Matchers(true); - reporter.test(expected.toBeTruthy(), - 'expect(true).toBeTruthy() should be true'); - - expected = new Jasmine.Matchers(undefined); - reporter.test(!expected.toBeTruthy(), - 'expect(undefined).toBeTruthy() should be false'); - - expected = new Jasmine.Matchers(0); - reporter.test(!expected.toBeTruthy(), - 'expect(0).toBeTruthy() should be false'); - - expected = new Jasmine.Matchers(""); - reporter.test(!expected.toBeTruthy(), - 'expect("").toBeTruthy() should be false'); - - expected = new Jasmine.Matchers("hi"); - reporter.test(expected.toBeTruthy(), - 'expect("hi").toBeTruthy() should be true'); - - expected = new Jasmine.Matchers(5); - reporter.test(expected.toBeTruthy(), - 'expect(5).toBeTruthy() should be true'); - - expected = new Jasmine.Matchers({foo: 1}); - reporter.test(expected.toBeTruthy(), - 'expect({foo: 1}).toBeTruthy() should be true'); - - expected = new Jasmine.Matchers(undefined); - reporter.test(expected.toEqual(undefined), - 'expect(undefined).toEqual(undefined) should return true'); - - expected = new Jasmine.Matchers({foo:'bar'}); - reporter.test(expected.toEqual({foo:'bar'}), - 'expect({foo:\'bar\').toEqual({foo:\'bar\'}) returned true'); - - expected = new Jasmine.Matchers("foo"); - reporter.test(! expected.toEqual({bar: undefined}), - 'expect({"foo").toEqual({bar:undefined}) should return false'); - - expected = new Jasmine.Matchers({foo: undefined}); - reporter.test(! expected.toEqual("goo"), - 'expect({foo:undefined}).toEqual("goo") should return false'); - - expected = new Jasmine.Matchers({foo: {bar :undefined}}); - reporter.test(! expected.toEqual("goo"), - 'expect({foo:{ bar: undefined}}).toEqual("goo") should return false'); - - expected = new Jasmine.Matchers("foo"); - reporter.test(expected.toEqual(Jasmine.any(String)), - 'expect("foo").toEqual(Jasmine.any(String)) should return true'); - - expected = new Jasmine.Matchers(3); - reporter.test(expected.toEqual(Jasmine.any(Number)), - 'expect(3).toEqual(Jasmine.any(Number)) should return true'); - - expected = new Jasmine.Matchers("foo"); - reporter.test(! expected.toEqual(Jasmine.any(Function)), - 'expect("foo").toEqual(Jasmine.any(Function)) should return false'); - - expected = new Jasmine.Matchers(["foo", "goo"]); - reporter.test(expected.toEqual(["foo", Jasmine.any(String)]), - 'expect(["foo", "goo"]).toEqual(["foo", Jasmine.any(String)]) should return true'); - - expected = new Jasmine.Matchers(function () { - }); - reporter.test(expected.toEqual(Jasmine.any(Function)), - 'expect(function () {}).toEqual(Jasmine.any(Function)) should return true'); - - - expected = new Jasmine.Matchers({foo: "bar", baz: undefined}); - reporter.test(expected.toEqual({foo: "bar", baz: undefined}), - 'expect({foo: "bar", baz: undefined}).toEqual({foo: "bar", baz: undefined}) should return true'); - - expected = new Jasmine.Matchers({foo:['bar','baz','quux']}); - reporter.test(expected.toEqual({foo:['bar','baz','quux']}), - "expect({foo:['bar','baz','quux']}).toEqual({foo:['bar','baz','quux']}) returned true"); - - expected = new Jasmine.Matchers({foo: {bar:'baz'}, quux:'corge'}); - reporter.test(expected.toEqual({foo:{bar:'baz'}, quux:'corge'}), - 'expect({foo:{bar:"baz"}, quux:"corge"}).toEqual({foo: {bar: \'baz\'}, quux:\'corge\'}) returned true'); - - expected = new Jasmine.Matchers({x:"x", y:"y", z:"w"}); - reporter.test(expected.toNotEqual({x:"x", y:"y", z:"z"}), - 'expect({x:"x", y:"y", z:"w"}).toNotEqual({x:"x", y:"y", z:"w"}) returned true'); - - expected = new Jasmine.Matchers({x:"x", y:"y", w:"z"}); - reporter.test(expected.toNotEqual({x:"x", y:"y", z:"z"}), - 'expect({x:"x", y:"y", w:"z"}).toNotEqual({x:"x", y:"y", z:"z"}) returned true'); - - expected = new Jasmine.Matchers({x:"x", y:"y", z:"z"}); - reporter.test(expected.toNotEqual({w: "w", x:"x", y:"y", z:"z"}), - 'expect({x:"x", y:"y", z:"z"}).toNotEqual({w: "w", x:"x", y:"y", z:"z"}) returned true'); - - expected = new Jasmine.Matchers({w: "w", x:"x", y:"y", z:"z"}); - reporter.test(expected.toNotEqual({x:"x", y:"y", z:"z"}), - 'expect({w: "w", x:"x", y:"y", z:"z"}).toNotEqual({x:"x", y:"y", z:"z"}) returned true'); - - expected = new Jasmine.Matchers([1, "A"]); - reporter.test(expected.toEqual([1, "A"]), - 'expect([1, "A"]).toEqual([1, "A"]) returned true'); - - - var expected = new Jasmine.Matchers(['A', 'B', 'C']); - reporter.test(expected.toContain('A'), - 'expect(["A", "B", "C").toContain("A") returned false'); - reporter.test(!expected.toContain('F'), - 'expect(["A", "B", "C").toContain("F") returned true'); - reporter.test(expected.toNotContain('F'), - 'expect(["A", "B", "C").toNotContain("F") returned false'); - reporter.test(!expected.toNotContain('A'), - 'expect(["A", "B", "C").toNotContain("A") returned true'); - - var currentSuite = describe('default current suite', function() { - }); - var spec = it(); - var TestClass = { someFunction: function() { - } }; - - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(!expected.wasCalled(), - 'expect(TestClass.someFunction).wasCalled() returned true for non-spies, expected false'); - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(!expected.wasNotCalled(), - 'expect(TestClass.someFunction).wasNotCalled() returned true for non-spies, expected false'); - - spec.spyOn(TestClass, 'someFunction'); - - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(!expected.wasCalled(), - 'expect(TestClass.someFunction).wasCalled() returned true when spies have not been called, expected false'); - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(expected.wasNotCalled(), - 'expect(TestClass.someFunction).wasNotCalled() returned false when spies have not been called, expected true'); - - TestClass.someFunction(); - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(expected.wasCalled(), - 'expect(TestClass.someFunction).wasCalled() returned false when spies have been called, expected true'); - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(!expected.wasNotCalled(), - 'expect(TestClass.someFunction).wasNotCalled() returned true when spies have been called, expected false'); - - TestClass.someFunction('a', 'b', 'c'); - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(expected.wasCalledWith('a', 'b', 'c'), - 'expect(TestClass.someFunction).wasCalledWith(\'a\', \'b\', \'c\') returned false, expected true'); - - expected = new Jasmine.Matchers(TestClass.someFunction); - reporter.test(!expected.wasCalledWith('c', 'b', 'a'), - 'expect(TestClass.someFunction).wasCalledWith(\'c\', \'b\', \'a\') returned true, expected false'); - // todo: make this better... only one result should be added. [xian/rajan 20090310] - reporter.test(expected.results.results[0].passed, - 'result 0 (from wasCalled()) should be true'); - reporter.test(!expected.results.results[1].passed, - 'result 1 (from arguments comparison) should be false'); -}; - -var testMatchersPrettyPrinting = function () { - var sampleValue; - var expected; - var actual; - - sampleValue = 'some string'; - reporter.test((Jasmine.pp(sampleValue) === "'some string'"), - "Expected Jasmine.pp('some string') to return the string 'some string' but got " + Jasmine.pp(sampleValue)); - - sampleValue = true; - reporter.test((Jasmine.pp(sampleValue) === 'true'), - "Expected Jasmine.pp(true) to return the string 'true' but got " + Jasmine.pp(sampleValue)); - - sampleValue = false; - reporter.test((Jasmine.pp(sampleValue) === 'false'), - "Expected Jasmine.pp(false) to return the string 'false' but got " + Jasmine.pp(sampleValue)); - - sampleValue = null; - reporter.test((Jasmine.pp(sampleValue) === 'null'), - "Expected Jasmine.pp(null) to return the string 'null' but got " + Jasmine.pp(sampleValue)); - - sampleValue = undefined; - reporter.test((Jasmine.pp(sampleValue) === 'undefined'), - "Expected Jasmine.pp(undefined) to return the string 'undefined' but got " + Jasmine.pp(sampleValue)); - - sampleValue = 3; - reporter.test((Jasmine.pp(sampleValue) === '3'), - "Expected Jasmine.pp(3) to return the string '3' but got " + Jasmine.pp(sampleValue)); - - sampleValue = [1, 2]; - reporter.test((Jasmine.pp(sampleValue) === '[ 1, 2 ]'), - "Expected Jasmine.pp([ 1, 2 ]) to return the string '[ 1, 2 ]' but got " + Jasmine.pp(sampleValue)); - - var array1 = [1, 2]; - var array2 = [array1]; - array1.push(array2); - sampleValue = array1; - expected = '[ 1, 2, [ ] ]'; - actual = Jasmine.pp(sampleValue); - reporter.test(actual === expected, - "Expected Jasmine.pp([ 1, 2, Array ]) to return the string " + '"' + expected + '"' + " but got " + actual); - - sampleValue = [1, 'foo', {}, undefined, null]; - expected = "[ 1, 'foo', { }, undefined, null ]"; - actual = Jasmine.pp(sampleValue); - reporter.test(actual === expected, - "Expected Jasmine.pp([ 1, 'foo', Object, undefined, null ]) to return the string " + '"' + expected + '"' + " but got " + actual); - - sampleValue = window; - expected = ""; - actual = Jasmine.pp(sampleValue); - reporter.test(actual === expected, - "Expected Jasmine.pp() to return the string " + '"' + expected + '"' + " but got " + actual); - - sampleValue = {foo: 'bar'}; - expected = "{ foo : 'bar' }"; - actual = Jasmine.pp(sampleValue); - reporter.test(actual === expected, - "Expected Jasmine.pp({ foo : 'bar' }) to return the string " + '"' + expected + '"' + " but got " + actual); - - sampleValue = {foo:'bar', baz:3, nullValue: null, undefinedValue: undefined}; - expected = "{ foo : 'bar', baz : 3, nullValue : null, undefinedValue : undefined }"; - actual = Jasmine.pp(sampleValue); - reporter.test(actual === expected, - "Expected Jasmine.pp(" + '"' + "{ foo : 'bar', baz : 3, nullValue : null, undefinedValue : undefined }" + '"' + " to return the string " + '"' + expected + '"' + " but got " + actual); - - sampleValue = {foo: function () { - }, bar: [1, 2, 3]}; - expected = "{ foo : Function, bar : [ 1, 2, 3 ] }"; - actual = Jasmine.pp(sampleValue); - reporter.test(actual === expected, - "Expected Jasmine.pp(" + '"' + "{ foo : function () {}, bar : [1, 2, 3] }" + '"' + " to return the string " + '"' + expected + '"' + " but got " + actual); - - sampleValue = {foo: 'hello'}; - sampleValue.nested = sampleValue; - expected = "{ foo : 'hello', nested : }"; - actual = Jasmine.pp(sampleValue); - reporter.test(actual === expected, - "Expected Jasmine.pp({foo: \'hello\'}) to return the string " + '"' + expected + '"' + " but got " + actual); - - var sampleNode = document.createElement('div'); - sampleNode.innerHTML = 'foobar'; - sampleValue = sampleNode; - reporter.test((Jasmine.pp(sampleValue) === "HTMLNode"), - "Expected Jasmine.pp(" + sampleValue + ") to return the string " + '"' + "HTMLNode" + '"' + " but got " + Jasmine.pp(sampleValue)); - - sampleValue = {foo: sampleNode}; - reporter.test((Jasmine.pp(sampleValue) === "{ foo : HTMLNode }"), - "Expected Jasmine.pp({ foo : " + sampleNode + " }) to return the string " + '"' + "{ foo: HTMLNode }" + '"' + " but got " + Jasmine.pp(sampleValue)); - - //todo object with function -}; - -var testMatchersReporting = function () { - - var results = []; - var expected = new Jasmine.Matchers(true, results); - expected.toEqual(true); - expected.toEqual(false); - - reporter.test((results.length == 2), - "Results array doesn't have 2 results"); - - reporter.test((results[0].passed === true), - "First spec didn't pass"); - - reporter.test((results[1].passed === false), - "Second spec did pass"); - - results = []; - expected = new Jasmine.Matchers(false, results); - expected.toEqual(true); - - var expectedMessage = 'Expected

true

but got

false
'; - reporter.test((results[0].message == expectedMessage), - "Failed expectation didn't test the failure message, expected: " + expectedMessage + " got: " + results[0].message); - - results = []; - expected = new Jasmine.Matchers(null, results); - expected.toEqual('not null'); - - expectedMessage = 'Expected

\'not null\'

but got

null
'; - reporter.test((results[0].message == expectedMessage), - "Failed expectation didn't test the failure message, expected: " + expectedMessage + " got: " + results[0].message); - - results = []; - expected = new Jasmine.Matchers(undefined, results); - expected.toEqual('not undefined'); - - expectedMessage = 'Expected

\'not undefined\'

but got

undefined
'; - reporter.test((results[0].message == expectedMessage), - "Failed expectation didn't test the failure message, expected: " + expectedMessage + " got: " + results[0].message); - - - results = []; - expected = new Jasmine.Matchers({foo:'one',baz:'two', more: 'blah'}, results); - expected.toEqual({foo:'one', bar: 'three &', baz: '2'}); - - expectedMessage = - "Expected

{ foo : 'one', bar : '<b>three</b> &', baz : '2' }

but got

{ foo : 'one', baz : 'two', more : 'blah' }
" + - "

Different Keys:
" + - "expected has key 'bar', but missing from actual.
" + - "expected missing key 'more', but present in actual.
" + - "

Different Values:
" + - "'bar' was

'<b>three</b> &'

in expected, but was

'undefined'

in actual.

" + - "'baz' was

'2'

in expected, but was

'two'

in actual.

"; - var actualMessage = results[0].message; - reporter.test((actualMessage == expectedMessage), - "Matcher message was incorrect. This is the message we expected:

" + expectedMessage + "

This is the message we got:

" + actualMessage); - - - results = []; - expected = new Jasmine.Matchers(true, results); - expected.toEqual(true); - - reporter.test((results[0].message == 'Passed.'), - "Passing expectation didn't test the passing message"); -}; - -var testDisabledSpecs = function () { - var xitSpecWasRun = false; - var suite = describe('default current suite', function() { - - xit('disabled spec').runs(function () { - xitSpecWasRun = true; - }); - - it('enabled spec').runs(function () { - var foo = 'bar'; - expect(foo).toEqual('bar'); - }); - - }); - - +function runSuite(filename) { + var suite = jasmine.include(filename); suite.execute(); - - reporter.test((suite.specs.length === 1), - "Only one spec should be defined in this suite."); - - reporter.test((xitSpecWasRun === false), - "xitSpec should not have been run."); - -}; - -var testDisabledSuites = function() { - var dontChangeMe = 'dontChangeMe'; - var disabledSuite = xdescribe('a disabled suite', function() { - it('enabled spec, but should not be run', function() { - dontChangeMe = 'changed'; - }); - }); - - disabledSuite.execute(); - - reporter.test((dontChangeMe === 'dontChangeMe'), - "spec in disabled suite should not have been run."); -}; - -var testSpecs = function () { - var currentSuite = describe('default current suite', function() { - }); - - var spec = it('new spec'); - reporter.test((spec.description == 'new spec'), - "Spec did not have a description"); - - var another_spec = it('spec with an expectation').runs(function () { - var foo = 'bar'; - expect(foo).toEqual('bar'); - }); - another_spec.execute(); - another_spec.done = true; - - reporter.test((another_spec.results.results.length === 1), - "Results aren't there after a spec was executed"); - reporter.test((another_spec.results.results[0].passed === true), - "Results has a result, but it's true"); - reporter.test((another_spec.results.description === 'spec with an expectation'), - "Spec's results did not get the spec's description"); - - var yet_another_spec = it('spec with failing expectation').runs(function () { - var foo = 'bar'; - expect(foo).toEqual('baz'); - }); - yet_another_spec.execute(); - yet_another_spec.done = true; - - reporter.test((yet_another_spec.results.results[0].passed === false), - "Expectation that failed, passed"); - - var yet_yet_another_spec = it('spec with multiple assertions').runs(function () { - var foo = 'bar'; - var baz = 'quux'; - - expect(foo).toEqual('bar'); - expect(baz).toEqual('quux'); - }); - yet_yet_another_spec.execute(); - yet_yet_another_spec.done = true; - - reporter.test((yet_yet_another_spec.results.results.length === 2), - "Spec doesn't support multiple expectations"); -}; - -var testSpecsWithoutRunsBlock = function () { - var currentSuite = describe('default current suite', function() { - }); - - var another_spec = it('spec with an expectation', function () { - var foo = 'bar'; - expect(foo).toEqual('bar'); - expect(foo).toEqual('baz'); - }); - - another_spec.execute(); - another_spec.done = true; - - reporter.test((another_spec.results.results.length === 2), - "Results length should be 2, got " + another_spec.results.results.length); - reporter.test((another_spec.results.results[0].passed === true), - "In a spec without a run block, expected first expectation result to be true but was false"); - reporter.test((another_spec.results.results[1].passed === false), - "In a spec without a run block, expected second expectation result to be false but was true"); - reporter.test((another_spec.results.description === 'spec with an expectation'), - "In a spec without a run block, results did not include the spec's description"); - -}; - -var testAsyncSpecs = function () { - var foo = 0; - - //set a bogus suite for the spec to attach to - Jasmine.getEnv().currentSuite = {specs: []}; - - var a_spec = it('simple queue test', function () { - runs(function () { - foo++; - }); - runs(function () { - expect(foo).toEqual(1); - }); - }); - - reporter.test(a_spec.queue.length === 1, - 'Expected spec queue length to be 1, was ' + a_spec.queue.length); - - a_spec.execute(); - reporter.test(a_spec.queue.length === 3, - 'Expected spec queue length to be 3, was ' + a_spec.queue.length); - - foo = 0; - a_spec = it('spec w/ queued statments', function () { - runs(function () { - foo++; - }); - runs(function () { - expect(foo).toEqual(1); - }); - }); - - a_spec.execute(); - - reporter.test((a_spec.results.results.length === 1), - 'No call to waits(): Spec queue did not run all functions'); - reporter.test((a_spec.results.results[0].passed === true), - 'No call to waits(): Queued expectation failed'); - - foo = 0; - a_spec = it('spec w/ queued statments', function () { - runs(function () { - setTimeout(function() { - foo++; - }, 500); - }); - waits(1000); - runs(function() { - expect(foo).toEqual(1); - }); - }); - - a_spec.execute(); - Clock.tick(500); - Clock.tick(500); - - reporter.test((a_spec.results.results.length === 1), - 'Calling waits(): Spec queue did not run all functions'); - - reporter.test((a_spec.results.results[0].passed === true), - 'Calling waits(): Queued expectation failed'); - - var bar = 0; - var another_spec = it('spec w/ queued statments', function () { - runs(function () { - setTimeout(function() { - bar++; - }, 250); - - }); - waits(500); - runs(function () { - setTimeout(function() { - bar++; - }, 250); - }); - waits(500); - runs(function () { - expect(bar).toEqual(2); - }); - }); - - reporter.test((another_spec.queue.length === 1), - 'Calling 2 waits(): Expected queue length to be 1, got ' + another_spec.queue.length); - - another_spec.execute(); - - Clock.tick(1000); - reporter.test((another_spec.queue.length === 4), - 'Calling 2 waits(): Expected queue length to be 4, got ' + another_spec.queue.length); - - reporter.test((another_spec.results.results.length === 1), - 'Calling 2 waits(): Spec queue did not run all functions'); - - reporter.test((another_spec.results.results[0].passed === true), - 'Calling 2 waits(): Queued expectation failed'); - - var baz = 0; - var yet_another_spec = it('spec w/ async fail', function () { - runs(function () { - setTimeout(function() { - baz++; - }, 250); - }); - waits(100); - runs(function() { - expect(baz).toEqual(1); - }); - }); - - - yet_another_spec.execute(); - Clock.tick(250); - - reporter.test((yet_another_spec.queue.length === 3), - 'Calling 2 waits(): Expected queue length to be 3, got ' + another_spec.queue.length); - reporter.test((yet_another_spec.results.results.length === 1), - 'Calling 2 waits(): Spec queue did not run all functions'); - reporter.test((yet_another_spec.results.results[0].passed === false), - 'Calling 2 waits(): Queued expectation failed'); -}; - -var testAsyncSpecsWithMockSuite = function () { - var bar = 0; - var another_spec = it('spec w/ queued statments', function () { - runs(function () { - setTimeout(function() { - bar++; - }, 250); - }); - waits(500); - runs(function () { - setTimeout(function() { - bar++; - }, 250); - }); - waits(1500); - runs(function() { - expect(bar).toEqual(2); - }); - }); - - another_spec.execute(); - Clock.tick(2000); - reporter.test((another_spec.queue.length === 4), - 'Calling 2 waits(): Expected queue length to be 4, got ' + another_spec.queue.length); - reporter.test((another_spec.results.results.length === 1), - 'Calling 2 waits(): Spec queue did not run all functions'); - reporter.test((another_spec.results.results[0].passed === true), - 'Calling 2 waits(): Queued expectation failed'); -}; - -var testWaitsFor = function() { - var doneWaiting = false; - var runsBlockExecuted = false; - - var spec; - describe('foo', function() { - spec = it('has a waits for', function() { - runs(function() { - }); - - waitsFor(500, function() { - return doneWaiting; - }); - - runs(function() { - runsBlockExecuted = true; - }); - }); - }); - - spec.execute(); - reporter.test(runsBlockExecuted === false, 'should not have executed runs block yet'); - Clock.tick(100); - doneWaiting = true; - Clock.tick(100); - reporter.test(runsBlockExecuted === true, 'should have executed runs block'); -}; - -var testWaitsForFailsWithMessage = function() { - var spec; - describe('foo', function() { - spec = it('has a waits for', function() { - runs(function() { - }); - - waitsFor(500, function() { - return false; // force a timeout - }, 'my awesome condition'); - - runs(function() { - }); - }); - }); - - spec.execute(); - Clock.tick(1000); - var actual = spec.results.results[0].message; - var expected = 'timeout: timed out after 500 msec waiting for my awesome condition'; - reporter.test(actual === expected, - 'expected "' + expected + '" but found "' + actual + '"'); -}; - -var testWaitsForFailsIfTimeout = function() { - var runsBlockExecuted = false; - - var spec; - describe('foo', function() { - spec = it('has a waits for', function() { - runs(function() { - }); - - waitsFor(500, function() { - return false; // force a timeout - }); - - runs(function() { - runsBlockExecuted = true; - }); - }); - }); - - spec.execute(); - reporter.test(runsBlockExecuted === false, 'should not have executed runs block yet'); - Clock.tick(100); - reporter.test(runsBlockExecuted === false, 'should not have executed runs block yet'); - Clock.tick(400); - reporter.test(runsBlockExecuted === false, 'should have timed out, so the second runs block should not have been called'); - var actual = spec.results.results[0].message; - var expected = 'timeout: timed out after 500 msec waiting for something to happen'; - reporter.test(actual === expected, - 'expected "' + expected + '" but found "' + actual + '"'); -}; - -var testSpecAfter = function() { - var log = ""; - var spec; - var suite = describe("has after", function() { - spec = it('spec with after', function() { - runs(function() { - log += "spec"; - }); - }); - }); - spec.after(function() { - log += "after1"; - }); - spec.after(function() { - log += "after2"; - }); - - suite.execute(); - reporter.test((log == "specafter1after2"), "after function should be executed after spec runs"); -}; - -var testSuites = function () { - - // suite has a description - var suite = describe('one suite description', function() { - }); - reporter.test((suite.description == 'one suite description'), - 'Suite did not get a description'); - - // suite can have a test - suite = describe('one suite description', function () { - it('should be a test'); - }); - - reporter.test((suite.specs.length === 1), - 'Suite did not get a spec pushed'); - reporter.test((suite.specs[0].queue.length === 0), - "Suite's Spec should not have queuedFunctions"); - - suite = describe('one suite description', function () { - it('should be a test with queuedFunctions', function() { - runs(function() { - var foo = 0; - foo++; - }); - }); - }); - - reporter.test((suite.specs[0].queue.length === 1), - "Suite's spec did not get a function pushed"); - - suite = describe('one suite description', function () { - it('should be a test with queuedFunctions', function() { - runs(function() { - var foo = 0; - foo++; - }); - waits(100); - runs(function() { - var bar = 0; - bar++; - }); - - }); - }); - - reporter.test((suite.specs[0].queue.length === 1), - "Suite's spec length should have been 1, was " + suite.specs[0].queue.length); - - suite.execute(); - - reporter.test((suite.specs[0].queue.length === 3), - "Suite's spec length should have been 3, was " + suite.specs[0].queue.length); - - var foo = 0; - suite = describe('one suite description', function () { - it('should be a test with queuedFunctions', function() { - runs(function() { - foo++; - }); - }); - - it('should be a another spec with queuedFunctions', function() { - runs(function() { - foo++; - }); - }); - }); - - suite.execute(); - - reporter.test((suite.specs.length === 2), - "Suite doesn't have two specs"); - reporter.test((foo === 2), - "Suite didn't execute both specs"); -}; - -var testBeforeAndAfterCallbacks = function () { - - var suiteWithBefore = describe('one suite with a before', function () { - - beforeEach(function () { - this.foo = 1; - }); - - it('should be a spec', function () { - runs(function() { - this.foo++; - expect(this.foo).toEqual(2); - }); - }); - - it('should be another spec', function () { - runs(function() { - this.foo++; - expect(this.foo).toEqual(2); - }); - }); - }); - - suiteWithBefore.execute(); - var suite = suiteWithBefore; - reporter.test((suite.beforeEach !== undefined), - "testBeforeAndAfterCallbacks: Suite's beforeEach was not defined"); - reporter.test((suite.results.results[0].results[0].passed === true), - "testBeforeAndAfterCallbacks: the first spec's foo should have been 2"); - reporter.test((suite.results.results[1].results[0].passed === true), - "testBeforeAndAfterCallbacks: the second spec's this.foo should have been 2"); - - var suiteWithAfter = describe('one suite with an after_each', function () { - - it('should be a spec with an after_each', function () { - runs(function() { - this.foo = 0; - this.foo++; - expect(this.foo).toEqual(1); - }); - }); - - it('should be another spec with an after_each', function () { - runs(function() { - this.foo = 0; - this.foo++; - expect(this.foo).toEqual(1); - }); - }); - - afterEach(function () { - this.foo = 0; - }); - }); - - suiteWithAfter.execute(); - var suite = suiteWithAfter; - reporter.test((suite.afterEach !== undefined), - "testBeforeAndAfterCallbacks: Suite's afterEach was not defined"); - reporter.test((suite.results.results[0].results[0].passed === true), - "testBeforeAndAfterCallbacks: afterEach failure: " + suite.results.results[0].results[0].message); - reporter.test((suite.specs[0].foo === 0), - "testBeforeAndAfterCallbacks: afterEach failure: foo was not reset to 0"); - reporter.test((suite.results.results[1].results[0].passed === true), - "testBeforeAndAfterCallbacks: afterEach failure: " + suite.results.results[0].results[0].message); - reporter.test((suite.specs[1].foo === 0), - "testBeforeAndAfterCallbacks: afterEach failure: foo was not reset to 0"); - -}; - -var testBeforeExecutesSafely = function() { - var report = ""; - var suite = describe('before fails on first test, passes on second', function() { - var counter = 0; - beforeEach(function() { - counter++; - if (counter == 1) { - throw "before failure"; - } - }); - it("first should not run because before fails", function() { - runs(function() { - report += "first"; - expect(true).toEqual(true); - }); - }); - it("second should run and pass because before passes", function() { - runs(function() { - report += "second"; - expect(true).toEqual(true); - }); - }); - }); - - suite.execute(); - - reporter.test((report === "firstsecond"), "both tests should run"); - reporter.test(suite.specs[0].results.results[0].passed === false, "1st spec should fail"); - reporter.test(suite.specs[1].results.results[0].passed === true, "2nd spec should pass"); - - reporter.test(suite.specResults[0].results[0].passed === false, "1st spec should fail"); - reporter.test(suite.specResults[1].results[0].passed === true, "2nd spec should pass"); -}; - -var testAfterExecutesSafely = function() { - var report = ""; - var suite = describe('after fails on first test, then passes', function() { - var counter = 0; - afterEach(function() { - counter++; - if (counter == 1) { - throw "after failure"; - } - }); - it("first should run, expectation passes, but spec fails because after fails", function() { - runs(function() { - report += "first"; - expect(true).toEqual(true); - }); - }); - it("second should run and pass because after passes", function() { - runs(function() { - report += "second"; - expect(true).toEqual(true); - }); - }); - it("third should run and pass because after passes", function() { - runs(function() { - report += "third"; - expect(true).toEqual(true); - }); - }); - }); - - suite.execute(); - - reporter.test((report === "firstsecondthird"), "all tests should run"); - //After each errors should not go in spec results because it confuses the count. - reporter.test(suite.specs.length === 3, 'testAfterExecutesSafely should have results for three specs'); - reporter.test(suite.specs[0].results.results[0].passed === true, "testAfterExecutesSafely 1st spec should pass"); - reporter.test(suite.specs[1].results.results[0].passed === true, "testAfterExecutesSafely 2nd spec should pass"); - reporter.test(suite.specs[2].results.results[0].passed === true, "testAfterExecutesSafely 3rd spec should pass"); - - reporter.test(suite.specResults[0].results[0].passed === true, "testAfterExecutesSafely 1st result for 1st suite spec should pass"); - reporter.test(suite.specResults[0].results[1].passed === false, "testAfterExecutesSafely 2nd result for 1st suite spec should fail because afterEach failed"); - reporter.test(suite.specResults[1].results[0].passed === true, "testAfterExecutesSafely 2nd suite spec should pass"); - reporter.test(suite.specResults[2].results[0].passed === true, "testAfterExecutesSafely 3rd suite spec should pass"); - -}; - - -var testSpecSpy = function () { - var suite = describe('Spec spying', function () { - it('should replace the specified function with a spy object', function() { - var originalFunctionWasCalled = false; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - } - }; - this.spyOn(TestClass, 'someFunction'); - - expect(TestClass.someFunction.wasCalled).toEqual(false); - expect(TestClass.someFunction.callCount).toEqual(0); - TestClass.someFunction('foo'); - expect(TestClass.someFunction.wasCalled).toEqual(true); - expect(TestClass.someFunction.callCount).toEqual(1); - expect(TestClass.someFunction.mostRecentCall.args).toEqual(['foo']); - expect(TestClass.someFunction.mostRecentCall.object).toEqual(TestClass); - expect(originalFunctionWasCalled).toEqual(false); - - TestClass.someFunction('bar'); - expect(TestClass.someFunction.callCount).toEqual(2); - expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']); - }); - - it('should return allow you to view args for a particular call', function() { - var originalFunctionWasCalled = false; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - } - }; - this.spyOn(TestClass, 'someFunction'); - - TestClass.someFunction('foo'); - TestClass.someFunction('bar'); - expect(TestClass.someFunction.argsForCall[0]).toEqual(['foo']); - expect(TestClass.someFunction.argsForCall[1]).toEqual(['bar']); - expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']); - }); - - it('should be possible to call through to the original method, or return a specific result', function() { - var originalFunctionWasCalled = false; - var passedArgs; - var passedObj; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - passedArgs = arguments; - passedObj = this; - return "return value from original function"; - } - }; - - this.spyOn(TestClass, 'someFunction').andCallThrough(); - var result = TestClass.someFunction('arg1', 'arg2'); - expect(result).toEqual("return value from original function"); - expect(originalFunctionWasCalled).toEqual(true); - expect(passedArgs).toEqual(['arg1', 'arg2']); - expect(passedObj).toEqual(TestClass); - expect(TestClass.someFunction.wasCalled).toEqual(true); - }); - - it('should be possible to return a specific value', function() { - var originalFunctionWasCalled = false; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - return "return value from original function"; - } - }; - - this.spyOn(TestClass, 'someFunction').andReturn("some value"); - originalFunctionWasCalled = false; - var result = TestClass.someFunction('arg1', 'arg2'); - expect(result).toEqual("some value"); - expect(originalFunctionWasCalled).toEqual(false); - }); - - it('should be possible to throw a specific error', function() { - var originalFunctionWasCalled = false; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - return "return value from original function"; - } - }; - - this.spyOn(TestClass, 'someFunction').andThrow(new Error('fake error')); - var exception; - try { - TestClass.someFunction('arg1', 'arg2'); - } catch (e) { - exception = e; - } - expect(exception.message).toEqual('fake error'); - expect(originalFunctionWasCalled).toEqual(false); - }); - - it('should be possible to call a specified function', function() { - var originalFunctionWasCalled = false; - var fakeFunctionWasCalled = false; - var passedArgs; - var passedObj; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - return "return value from original function"; - } - }; - - this.spyOn(TestClass, 'someFunction').andCallFake(function() { - fakeFunctionWasCalled = true; - passedArgs = arguments; - passedObj = this; - return "return value from fake function"; - }); - - var result = TestClass.someFunction('arg1', 'arg2'); - expect(result).toEqual("return value from fake function"); - expect(originalFunctionWasCalled).toEqual(false); - expect(fakeFunctionWasCalled).toEqual(true); - expect(passedArgs).toEqual(['arg1', 'arg2']); - expect(passedObj).toEqual(TestClass); - expect(TestClass.someFunction.wasCalled).toEqual(true); - }); - - it('is torn down when Pockets.removeAllSpies is called', function() { - var originalFunctionWasCalled = false; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - } - }; - this.spyOn(TestClass, 'someFunction'); - - TestClass.someFunction('foo'); - expect(originalFunctionWasCalled).toEqual(false); - - this.removeAllSpies(); - - TestClass.someFunction('foo'); - expect(originalFunctionWasCalled).toEqual(true); - }); - - it('adds removeAllSpies to the after spec teardown', function() { - var originalFunctionWasCalled = false; - var TestClass = { - someFunction: function() { - originalFunctionWasCalled = true; - } - }; - - expect(this.afterCallbacks.length).toEqual(0); - - this.spyOn(TestClass, 'someFunction'); - - expect(this.afterCallbacks.length).toEqual(1); - this.afterCallbacks[0].call(); - - TestClass.someFunction('foo'); - expect(originalFunctionWasCalled).toEqual(true); - }); - - it('throws an exception when some method is spied on twice', function() { - var TestClass = { someFunction: function() { - } }; - this.spyOn(TestClass, 'someFunction'); - var exception; - try { - this.spyOn(TestClass, 'someFunction'); - } catch (e) { - exception = e; - } - expect(exception).toBeDefined(); - }); - - it('should be able to reset a spy', function() { - var TestClass = { someFunction: function() { - } }; - this.spyOn(TestClass, 'someFunction'); - - expect(TestClass.someFunction).wasNotCalled(); - TestClass.someFunction(); - expect(TestClass.someFunction).wasCalled(); - TestClass.someFunction.reset(); - expect(TestClass.someFunction).wasNotCalled(); - expect(TestClass.someFunction.callCount).toEqual(0); - }); - }); - - suite.execute(); - - for (var j = 0; j < suite.specResults.length; j++) { - reporter.test(suite.specResults[j].results.length > 0, "testSpecSpy: should have results, got " + suite.specResults[j].results.length); - for (var i = 0; i < suite.specResults[j].results.length; i++) { - reporter.test(suite.specResults[j].results[i].passed === true, "testSpecSpy: expectation number " + i + " failed: " + suite.specResults[j].results[i].message); + emitSuiteResults(filename, suite); +} + +function emitSpecResults(testName, spec) { + var results = spec.results.getItems(); + reporter.test(results.length > 0, testName + ": should have results, got " + results.length); + + for (var i = 0; i < results.length; i++) { + reporter.test(results[i].passed === true, testName + ':' + spec.getFullName() + ": expectation number " + i + " failed: " + results[i].message); + } +} + +function emitSuiteResults(testName, suite) { + for (var j = 0; j < suite.specs.length; j++) { + var specOrSuite = suite.specs[j]; + + if (specOrSuite instanceof jasmine.Suite) { + emitSuiteResults(testName, specOrSuite); + } else { + emitSpecResults(testName, specOrSuite); } } -}; +} var testExplodes = function () { var suite = describe('exploding', function () { @@ -1301,362 +97,53 @@ var testExplodes = function () { }); suite.execute(); - for (var j = 0; j < suite.specResults.length; j++) { - reporter.test(suite.specResults[j].results.length > 0, "testExplodes: should have results, got " + suite.specResults[j].results.length); - for (var i = 0; i < suite.specResults[j].results.length; i++) { - reporter.test(suite.specResults[j].results[i].passed === true, "testExplodes: expectation number " + i + " failed: " + suite.specResults[j].results[i].message); - } - } -}; - -var testSpecScope = function () { - - var suite = describe('one suite description', function () { - it('should be a test with queuedFunctions', function() { - runs(function() { - this.foo = 0; - this.foo++; - }); - - runs(function() { - var that = this; - setTimeout(function() { - that.foo++; - }, 250); - }); - - runs(function() { - expect(this.foo).toEqual(2); - }); - - waits(300); - - runs(function() { - expect(this.foo).toEqual(2); - }); - }); - - }); - - suite.execute(); - Clock.tick(600); - reporter.test((suite.specs[0].foo === 2), - "Spec does not maintain scope in between functions"); - reporter.test((suite.specs[0].results.results.length === 2), - "Spec did not get results for all expectations"); - reporter.test((suite.specs[0].results.results[0].passed === false), - "Spec did not return false for a failed expectation"); - reporter.test((suite.specs[0].results.results[1].passed === true), - "Spec did not return true for a passing expectation"); - reporter.test((suite.results.description === 'one suite description'), - "Suite did not get its description in the results"); + emitSuiteResults('testExplodes', suite); }; +function newJasmineEnv() { + return new jasmine.Env(); +} var testRunner = function() { - - var runner = Runner(); - describe('one suite description', function () { - it('should be a test'); - }); - reporter.test((runner.suites.length === 1), - "Runner expected one suite, got " + runner.suites.length); - - runner = Runner(); - describe('one suite description', function () { - it('should be a test'); - }); - describe('another suite description', function () { - it('should be a test'); - }); - reporter.test((runner.suites.length === 2), - "Runner expected two suites, but got " + runner.suites.length); - - runner = Runner(); - describe('one suite description', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - }); - - describe('another suite description', function () { - it('should be another test', function() { - runs(function () { - expect(true).toEqual(false); - }); - }); - }); - - runner.execute(); - - reporter.test((runner.suites.length === 2), - "Runner expected two suites, got " + runner.suites.length); - reporter.test((runner.suites[0].specs[0].results.results[0].passed === true), - "Runner should have run specs in first suite"); - reporter.test((runner.suites[1].specs[0].results.results[0].passed === false), - "Runner should have run specs in second suite"); - - runner = Runner(); - xdescribe('one suite description', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - }); - - describe('another suite description', function () { - it('should be another test', function() { - runs(function () { - expect(true).toEqual(false); - }); - }); - }); - - runner.execute(); - - reporter.test((runner.suites.length === 1), - "Runner expected 1 suite, got " + runner.suites.length); - reporter.test((runner.suites[0].specs[0].results.results[0].passed === false), - "Runner should have run specs in first suite"); - reporter.test((runner.suites[1] === undefined), - "Second suite should be undefined, but was " + reporter.toJSON(runner.suites[1])); }; var testRunnerFinishCallback = function () { - var runner = Runner(); + var env = newJasmineEnv(); var foo = 0; - runner.finish(); + env.currentRunner.finish(); - reporter.test((runner.finished === true), + reporter.test((env.currentRunner.finished === true), "Runner finished flag was not set."); - runner.finishCallback = function () { + env.currentRunner.finishCallback = function () { foo++; }; - runner.finish(); + env.currentRunner.finish(); - reporter.test((runner.finished === true), + reporter.test((env.currentRunner.finished === true), "Runner finished flag was not set."); reporter.test((foo === 1), "Runner finish callback was not called"); }; - -var testNestedResults = function () { - - // Leaf case - var results = new Jasmine.NestedResults(); - - results.push({passed: true, message: 'Passed.'}); - - reporter.test((results.results.length === 1), - "nestedResults.push didn't work"); - reporter.test((results.totalCount === 1), - "nestedResults.push didn't increment totalCount"); - reporter.test((results.passedCount === 1), - "nestedResults.push didn't increment passedCount"); - reporter.test((results.failedCount === 0), - "nestedResults.push didn't ignore failedCount"); - - results.push({passed: false, message: 'FAIL.'}); - - reporter.test((results.results.length === 2), - "nestedResults.push didn't work"); - reporter.test((results.totalCount === 2), - "nestedResults.push didn't increment totalCount"); - reporter.test((results.passedCount === 1), - "nestedResults.push didn't ignore passedCount"); - reporter.test((results.failedCount === 1), - "nestedResults.push didn't increment failedCount"); - - // Branch case - var leafResultsOne = new Jasmine.NestedResults(); - leafResultsOne.push({passed: true, message: ''}); - leafResultsOne.push({passed: false, message: ''}); - - var leafResultsTwo = new Jasmine.NestedResults(); - leafResultsTwo.push({passed: true, message: ''}); - leafResultsTwo.push({passed: false, message: ''}); - - var branchResults = new Jasmine.NestedResults(); - branchResults.push(leafResultsOne); - branchResults.push(leafResultsTwo); - - reporter.test((branchResults.results.length === 2), - "Branch Results should have 2 nestedResults, has " + branchResults.results.length); - reporter.test((branchResults.totalCount === 4), - "Branch Results should have 4 results, has " + branchResults.totalCount); - reporter.test((branchResults.passedCount === 2), - "Branch Results should have 2 passed, has " + branchResults.passedCount); - reporter.test((branchResults.failedCount === 2), - "Branch Results should have 2 failed, has " + branchResults.failedCount); -}; - -var testResults = function () { - var runner = Runner(); - describe('one suite description', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - }); - - describe('another suite description', function () { - it('should be another test', function() { - runs(function () { - expect(true).toEqual(false); - }); - }); - }); - - runner.execute(); - - reporter.test((runner.results.totalCount === 2), - 'Expectation count should be 2, but was ' + runner.results.totalCount); - reporter.test((runner.results.passedCount === 1), - 'Expectation Passed count should be 1, but was ' + runner.results.passedCount); - reporter.test((runner.results.failedCount === 1), - 'Expectation Failed count should be 1, but was ' + runner.results.failedCount); - reporter.test((runner.results.description === 'All Jasmine Suites'), - 'Jasmine Runner does not have the expected description, has: ' + runner.results.description); - -}; - -var testReporterWithCallbacks = function () { - Jasmine.currentEnv_ = new Jasmine.Env(); - var runner = Runner(); - - describe('Suite for JSON Reporter with Callbacks', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - it('should be a failing test', function() { - runs(function () { - expect(false).toEqual(true); - }); - }); - }); - describe('Suite for JSON Reporter with Callbacks 2', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - - }); - - var foo = 0; - var bar = 0; - var baz = 0; - - var specCallback = function (results) { - foo++; - }; - var suiteCallback = function (results) { - bar++; - }; - var runnerCallback = function (results) { - baz++; - }; - - Jasmine.getEnv().reporter = Jasmine.Reporters.reporter({ - specCallback: specCallback, - suiteCallback: suiteCallback, - runnerCallback: runnerCallback - }); - runner.execute(); - - reporter.test((foo === 3), - 'foo was expected to be 3, was ' + foo); - reporter.test((bar === 2), - 'bar was expected to be 2, was ' + bar); - reporter.test((baz === 1), - 'baz was expected to be 1, was ' + baz); -}; - -var testJSONReporter = function () { - Jasmine.currentEnv_ = new Jasmine.Env(); - var runner = Runner(); - - describe('Suite for JSON Reporter, NO DOM', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - }); - - Jasmine.getEnv().reporter = Jasmine.Reporters.JSON(); - - runner.execute(); - - var expectedSpecJSON = '{"totalCount":1,"passedCount":1,"failedCount":0,"results":[{"passed":true,"message":"Passed."}],"description":"should be a test"}'; - var expectedSuiteJSON = '{"totalCount":1,"passedCount":1,"failedCount":0,"results":[' + expectedSpecJSON + '],"description":"Suite for JSON Reporter, NO DOM"}'; - var expectedRunnerJSON = '{"totalCount":1,"passedCount":1,"failedCount":0,"results":[' + expectedSuiteJSON + '],"description":"All Jasmine Suites"}'; - - var specJSON = Jasmine.getEnv().reporter.specJSON; - reporter.test((specJSON === expectedSpecJSON), - 'JSON Reporter does not have the expected Spec results report.
Expected:
' + expectedSpecJSON + - '
Got:
' + specJSON); - - var suiteJSON = Jasmine.getEnv().reporter.suiteJSON; - reporter.test((suiteJSON === expectedSuiteJSON), - 'JSON Reporter does not have the expected Suite results report.
Expected:
' + expectedSuiteJSON + - '
Got:
' + suiteJSON); - - var runnerJSON = Jasmine.getEnv().reporter.runnerJSON; - reporter.test((runnerJSON === expectedRunnerJSON), - 'JSON Reporter does not have the expected Runner results report.
Expected:
' + expectedRunnerJSON + - '
Got:
' + runnerJSON); -}; - -var testJSONReporterWithDOM = function () { - Jasmine.currentEnv_ = new Jasmine.Env(); - var runner = Runner(); - - describe('Suite for JSON Reporter/DOM', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - }); - - Jasmine.getEnv().reporter = Jasmine.Reporters.JSONtoDOM('json_reporter_results'); - runner.execute(); - - var expectedJsonString = '{"totalCount":1,"passedCount":1,"failedCount":0,"results":[{"totalCount":1,"passedCount":1,"failedCount":0,"results":[{"totalCount":1,"passedCount":1,"failedCount":0,"results":[{"passed":true,"message":"Passed."}],"description":"should be a test"}],"description":"Suite for JSON Reporter/DOM"}],"description":"All Jasmine Suites"}'; - //this statement makes sure we have a string that is the same across different DOM implementations. - var actualJsonString = document.getElementById('json_reporter_results').innerHTML.replace(/"/g, '"'); - reporter.test((actualJsonString == expectedJsonString), - 'JSON Reporter with DOM did not write the expected report to the DOM, got:

' + actualJsonString + '

expected

' + expectedJsonString); -}; - - var testHandlesBlankSpecs = function () { - Jasmine.currentEnv_ = new Jasmine.Env(); - var runner = Runner(); - describe('Suite for handles blank specs', function () { - it('should be a test with a blank runs block', function() { - runs(function () { + var env = newJasmineEnv(); + env.describe('Suite for handles blank specs', function () { + env.it('should be a test with a blank runs block', function() { + this.runs(function () { }); }); - it('should be a blank (empty function) test', function() { + env.it('should be a blank (empty function) test', function() { }); }); + var runner = env.currentRunner; runner.execute(); - reporter.test((runner.suites[0].specResults.length === 2), - 'Should have found 2 spec results, got ' + runner.suites[0].specResults.length); + reporter.test((runner.suites[0].results.getItems().length === 2), + 'Should have found 2 spec results, got ' + runner.suites[0].results.getItems().length); reporter.test((runner.suites[0].results.passedCount === 2), 'Should have found 2 passing specs, got ' + runner.suites[0].results.passedCount); }; @@ -1679,183 +166,127 @@ var testFormatsExceptionMessages = function () { var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)'; - reporter.test((Jasmine.util.formatException(sampleFirefoxException) === expected), - 'Should have got ' + expected + ' but got: ' + Jasmine.util.formatException(sampleFirefoxException)); + reporter.test((jasmine.util.formatException(sampleFirefoxException) === expected), + 'Should have got ' + expected + ' but got: ' + jasmine.util.formatException(sampleFirefoxException)); - reporter.test((Jasmine.util.formatException(sampleWebkitException) === expected), - 'Should have got ' + expected + ' but got: ' + Jasmine.util.formatException(sampleWebkitException)); + reporter.test((jasmine.util.formatException(sampleWebkitException) === expected), + 'Should have got ' + expected + ' but got: ' + jasmine.util.formatException(sampleWebkitException)); }; var testHandlesExceptions = function () { - Jasmine.currentEnv_ = new Jasmine.Env(); - var runner = Runner(); + var env = newJasmineEnv(); //we run two exception tests to make sure we continue after throwing an exception - describe('Suite for handles exceptions', function () { - it('should be a test that fails because it throws an exception', function() { - runs(function () { - fakeObject.fakeMethod(); + var suite = env.describe('Suite for handles exceptions', function () { + env.it('should be a test that fails because it throws an exception', function() { + this.runs(function () { + throw new Error('fake error 1'); }); }); - it('should be another test that fails because it throws an exception', function() { - runs(function () { - fakeObject2.fakeMethod2(); + env.it('should be another test that fails because it throws an exception', function() { + this.runs(function () { + throw new Error('fake error 2'); }); - runs(function () { - expect(true).toEqual(true); + this.runs(function () { + this.expect(true).toEqual(true); }); }); - it('should be a passing test that runs after exceptions are thrown', function() { - runs(function () { - expect(true).toEqual(true); + env.it('should be a passing test that runs after exceptions are thrown', function() { + this.runs(function () { + this.expect(true).toEqual(true); }); }); - it('should be another test that fails because it throws an exception after a wait', function() { - runs(function () { + env.it('should be another test that fails because it throws an exception after a wait', function() { + this.runs(function () { var foo = 'foo'; }); - waits(250); - runs(function () { - fakeObject3.fakeMethod(); + this.waits(250); + this.runs(function () { + throw new Error('fake error 3'); }); }); - it('should be a passing test that runs after exceptions are thrown from a async test', function() { - runs(function () { - expect(true).toEqual(true); + env.it('should be a passing test that runs after exceptions are thrown from a async test', function() { + this.runs(function () { + this.expect(true).toEqual(true); }); }); - - }); + + + var runner = env.currentRunner; runner.execute(); Clock.tick(400); //TODO: setting this to a large number causes failures, but shouldn't - reporter.test((runner.suites[0].specResults.length === 5), - 'Should have found 5 spec results, got ' + runner.suites[0].specResults.length); + var resultsForSpec0 = suite.specs[0].getResults(); + var resultsForSpec1 = suite.specs[1].getResults(); + var resultsForSpec2 = suite.specs[2].getResults(); + var resultsForSpec3 = suite.specs[3].getResults(); - reporter.test((runner.suites[0].specs[0].expectationResults[0].passed === false), - 'First test should have failed, got passed'); + reporter.test((suite.getResults().totalCount == 6), + 'Should have found 5 spec results, got ' + suite.getResults().totalCount); - reporter.test((typeof runner.suites[0].specs[0].expectationResults[0].message.search(/fakeObject/) !== -1), - 'First test should have contained /fakeObject/, got ' + runner.suites[0].specs[0].expectationResults[0].message); + reporter.test((resultsForSpec0.getItems()[0].passed === false), + 'Spec1 test, expectation 0 should have failed, got passed'); - reporter.test((runner.suites[0].specs[1].expectationResults[0].passed === false), - 'Second test should have a failing first result, got passed'); + reporter.test((resultsForSpec0.getItems()[0].message.match(/fake error 1/)), + 'Spec1 test, expectation 0 should have a message that contained /fake error 1/, got ' + resultsForSpec0.getItems()[0].message); - reporter.test((typeof runner.suites[0].specs[1].expectationResults[0].message.search(/fakeObject2/) !== -1), - 'Second test should have contained /fakeObject2/, got ' + runner.suites[0].specs[1].expectationResults[0].message); + reporter.test((resultsForSpec1.getItems()[0].passed === false), + 'Spec2 test, expectation 0 should have failed, got passed'); - reporter.test((runner.suites[0].specs[1].expectationResults[1].passed === true), - 'Second expectation in second test should have still passed'); + reporter.test((resultsForSpec1.getItems()[0].message.match(/fake error 2/)), + 'Spec2 test, expectation 0 should have a message that contained /fake error 2/, got ' + resultsForSpec1.getItems()[0].message); - reporter.test((runner.suites[0].specs[2].expectationResults[0].passed === true), - 'Third test should have passed, got failed'); + reporter.test((resultsForSpec1.getItems()[1].passed === true), + 'Spec2 test should have had a passing 2nd expectation'); - reporter.test((runner.suites[0].specs[3].expectationResults[0].passed === false), - 'Fourth test should have a failing first result, got passed'); + reporter.test((resultsForSpec2.getItems()[0].passed === true), + 'Spec3 test should have passed, got failed'); - reporter.test((typeof runner.suites[0].specs[3].expectationResults[0].message.search(/fakeObject3/) !== -1), - 'Fourth test should have contained /fakeObject3/, got ' + runner.suites[0].specs[3].expectationResults[0].message); + reporter.test((resultsForSpec3.getItems()[0].passed === false), + 'Spec3 test should have a failing first expectation, got passed'); + + reporter.test((resultsForSpec3.getItems()[0].message.match(/fake error 3/)), + 'Spec3 test should have an error message that contained /fake error 3/, got ' + resultsForSpec3.getItems()[0].message); }; var testResultsAliasing = function () { - Jasmine.currentEnv_ = new Jasmine.Env(); - var runner = Runner(); + var env = newJasmineEnv(); - describe('Suite for result aliasing test', function () { + env.describe('Suite for result aliasing test', function () { - it('should be a test', function() { - runs(function () { - expect(true).toEqual(true); + env.it('should be a test', function() { + this.runs(function () { + this.expect(true).toEqual(true); }); }); }); - describe('Suite number two for result aliasing test', function () { - it('should be a passing test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - - it('should be a passing test', function() { - runs(function () { - expect(true).toEqual(true); - }); - }); - - }); - - - runner.execute(); - - reporter.test((runner.suiteResults !== undefined), - 'runner.suiteResults was not defined'); - - reporter.test((runner.suiteResults == runner.results.results), - 'runner.suiteResults should have been ' + reporter.toJSON(runner.results.results) + - ', but was ' + reporter.toJSON(runner.suiteResults)); - - reporter.test((runner.suiteResults[1] == runner.results.results[1]), - 'runner.suiteResults should have been ' + reporter.toJSON(runner.results.results[1]) + - ', but was ' + reporter.toJSON(runner.suiteResults[1])); - - reporter.test((runner.suites[0].specResults !== undefined), - 'runner.suites[0].specResults was not defined'); - - reporter.test((runner.suites[0].specResults == runner.results.results[0].results), - 'runner.suites[0].specResults should have been ' + reporter.toJSON(runner.results.results[0].results) + - ', but was ' + reporter.toJSON(runner.suites[0].specResults)); - - reporter.test((runner.suites[0].specs[0].expectationResults !== undefined), - 'runner.suites[0].specs[0].expectationResults was not defined'); - - reporter.test((runner.suites[0].specs[0].expectationResults == runner.results.results[0].results[0].results), - 'runner.suites[0].specs[0].expectationResults should have been ' + reporter.toJSON(runner.results.results[0].results[0].results) + - ', but was ' + reporter.toJSON(runner.suites[0].specs[0].expectationResults)); - }; var runTests = function () { document.getElementById('spinner').style.display = ""; - testMatchersPrettyPrinting(); - testMatchersComparisons(); - testMatchersReporting(); - testDisabledSpecs(); - testDisabledSuites(); - testSpecs(); - testSpecsWithoutRunsBlock(); - testAsyncSpecs(); - testAsyncSpecsWithMockSuite(); - testWaitsFor(); - testWaitsForFailsWithMessage(); - testWaitsForFailsIfTimeout(); - testSpecAfter(); - testSuites(); - testBeforeAndAfterCallbacks(); - testBeforeExecutesSafely(); - testAfterExecutesSafely(); - testSpecScope(); - testRunner(); + runSuite('PrettyPrintTest.js'); + runSuite('MatchersTest.js'); + runSuite('SpecRunningTest.js'); testRunnerFinishCallback(); - testNestedResults(); - testResults(); + runSuite('NestedResultsTest.js'); testFormatsExceptionMessages(); testHandlesExceptions(); testResultsAliasing(); - testReporterWithCallbacks(); - testJSONReporter(); - testJSONReporterWithDOM(); - testSpecSpy(); + runSuite('ReporterTest.js'); + runSuite('RunnerTest.js'); + runSuite('JsonReporterTest.js'); + runSuite('SpyTest.js'); testExplodes(); diff --git a/test/mock-ajax.js b/test/mock-ajax.js new file mode 100644 index 0000000..c7eee61 --- /dev/null +++ b/test/mock-ajax.js @@ -0,0 +1,57 @@ +jasmine.AjaxRequests = { + requests: $A(), + + activeRequest: function() { + return this.requests.last(); + }, + + add: function(request) { + this.requests.push(request); + var spec = jasmine.getEnv().currentSpec; + spec.after(function() { jasmine.AjaxRequests.clear(); }); + }, + + remove: function(request) { + this.requests = this.requests.without(request); + }, + + clear: function() { + this.requests.clear(); + } +}; + +jasmine.AjaxRequest = Class.create(Ajax.Request, { + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + jasmine.AjaxRequests.add(this); + }, + + response: function(response) { + if (!response.status || response.status == 200 || response.status == "200") { + if (this.options.onSuccess) {this.options.onSuccess(response);} + } else { + if (this.options.onFailure) {this.options.onFailure(response);} + } + if (this.options.onComplete) {this.options.onComplete(response);} + jasmine.AjaxRequests.remove(this); + } +}); diff --git a/test/mock-timeout.js b/test/mock-timeout.js new file mode 100755 index 0000000..c959949 --- /dev/null +++ b/test/mock-timeout.js @@ -0,0 +1,158 @@ +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + + +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: window.setTimeout, + clearTimeout: window.clearTimeout, + setInterval: window.setInterval, + clearInterval: window.clearInterval + }, + + assertInstalled: function() { + if (jasmine.Clock.installed != jasmine.Clock.defaultFakeTimer) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +window.setTimeout = function(funcToCall, millis) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); +}; + +window.setInterval = function(funcToCall, millis) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); +}; + +window.clearTimeout = function(timeoutKey) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); +}; + +window.clearInterval = function(timeoutKey) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); +}; +