diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index db0a01ae..32363b08 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1311,27 +1311,28 @@ getJasmineRequireObj().QueueRunner = function() { for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { var fn = fns[iterativeIndex]; if (fn.length > 0) { - attempt(function() { + var attemptSuccessful = attempt(function() { fn.call(self, function() { self.run(fns, iterativeIndex + 1); }); }); - return; + + if(attemptSuccessful) { + return; + } } else { attempt(function() { fn.call(self); }); } } - var runnerDone = iterativeIndex >= length, - hasBeenAsyncSpec = recursiveIndex > 0; + var runnerDone = iterativeIndex >= length; - if (runnerDone && hasBeenAsyncSpec) { + if (runnerDone) { this.clearStack(this.onComplete); - } else if(runnerDone) { - this.onComplete(); } function attempt(fn) { try { fn(); + return true; } catch (e) { self.onException(e); if (!self.catchException(e)) { @@ -1339,6 +1340,7 @@ getJasmineRequireObj().QueueRunner = function() { //use a finally block to close the loop in a nice way.. throw e; } + return false; } } }; @@ -1545,7 +1547,7 @@ getJasmineRequireObj().Suite = function() { children = this.children_; for (var i = 0; i < children.length; i++) { - allFns.push(wrapChild(children[i])); + allFns.push(wrapChildAsAsync(children[i])); } this.onStart(this); @@ -1563,8 +1565,8 @@ getJasmineRequireObj().Suite = function() { } } - function wrapChild(child) { - return function() { child.execute(); }; + function wrapChildAsAsync(child) { + return function(done) { child.execute(done); }; } }; diff --git a/spec/core/EnvSpec.js b/spec/core/EnvSpec.js index fbb69b45..f88d8ca6 100644 --- a/spec/core/EnvSpec.js +++ b/spec/core/EnvSpec.js @@ -189,9 +189,34 @@ describe("Env integration", function() { env.execute(); }); + it("should run async specs in order, waiting for them to complete", function(done) { + var env = new j$.Env(), mutatedVar; + + env.describe("tests", function() { + env.beforeEach(function() { + mutatedVar = 2; + }); + + env.it("async spec", function(underTestCallback) { + setTimeout(function() { + expect(mutatedVar).toEqual(2); + underTestCallback(); + done(); + }, 0); + }); + + env.it("after async spec", function() { + mutatedVar = 3; + }); + }); + + env.execute(); + }); + // TODO: something is wrong with this spec it("should report as expected", function(done) { - var reporter = jasmine.createSpyObj('fakeReporter', [ + var env = new j$.Env(), + reporter = jasmine.createSpyObj('fakeReporter', [ "jasmineStarted", "jasmineDone", "suiteStarted", diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index da603fd9..bdf7c202 100644 --- a/spec/core/QueueRunnerSpec.js +++ b/spec/core/QueueRunnerSpec.js @@ -102,6 +102,18 @@ describe("QueueRunner", function() { expect(function() { queueRunner.execute(); }).toThrow(); }); + it("continues running the functions even after an exception is thrown in an async spec", function() { + var fn = function(done) { throw new Error("error"); }, + nextFn = jasmine.createSpy("nextFunction"); + + queueRunner = new j$.QueueRunner({ + fns: [fn, nextFn] + }); + + queueRunner.execute(); + expect(nextFn).toHaveBeenCalled(); + }); + it("calls a provided complete callback when done", function() { var fn = jasmine.createSpy('fn'), completeCallback = jasmine.createSpy('completeCallback'), @@ -115,7 +127,7 @@ describe("QueueRunner", function() { expect(completeCallback).toHaveBeenCalled(); }); - it("with an async spec, calls a provided stack clearing function when done", function() { + it("calls a provided stack clearing function when done", function() { var asyncFn = function(done) { done() }, afterFn = jasmine.createSpy('afterFn'), completeCallback = jasmine.createSpy('completeCallback'), diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index fe7d7592..ac615053 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -20,27 +20,28 @@ getJasmineRequireObj().QueueRunner = function() { for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { var fn = fns[iterativeIndex]; if (fn.length > 0) { - attempt(function() { + var attemptSuccessful = attempt(function() { fn.call(self, function() { self.run(fns, iterativeIndex + 1); }); }); - return; + + if(attemptSuccessful) { + return; + } } else { attempt(function() { fn.call(self); }); } } - var runnerDone = iterativeIndex >= length, - hasBeenAsyncSpec = recursiveIndex > 0; + var runnerDone = iterativeIndex >= length; - if (runnerDone && hasBeenAsyncSpec) { + if (runnerDone) { this.clearStack(this.onComplete); - } else if(runnerDone) { - this.onComplete(); } function attempt(fn) { try { fn(); + return true; } catch (e) { self.onException(e); if (!self.catchException(e)) { @@ -48,6 +49,7 @@ getJasmineRequireObj().QueueRunner = function() { //use a finally block to close the loop in a nice way.. throw e; } + return false; } } }; diff --git a/src/core/Suite.js b/src/core/Suite.js index 5d080d6c..c586551d 100644 --- a/src/core/Suite.js +++ b/src/core/Suite.js @@ -74,7 +74,7 @@ getJasmineRequireObj().Suite = function() { children = this.children_; for (var i = 0; i < children.length; i++) { - allFns.push(wrapChild(children[i])); + allFns.push(wrapChildAsAsync(children[i])); } this.onStart(this); @@ -92,8 +92,8 @@ getJasmineRequireObj().Suite = function() { } } - function wrapChild(child) { - return function() { child.execute(); }; + function wrapChildAsAsync(child) { + return function(done) { child.execute(done); }; } };