From ec7d58fce0ca9475d942afd1a965495e75df3abd Mon Sep 17 00:00:00 2001 From: Sheel Choksi Date: Sun, 7 Jul 2013 21:00:07 -0700 Subject: [PATCH 1/3] QueueRunner continues running functions in async case Continue running functions even if an async spec throws an exception during the synchronous portion of the spec --- lib/jasmine-core/jasmine.js | 9 +++++++-- spec/core/QueueRunnerSpec.js | 12 ++++++++++++ src/core/QueueRunner.js | 9 +++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index db0a01ae..ae5618a0 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1311,10 +1311,13 @@ 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); }); } @@ -1332,6 +1335,7 @@ getJasmineRequireObj().QueueRunner = function() { function attempt(fn) { try { fn(); + return true; } catch (e) { self.onException(e); if (!self.catchException(e)) { @@ -1339,6 +1343,7 @@ getJasmineRequireObj().QueueRunner = function() { //use a finally block to close the loop in a nice way.. throw e; } + return false; } } }; diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index da603fd9..e6edf96b 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'), diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index fe7d7592..85dfea3c 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -20,10 +20,13 @@ 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); }); } @@ -41,6 +44,7 @@ getJasmineRequireObj().QueueRunner = function() { function attempt(fn) { try { fn(); + return true; } catch (e) { self.onException(e); if (!self.catchException(e)) { @@ -48,6 +52,7 @@ getJasmineRequireObj().QueueRunner = function() { //use a finally block to close the loop in a nice way.. throw e; } + return false; } } }; From ccdcb293f4f15c60d6173866e7b169d80afd2c29 Mon Sep 17 00:00:00 2001 From: Sheel Choksi Date: Sun, 7 Jul 2013 21:01:53 -0700 Subject: [PATCH 2/3] Add back in forgotten 'env' to Env integration specs As pointed out by @jdmarshall. Fixes #399 --- spec/core/EnvSpec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/core/EnvSpec.js b/spec/core/EnvSpec.js index fbb69b45..db221c4c 100644 --- a/spec/core/EnvSpec.js +++ b/spec/core/EnvSpec.js @@ -191,7 +191,8 @@ describe("Env integration", function() { // 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", From aabf8cec8246ed4fa63d55ec8d044d702c74cc73 Mon Sep 17 00:00:00 2001 From: Sheel Choksi Date: Mon, 8 Jul 2013 23:00:42 -0700 Subject: [PATCH 3/3] Specs/Suites wait for an async spec to finish Go back to having all suites and specs run asynchronously so that they properly wait for any async specs that there might be --- lib/jasmine-core/jasmine.js | 13 +++++-------- spec/core/EnvSpec.js | 24 ++++++++++++++++++++++++ spec/core/QueueRunnerSpec.js | 2 +- src/core/QueueRunner.js | 7 ++----- src/core/Suite.js | 6 +++--- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index ae5618a0..32363b08 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1323,13 +1323,10 @@ getJasmineRequireObj().QueueRunner = function() { } } - 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) { @@ -1550,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); @@ -1568,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 db221c4c..f88d8ca6 100644 --- a/spec/core/EnvSpec.js +++ b/spec/core/EnvSpec.js @@ -189,6 +189,30 @@ 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 env = new j$.Env(), diff --git a/spec/core/QueueRunnerSpec.js b/spec/core/QueueRunnerSpec.js index e6edf96b..bdf7c202 100644 --- a/spec/core/QueueRunnerSpec.js +++ b/spec/core/QueueRunnerSpec.js @@ -127,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 85dfea3c..ac615053 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -32,13 +32,10 @@ getJasmineRequireObj().QueueRunner = function() { } } - 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) { 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); }; } };