From 9475de28b306cc5498ad6dbb9e632bc57e5be1e8 Mon Sep 17 00:00:00 2001 From: ragaskar Date: Sat, 1 Aug 2009 15:28:39 -0700 Subject: [PATCH] Queue/Spec refactor --- lib/TrivialReporter.js | 2 +- lib/jasmine.js | 162 ++++++++++++++++++++++----------- spec/suites/ExceptionsTest.js | 29 +++--- spec/suites/ReporterTest.js | 2 +- spec/suites/RunnerTest.js | 6 +- spec/suites/SpecRunningTest.js | 153 +++++++++++++++++++++---------- src/ActionCollection.js | 2 +- src/Block.js | 4 +- src/Env.js | 4 +- src/NestedResults.js | 4 +- src/Queue.js | 40 ++++++-- src/Runner.js | 3 +- src/Spec.js | 42 +++++---- src/Suite.js | 53 +++++++---- src/WaitsBlock.js | 2 +- src/WaitsForBlock.js | 6 +- 16 files changed, 340 insertions(+), 174 deletions(-) diff --git a/lib/TrivialReporter.js b/lib/TrivialReporter.js index 39b0c5e..5d10f5d 100644 --- a/lib/TrivialReporter.js +++ b/lib/TrivialReporter.js @@ -35,7 +35,7 @@ jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { var specDiv = this.createDom('div', { - className: spec.getResults().passed ? 'spec passed' : 'spec failed' + className: spec.getResults().passed() ? 'spec passed' : 'spec failed' }, spec.getFullName()); var resultItems = spec.getResults().getItems(); diff --git a/lib/jasmine.js b/lib/jasmine.js index f3f009f..ae6ec96 100644 --- a/lib/jasmine.js +++ b/lib/jasmine.js @@ -614,7 +614,7 @@ jasmine.Env.prototype.describe = function(description, specDefinitions) { var parentSuite = this.currentSuite; if (parentSuite) { - parentSuite.specs.push(suite); + parentSuite.add(suite); } else { this.currentRunner.suites.push(suite); } @@ -645,7 +645,7 @@ jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { jasmine.Env.prototype.it = function(description, func) { var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.specs.push(spec); + this.currentSuite.add(spec); this.currentSpec = spec; if (func) { @@ -844,7 +844,7 @@ jasmine.ActionCollection.prototype.waitForDone = function(action) { self.env.clearInterval(id); afterExecute(); } - }, 150); + }, 15000); }; /** No-op base class for Jasmine reporters. * @@ -887,7 +887,7 @@ jasmine.Block = function(env, func, spec) { this.spec = spec; }; -jasmine.Block.prototype.next = function() { +jasmine.Block.prototype._next = function() { this.spec.finish(); // default value is to be done after one function }; @@ -898,7 +898,7 @@ jasmine.Block.prototype.execute = function() { } catch (e) { this.fail(e); } - this.next(); + this._next(); }; jasmine.Block.prototype.fail = function(e) { @@ -1339,9 +1339,9 @@ jasmine.NestedResults.prototype.addResult = function(result) { /** * @returns {Boolean} True if everything below passed */ -jasmine.NestedResults.prototype.__defineGetter__('passed', function() { +jasmine.NestedResults.prototype.passed = function() { return this.passedCount === this.totalCount; -}); +} /** * Base class for pretty printing for expectation results. */ @@ -1462,8 +1462,12 @@ jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { jasmine.StringPrettyPrinter.prototype.append = function(value) { this.string += value; }; -jasmine.Queue = function() { +jasmine.Queue = function(onComplete) { this.blocks = []; + this.onComplete = function () { + onComplete(); + }; + this.index = 0; }; jasmine.Queue.prototype.add = function(block) { @@ -1471,11 +1475,18 @@ jasmine.Queue.prototype.add = function(block) { this.blocks.push(block); }; -jasmine.Queue.prototype.start = function(onComplete) { +jasmine.Queue.prototype.start = function() { if (this.blocks[0]) { this.blocks[0].execute(); } else { - onComplete(); + this.onComplete(); + } +}; + +jasmine.Queue.prototype._next = function () { + this.index++; + if (this.index < this.blocks.length) { + this.blocks[this.index].execute(); } }; @@ -1483,14 +1494,31 @@ jasmine.Queue.prototype.start = function(onComplete) { * @private */ jasmine.Queue.prototype.setNextOnLastInQueue = function (block) { - if (this.blocks.length > 0) { - var previousBlock = this.blocks[this.blocks.length - 1]; - previousBlock.next = function() { + var self = this; + block._next = function () { + self.onComplete(); + }; + if (self.blocks.length > 0) { + var previousBlock = self.blocks[self.blocks.length - 1]; + previousBlock._next = function() { block.execute(); }; } }; +jasmine.Queue.prototype.isComplete = function () { + return this.index >= (this.blocks.length - 1); +}; + +jasmine.Queue.prototype.getResults = function () { + var results = []; + for (var i = 0; i < this.blocks.length; i++) { + results.push(this.blocks[i].getResults()); + } + return results; +}; + + /* 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) @@ -1551,7 +1579,8 @@ jasmine.Runner.prototype.finishCallback = function() { 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()); + //TODO: FIX + results.rollupCounts(this.suites[i].getResults()[0]); } return results; }; @@ -1564,18 +1593,22 @@ jasmine.Runner.prototype.getResults = function() { * @param {String} description */ jasmine.Spec = function(env, suite, description) { - this.id = env.nextSpecId_++; - this.env = env; - this.suite = suite; - this.description = description; - this.queue = new jasmine.Queue(); - this.finished = false; - this.afterCallbacks = []; - this.spies_ = []; + var spec = this; + spec.id = env.nextSpecId_++; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(function () { + spec.finish(); + }); - this.results = new jasmine.NestedResults(); - this.results.description = description; - this.matchersClass = null; + spec.finished = false; + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results = new jasmine.NestedResults(); + spec.results.description = description; + spec.matchersClass = null; }; jasmine.Spec.prototype.getFullName = function() { @@ -1601,7 +1634,7 @@ jasmine.Spec.prototype.expects_that = function(actual) { }; /** -* @private + * @private */ jasmine.Spec.prototype.expect = function(actual) { return new (this.getMatchersClass_())(this.env, actual, this.results); @@ -1644,17 +1677,23 @@ jasmine.Spec.prototype.finishCallback = function() { }; jasmine.Spec.prototype.finish = function() { + for (var i = 0; i < this.afterCallbacks.length; i++) { + this.afterCallbacks[i](); + } this.safeExecuteAfters(); - this.removeAllSpies(); this.finishCallback(); this.finished = true; + if (this.suite.next) { + this.suite.next(); + } }; jasmine.Spec.prototype.after = function(doAfter) { this.afterCallbacks.unshift(doAfter); }; + jasmine.Spec.prototype.execute = function() { var spec = this; if (!spec.env.specFilter(spec)) { @@ -1669,7 +1708,7 @@ jasmine.Spec.prototype.execute = function() { spec.safeExecuteBefores(); - spec.queue.start(function () { spec.finish(); }); + spec.queue.start(); spec.env.currentlyRunningTests = false; }; @@ -1678,7 +1717,7 @@ jasmine.Spec.prototype.safeExecuteBefores = function() { for (var suite = this.suite; suite; suite = suite.parentSuite) { if (suite.beforeQueue) { for (var i = 0; i < suite.beforeQueue.length; i++) - befores.push(suite.beforeQueue[i]); + befores.push(suite.beforeQueue[i]); } } @@ -1692,7 +1731,7 @@ jasmine.Spec.prototype.safeExecuteAfters = function() { for (var suite = this.suite; suite; suite = suite.parentSuite) { if (suite.afterQueue) { for (var i = 0; i < suite.afterQueue.length; i++) - afters.unshift(suite.afterQueue[i]); + afters.unshift(suite.afterQueue[i]); } } while (afters.length) { @@ -1755,17 +1794,16 @@ jasmine.Spec.prototype.removeAllSpies = function() { * @param {jasmine.Suite} parentSuite */ jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - jasmine.ActionCollection.call(this, env); - - this.id = env.nextSuiteId_++; - this.description = description; - this.specs = this.actions; - this.parentSuite = parentSuite; - - this.beforeQueue = []; - this.afterQueue = []; + var self = this; + self.id = env.nextSuiteId_++; + self.description = description; + self.queue = new jasmine.Queue(function () { self.finish(); }); + self.parentSuite = parentSuite; + self.env = env; + self.beforeQueue = []; + self.afterQueue = []; }; -jasmine.util.inherit(jasmine.Suite, jasmine.ActionCollection); + jasmine.Suite.prototype.getFullName = function() { var fullName = this.description; @@ -1775,8 +1813,12 @@ jasmine.Suite.prototype.getFullName = function() { return fullName; }; -jasmine.Suite.prototype.finishCallback = function() { +jasmine.Suite.prototype.finish = function() { this.env.reporter.reportSuiteResults(this); + this.finished = true; + for (var suite = this; suite; suite = suite.parentSuite) { + suite.finished = true; + } }; jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { @@ -1790,16 +1832,30 @@ jasmine.Suite.prototype.afterEach = function(afterEachFunction) { }; jasmine.Suite.prototype.getResults = function() { - var results = new jasmine.NestedResults(); - results.description = this.description; - results.id = this.id; - - for (var i = 0; i < this.specs.length; i++) { - results.rollupCounts(this.specs[i].getResults()); - } - return results; + return this.queue.getResults(); }; +jasmine.Suite.prototype.add = function(block) { + this.queue.add(block); +}; + +jasmine.Suite.prototype.execute = function() { + this.queue.start(); +}; + +jasmine.Suite.prototype.finished = function () { + //for (var suite = this; suite; suite = suite.parentSuite) { + // suite.finished = true; + //} +}; + +jasmine.Suite.prototype.next = function() { + if (this.queue.isComplete()) { + this.finish(); + } else { + this.queue._next(); + } +}; jasmine.WaitsBlock = function(env, timeout, spec) { this.timeout = timeout; jasmine.Block.call(this, env, null, spec); @@ -1811,7 +1867,7 @@ jasmine.WaitsBlock.prototype.execute = function () { var self = this; self.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); self.env.setTimeout(function () { - self.next(); + self._next(); }, self.timeout); }; jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { @@ -1834,19 +1890,19 @@ jasmine.WaitsForBlock.prototype.execute = function () { latchFunctionResult = self.latchFunction.apply(self.spec); } catch (e) { self.fail(e); - self.next(); + self._next(); return; } if (latchFunctionResult) { - self.next(); + self._next(); } else if (self.totalTimeSpentWaitingForLatch >= self.timeout) { var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.message || 'something to happen'); self.fail({ name: 'timeout', message: message }); - self.spec.next(); + self.spec._next(); } else { self.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; self.env.setTimeout(function () { self.execute(); }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); diff --git a/spec/suites/ExceptionsTest.js b/spec/suites/ExceptionsTest.js index 8fc4e9c..db772db 100644 --- a/spec/suites/ExceptionsTest.js +++ b/spec/suites/ExceptionsTest.js @@ -74,25 +74,24 @@ describe('Exceptions:', function() { var runner = env.currentRunner; suite.execute(); - fakeTimer.tick(300); //TODO: setting this to a large number causes failures, but shouldn't + fakeTimer.tick(2500); - var resultsForSpec0 = suite.specs[0].getResults(); - var resultsForSpec1 = suite.specs[1].getResults(); - var resultsForSpec2 = suite.specs[2].getResults(); - var resultsForSpec3 = suite.specs[3].getResults(); - - expect(suite.getResults().totalCount).toEqual(6); - expect(resultsForSpec0.getItems()[0].passed).toEqual(false); - expect(resultsForSpec0.getItems()[0].message).toMatch(/fake error 1/); + var suiteResults = suite.getResults(); + expect(suiteResults.length).toEqual(5); + expect(suiteResults[0].passed()).toEqual(false); + expect(suiteResults[0].items_[0].message).toMatch(/fake error 1/); - expect(resultsForSpec1.getItems()[0].passed).toEqual(false), - expect(resultsForSpec1.getItems()[0].message).toMatch(/fake error 2/), - expect(resultsForSpec1.getItems()[1].passed).toEqual(true); + expect(suiteResults[1].passed()).toEqual(false), + expect(suiteResults[1].items_[0].message).toMatch(/fake error 2/), + expect(suiteResults[1].items_[1].passed).toEqual(true); - expect(resultsForSpec2.getItems()[0].passed).toEqual(true); + expect(suiteResults[2].passed()).toEqual(true); + + expect(suiteResults[3].passed()).toEqual(false); + expect(suiteResults[3].items_[0].message).toMatch(/fake error 3/); + + expect(suiteResults[4].passed()).toEqual(true); - expect(resultsForSpec3.getItems()[0].passed).toEqual(false); - expect(resultsForSpec3.getItems()[0].message).toMatch(/fake error 3/); }); }); \ No newline at end of file diff --git a/spec/suites/ReporterTest.js b/spec/suites/ReporterTest.js index e1e4dc2..6743e84 100644 --- a/spec/suites/ReporterTest.js +++ b/spec/suites/ReporterTest.js @@ -5,7 +5,7 @@ describe('jasmine.Reporter', function() { env = new jasmine.Env(); }); - it('should ', function() { + it('should get called from the test runner', function() { env.describe('Suite for JSON Reporter with Callbacks', function () { env.it('should be a test', function() { this.runs(function () { diff --git a/spec/suites/RunnerTest.js b/spec/suites/RunnerTest.js index c0009b3..e6efbd2 100644 --- a/spec/suites/RunnerTest.js +++ b/spec/suites/RunnerTest.js @@ -41,8 +41,8 @@ describe('RunnerTest', function() { env.currentRunner.execute(); expect(env.currentRunner.suites.length).toEqual(2); // "Runner expected two suites, got " + env.currentRunner.suites.length); - expect(env.currentRunner.suites[0].specs[0].results.getItems()[0].passed).toEqual(true); //"Runner should have run specs in first suite"); - expect(env.currentRunner.suites[1].specs[0].results.getItems()[0].passed).toEqual(false); //"Runner should have run specs in second suite"); + expect(env.currentRunner.suites[0].getResults()[0].passed()).toEqual(true); //"Runner should have run specs in first suite"); + expect(env.currentRunner.suites[1].getResults()[0].passed()).toEqual(false); //"Runner should have run specs in second suite"); }); it('should ignore suites that have been x\'d', function() { @@ -65,7 +65,7 @@ describe('RunnerTest', function() { env.currentRunner.execute(); expect(env.currentRunner.suites.length).toEqual(1); // "Runner expected 1 suite, got " + env.currentRunner.suites.length); - expect(env.currentRunner.suites[0].specs[0].results.getItems()[0].passed).toEqual(false); // "Runner should have run specs in first suite"); + expect(env.currentRunner.suites[0].getResults()[0].passed()).toEqual(false); // "Runner should have run specs in first suite"); expect(env.currentRunner.suites[1]).toEqual(undefined); // "Second suite should be undefined, but was " + reporter.toJSON(env.currentRunner.suites[1])); }); diff --git a/spec/suites/SpecRunningTest.js b/spec/suites/SpecRunningTest.js index 6736d7c..3dc00c0 100644 --- a/spec/suites/SpecRunningTest.js +++ b/spec/suites/SpecRunningTest.js @@ -38,6 +38,7 @@ describe("jasmine spec running", function () { it("should build up some objects with results we can inspect", function() { + var specWithNoBody, specWithExpectation, specWithFailingExpectations, specWithMultipleExpectations; var suite = env.describe('default current suite', function() { @@ -352,7 +353,7 @@ describe("jasmine spec running", function () { }); suite.execute(); - expect(log).toEqual("specafter2after1"); // "after function should be executed in reverse order after spec runs"); + expect(log).toEqual("specafter2after1"); }); describe('test suite declaration', function() { @@ -392,7 +393,6 @@ describe("jasmine spec running", function () { }); it("testBeforeAndAfterCallbacks", function () { - var suiteWithBefore = env.describe('one suite with a before', function () { this.beforeEach(function () { @@ -417,39 +417,36 @@ describe("jasmine spec running", function () { suiteWithBefore.execute(); var suite = suiteWithBefore; expect(suite.beforeEachFunction); // "testBeforeAndAfterCallbacks: Suite's beforeEach was not defined"); - expect(suite.specs[0].results.getItems()[0].passed).toEqual(true); // "testBeforeAndAfterCallbacks: the first spec's foo should have been 2"); - expect(suite.specs[1].results.getItems()[0].passed).toEqual(true); // "testBeforeAndAfterCallbacks: the second spec's this.foo should have been 2"); + expect(suite.getResults()[0].passed()).toEqual(true); // "testBeforeAndAfterCallbacks: the first spec's foo should have been 2"); + expect(suite.getResults()[1].passed()).toEqual(true); // "testBeforeAndAfterCallbacks: the second spec's this.foo should have been 2"); + + var foo = 1; var suiteWithAfter = env.describe('one suite with an after_each', function () { env.it('should be a spec with an after_each', function () { - this.runs(function() { - this.foo = 0; - this.foo++; - this.expect(this.foo).toEqual(1); - }); + this.expect(foo).toEqual(1); + foo++; + this.expect(foo).toEqual(2); }); env.it('should be another spec with an after_each', function () { - this.runs(function() { - this.foo = 0; - this.foo++; - this.expect(this.foo).toEqual(1); - }); + this.expect(foo).toEqual(0); + foo++; + this.expect(foo).toEqual(1); }); this.afterEach(function () { - this.foo = 0; + foo = 0; }); }); suiteWithAfter.execute(); suite = suiteWithAfter; - expect(suite.afterEachFunction); // "testBeforeAndAfterCallbacks: Suite's afterEach was not defined"); - expect(suite.specs[0].results.getItems()[0].passed).toEqual(true); // "testBeforeAndAfterCallbacks: afterEach failure: " + suite.results.getItems()[0].results[0].message); - expect(suite.specs[0].foo).toEqual(0); // "testBeforeAndAfterCallbacks: afterEach failure: foo was not reset to 0"); - expect(suite.specs[1].results.getItems()[0].passed).toEqual(true); // "testBeforeAndAfterCallbacks: afterEach failure: " + suite.results.getItems()[0].results[0].message); - expect(suite.specs[1].foo).toEqual(0); // "testBeforeAndAfterCallbacks: afterEach failure: foo was not reset to 0"); + expect(suite.afterEach.length).toEqual(1); + expect(suite.getResults()[0].passed()).toEqual(true); + expect(suite.getResults()[1].passed()).toEqual(true); + expect(foo).toEqual(0); }); @@ -474,9 +471,52 @@ describe("jasmine spec running", function () { expect(foo).toEqual(1); }); + it('nested suites', function () { + var foo = 0; + var bar = 0; + var baz = 0; + var quux = 0; + var nested = env.describe('suite', function () { + env.describe('nested', function () { + env.it('should run nested suites', function () { + console.log('first') + foo++; + }); + env.it('should run nested suites', function () { + console.log('second') + bar++; + }); + }); + + env.describe('nested 2', function () { + env.it('should run suites following nested suites', function () { + console.log('third') + baz++; + }); + }); + + env.it('should run tests following nested suites', function () { + console.log('fourth') + quux++; + }); + }); + + expect(foo).toEqual(0); + expect(bar).toEqual(0); + expect(baz).toEqual(0); + expect(quux).toEqual(0); + nested.execute(); + expect(foo).toEqual(1); + expect(bar).toEqual(1); + expect(baz).toEqual(1); + expect(quux).toEqual(1); + }); + describe('#waitsFor should allow consecutive calls', function () { + var foo; beforeEach(function () { + foo = 0; }); @@ -485,8 +525,13 @@ describe("jasmine spec running", function () { var reachedSecondWaitsFor = false; var waitsSuite = env.describe('suite that waits', function () { env.it('should stack timeouts', function() { - this.waitsFor(500, function () { reachedFirstWaitsFor = true; return false; }); - this.waitsFor(500, function () { reachedSecondWaitsFor = true;}); + this.waitsFor(500, function () { + reachedFirstWaitsFor = true; + return false; + }); + this.waitsFor(500, function () { + reachedSecondWaitsFor = true; + }); this.runs(function () { foo++; }); @@ -511,8 +556,18 @@ describe("jasmine spec running", function () { var secondWaitsResult = false; var waitsSuite = env.describe('suite that waits', function () { env.it('spec with waitsFors', function() { - this.waitsFor(600, function () { fakeTimer.setTimeout(function () {firstWaitsResult = true; }, 300); return firstWaitsResult; }); - this.waitsFor(600, function () { fakeTimer.setTimeout(function () {secondWaitsResult = true; }, 300); return secondWaitsResult; }); + this.waitsFor(600, function () { + fakeTimer.setTimeout(function () { + firstWaitsResult = true; + }, 300); + return firstWaitsResult; + }); + this.waitsFor(600, function () { + fakeTimer.setTimeout(function () { + secondWaitsResult = true; + }, 300); + return secondWaitsResult; + }); this.runs(function () { foo++; }); @@ -547,7 +602,9 @@ describe("jasmine spec running", function () { var bar = 0; var suiteWithBefore = env.describe('one suite with a before', function () { this.beforeEach(function () { + console.error('in beforeEach') this.runs(function () { + console.error('in beforeEach runs') foo++; }); this.waits(500); @@ -558,6 +615,7 @@ describe("jasmine spec running", function () { }); env.it('should be a spec', function () { + console.error('in spec ') bar = 1; foo++; }); @@ -567,11 +625,12 @@ describe("jasmine spec running", function () { expect(foo).toEqual(0); expect(bar).toEqual(0); suiteWithBefore.execute(); - + console.error('before tick'); expect(bar).toEqual(0); expect(foo).toEqual(1); fakeTimer.tick(500); + console.error('after tick') expect(bar).toEqual(0); expect(foo).toEqual(2); @@ -606,12 +665,10 @@ describe("jasmine spec running", function () { suite.execute(); - expect(report).toEqual("firstsecond"); // "both tests should run"); - expect(suite.specs[0].results.getItems()[0].passed).toEqual(false); // "1st spec should fail"); - expect(suite.specs[1].results.getItems()[0].passed).toEqual(true); // "2nd spec should pass"); - - expect(suite.specs[0].results.getItems()[0].passed).toEqual(false); // "1st spec should fail"); - expect(suite.specs[1].results.getItems()[0].passed).toEqual(true); // "2nd spec should pass"); + expect(report).toEqual("firstsecond"); + var suiteResults = suite.getResults(); + expect(suiteResults[0].getItems()[0].passed).toEqual(false); + expect(suiteResults[1].getItems()[0].passed).toEqual(true); }); it("testAfterExecutesSafely", function() { @@ -648,15 +705,17 @@ describe("jasmine spec running", function () { expect(report).toEqual("firstsecondthird"); // "all tests should run"); //After each errors should not go in spec results because it confuses the count. - expect(suite.specs.length).toEqual(3, 'testAfterExecutesSafely should have results for three specs'); - expect(suite.specs[0].results.getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 1st spec should pass"); - expect(suite.specs[1].results.getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 2nd spec should pass"); - expect(suite.specs[2].results.getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 3rd spec should pass"); + var suiteResults = suite.getResults(); + expect(suiteResults.length).toEqual(3, 'testAfterExecutesSafely should have results for three specs'); - expect(suite.specs[0].results.getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 1st result for 1st suite spec should pass"); - expect(suite.specs[0].results.getItems()[1].passed).toEqual(false, "testAfterExecutesSafely 2nd result for 1st suite spec should fail because afterEach failed"); - expect(suite.specs[1].results.getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 2nd suite spec should pass"); - expect(suite.specs[2].results.getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 3rd suite spec should pass"); + expect(suiteResults[0].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 1st spec should pass"); + expect(suiteResults[1].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 2nd spec should pass"); + expect(suiteResults[2].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 3rd spec should pass"); + + expect(suiteResults[0].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 1st result for 1st suite spec should pass"); + expect(suiteResults[0].getItems()[1].passed).toEqual(false, "testAfterExecutesSafely 2nd result for 1st suite spec should fail because afterEach failed"); + expect(suiteResults[1].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 2nd suite spec should pass"); + expect(suiteResults[2].getItems()[0].passed).toEqual(true, "testAfterExecutesSafely 3rd suite spec should pass"); }); it("testNestedDescribes", function() { @@ -731,8 +790,6 @@ describe("jasmine spec running", function () { "inner 2 afterEach", "outer afterEach" ]; - console.log(actions); - console.log(expected); expect(env.equals_(actions, expected)).toEqual(true); }); @@ -751,9 +808,10 @@ describe("jasmine spec running", function () { }); it("should bind 'this' to the running spec within the spec body", function() { + var spec; var suite = env.describe('one suite description', function () { env.it('should be a test with queuedFunctions', function() { - this.runs(function() { + spec = this.runs(function() { this.foo = 0; this.foo++; }); @@ -780,11 +838,11 @@ describe("jasmine spec running", function () { suite.execute(); fakeTimer.tick(600); - - expect(suite.specs[0].foo).toEqual(2); // "Spec does not maintain scope in between functions"); - expect(suite.specs[0].results.getItems().length).toEqual(2); // "Spec did not get results for all expectations"); - expect(suite.specs[0].results.getItems()[0].passed).toEqual(false); // "Spec did not return false for a failed expectation"); - expect(suite.specs[0].results.getItems()[1].passed).toEqual(true); // "Spec did not return true for a passing expectation"); + expect(spec.foo).toEqual(2); + var suiteResults = suite.getResults(); + expect(suiteResults[0].getItems().length).toEqual(2); + expect(suiteResults[0].getItems()[0].passed).toEqual(false); + expect(suiteResults[0].getItems()[1].passed).toEqual(true); }); it("shouldn't run disabled tests", function() { @@ -801,7 +859,6 @@ describe("jasmine spec running", function () { }); suite.execute(); - expect(suite.specs.length).toEqual(1); expect(xitSpecWasRun).toEqual(false); }); diff --git a/src/ActionCollection.js b/src/ActionCollection.js index 214b299..098afac 100644 --- a/src/ActionCollection.js +++ b/src/ActionCollection.js @@ -88,5 +88,5 @@ jasmine.ActionCollection.prototype.waitForDone = function(action) { self.env.clearInterval(id); afterExecute(); } - }, 150); + }, 15000); }; diff --git a/src/Block.js b/src/Block.js index dabd4ca..5948740 100644 --- a/src/Block.js +++ b/src/Block.js @@ -12,7 +12,7 @@ jasmine.Block = function(env, func, spec) { this.spec = spec; }; -jasmine.Block.prototype.next = function() { +jasmine.Block.prototype._next = function() { this.spec.finish(); // default value is to be done after one function }; @@ -23,7 +23,7 @@ jasmine.Block.prototype.execute = function() { } catch (e) { this.fail(e); } - this.next(); + this._next(); }; jasmine.Block.prototype.fail = function(e) { diff --git a/src/Env.js b/src/Env.js index 12525ae..8f7713f 100644 --- a/src/Env.js +++ b/src/Env.js @@ -45,7 +45,7 @@ jasmine.Env.prototype.describe = function(description, specDefinitions) { var parentSuite = this.currentSuite; if (parentSuite) { - parentSuite.specs.push(suite); + parentSuite.add(suite); } else { this.currentRunner.suites.push(suite); } @@ -76,7 +76,7 @@ jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { jasmine.Env.prototype.it = function(description, func) { var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.specs.push(spec); + this.currentSuite.add(spec); this.currentSpec = spec; if (func) { diff --git a/src/NestedResults.js b/src/NestedResults.js index 4e4842f..fab5e9b 100644 --- a/src/NestedResults.js +++ b/src/NestedResults.js @@ -75,6 +75,6 @@ jasmine.NestedResults.prototype.addResult = function(result) { /** * @returns {Boolean} True if everything below passed */ -jasmine.NestedResults.prototype.__defineGetter__('passed', function() { +jasmine.NestedResults.prototype.passed = function() { return this.passedCount === this.totalCount; -}); +} diff --git a/src/Queue.js b/src/Queue.js index 26165f6..3bdaafc 100644 --- a/src/Queue.js +++ b/src/Queue.js @@ -1,5 +1,9 @@ -jasmine.Queue = function() { +jasmine.Queue = function(onComplete) { this.blocks = []; + this.onComplete = function () { + onComplete(); + }; + this.index = 0; }; jasmine.Queue.prototype.add = function(block) { @@ -7,11 +11,18 @@ jasmine.Queue.prototype.add = function(block) { this.blocks.push(block); }; -jasmine.Queue.prototype.start = function(onComplete) { +jasmine.Queue.prototype.start = function() { if (this.blocks[0]) { this.blocks[0].execute(); } else { - onComplete(); + this.onComplete(); + } +}; + +jasmine.Queue.prototype._next = function () { + this.index++; + if (this.index < this.blocks.length) { + this.blocks[this.index].execute(); } }; @@ -19,11 +30,28 @@ jasmine.Queue.prototype.start = function(onComplete) { * @private */ jasmine.Queue.prototype.setNextOnLastInQueue = function (block) { - if (this.blocks.length > 0) { - var previousBlock = this.blocks[this.blocks.length - 1]; - previousBlock.next = function() { + var self = this; + block._next = function () { + self.onComplete(); + }; + if (self.blocks.length > 0) { + var previousBlock = self.blocks[self.blocks.length - 1]; + previousBlock._next = function() { block.execute(); }; } }; +jasmine.Queue.prototype.isComplete = function () { + return this.index >= (this.blocks.length - 1); +}; + +jasmine.Queue.prototype.getResults = function () { + var results = []; + for (var i = 0; i < this.blocks.length; i++) { + results.push(this.blocks[i].getResults()); + } + return results; +}; + + diff --git a/src/Runner.js b/src/Runner.js index 725cbe1..af52de3 100644 --- a/src/Runner.js +++ b/src/Runner.js @@ -25,7 +25,8 @@ jasmine.Runner.prototype.finishCallback = function() { 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()); + //TODO: FIX + results.rollupCounts(this.suites[i].getResults()[0]); } return results; }; diff --git a/src/Spec.js b/src/Spec.js index 026c345..3faec7e 100644 --- a/src/Spec.js +++ b/src/Spec.js @@ -7,18 +7,22 @@ * @param {String} description */ jasmine.Spec = function(env, suite, description) { - this.id = env.nextSpecId_++; - this.env = env; - this.suite = suite; - this.description = description; - this.queue = new jasmine.Queue(); - this.finished = false; - this.afterCallbacks = []; - this.spies_ = []; + var spec = this; + spec.id = env.nextSpecId_++; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(function () { + spec.finish(); + }); - this.results = new jasmine.NestedResults(); - this.results.description = description; - this.matchersClass = null; + spec.finished = false; + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results = new jasmine.NestedResults(); + spec.results.description = description; + spec.matchersClass = null; }; jasmine.Spec.prototype.getFullName = function() { @@ -44,7 +48,7 @@ jasmine.Spec.prototype.expects_that = function(actual) { }; /** -* @private + * @private */ jasmine.Spec.prototype.expect = function(actual) { return new (this.getMatchersClass_())(this.env, actual, this.results); @@ -87,17 +91,23 @@ jasmine.Spec.prototype.finishCallback = function() { }; jasmine.Spec.prototype.finish = function() { + for (var i = 0; i < this.afterCallbacks.length; i++) { + this.afterCallbacks[i](); + } this.safeExecuteAfters(); - this.removeAllSpies(); this.finishCallback(); this.finished = true; + if (this.suite.next) { + this.suite.next(); + } }; jasmine.Spec.prototype.after = function(doAfter) { this.afterCallbacks.unshift(doAfter); }; + jasmine.Spec.prototype.execute = function() { var spec = this; if (!spec.env.specFilter(spec)) { @@ -112,7 +122,7 @@ jasmine.Spec.prototype.execute = function() { spec.safeExecuteBefores(); - spec.queue.start(function () { spec.finish(); }); + spec.queue.start(); spec.env.currentlyRunningTests = false; }; @@ -121,7 +131,7 @@ jasmine.Spec.prototype.safeExecuteBefores = function() { for (var suite = this.suite; suite; suite = suite.parentSuite) { if (suite.beforeQueue) { for (var i = 0; i < suite.beforeQueue.length; i++) - befores.push(suite.beforeQueue[i]); + befores.push(suite.beforeQueue[i]); } } @@ -135,7 +145,7 @@ jasmine.Spec.prototype.safeExecuteAfters = function() { for (var suite = this.suite; suite; suite = suite.parentSuite) { if (suite.afterQueue) { for (var i = 0; i < suite.afterQueue.length; i++) - afters.unshift(suite.afterQueue[i]); + afters.unshift(suite.afterQueue[i]); } } while (afters.length) { diff --git a/src/Suite.js b/src/Suite.js index 5b56626..f1f4cf1 100644 --- a/src/Suite.js +++ b/src/Suite.js @@ -8,17 +8,16 @@ * @param {jasmine.Suite} parentSuite */ jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - jasmine.ActionCollection.call(this, env); - - this.id = env.nextSuiteId_++; - this.description = description; - this.specs = this.actions; - this.parentSuite = parentSuite; - - this.beforeQueue = []; - this.afterQueue = []; + var self = this; + self.id = env.nextSuiteId_++; + self.description = description; + self.queue = new jasmine.Queue(function () { self.finish(); }); + self.parentSuite = parentSuite; + self.env = env; + self.beforeQueue = []; + self.afterQueue = []; }; -jasmine.util.inherit(jasmine.Suite, jasmine.ActionCollection); + jasmine.Suite.prototype.getFullName = function() { var fullName = this.description; @@ -28,8 +27,12 @@ jasmine.Suite.prototype.getFullName = function() { return fullName; }; -jasmine.Suite.prototype.finishCallback = function() { +jasmine.Suite.prototype.finish = function() { this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (this.parentSuite) { + this.parentSuite.next(); + } }; jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { @@ -43,13 +46,25 @@ jasmine.Suite.prototype.afterEach = function(afterEachFunction) { }; jasmine.Suite.prototype.getResults = function() { - var results = new jasmine.NestedResults(); - results.description = this.description; - results.id = this.id; - - for (var i = 0; i < this.specs.length; i++) { - results.rollupCounts(this.specs[i].getResults()); - } - return results; + return this.queue.getResults(); }; +jasmine.Suite.prototype.add = function(block) { + this.queue.add(block); +}; + +jasmine.Suite.prototype.execute = function() { + this.queue.start(); +}; + +jasmine.Suite.prototype._next = function () { + this.next(); +}; + +jasmine.Suite.prototype.next = function() { + if (this.queue.isComplete()) { + this.finish(); + } else { + this.queue._next(); + } +}; diff --git a/src/WaitsBlock.js b/src/WaitsBlock.js index 58c0be9..5e90304 100644 --- a/src/WaitsBlock.js +++ b/src/WaitsBlock.js @@ -9,6 +9,6 @@ jasmine.WaitsBlock.prototype.execute = function () { var self = this; self.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); self.env.setTimeout(function () { - self.next(); + self._next(); }, self.timeout); }; diff --git a/src/WaitsForBlock.js b/src/WaitsForBlock.js index dd9a00d..afd14da 100644 --- a/src/WaitsForBlock.js +++ b/src/WaitsForBlock.js @@ -18,19 +18,19 @@ jasmine.WaitsForBlock.prototype.execute = function () { latchFunctionResult = self.latchFunction.apply(self.spec); } catch (e) { self.fail(e); - self.next(); + self._next(); return; } if (latchFunctionResult) { - self.next(); + self._next(); } else if (self.totalTimeSpentWaitingForLatch >= self.timeout) { var message = 'timed out after ' + self.timeout + ' msec waiting for ' + (self.message || 'something to happen'); self.fail({ name: 'timeout', message: message }); - self.spec.next(); + self.spec._next(); } else { self.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; self.env.setTimeout(function () { self.execute(); }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);