diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index 74952879..724b6b97 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -93,6 +93,10 @@ jasmineRequire.HtmlReporter = function(j$) { currentParent.addChild(result, 'spec'); }; + this.afterAllException = function(error) { + console.error(error); + }; + var failures = []; this.specDone = function(result) { if (result.status != 'disabled') { diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 27ccdcf9..ca98bd43 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -408,7 +408,8 @@ getJasmineRequireObj().Env = function(j$) { 'suiteStarted', 'suiteDone', 'specStarted', - 'specDone' + 'specDone', + 'afterAllException' ]); this.specFilter = function() { @@ -539,6 +540,7 @@ getJasmineRequireObj().Env = function(j$) { var queueRunnerFactory = function(options) { options.catchException = catchException; + options.reporter = reporter; options.clearStack = options.clearStack || clearStack; options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; @@ -721,7 +723,7 @@ getJasmineRequireObj().Env = function(j$) { }; this.afterAll = function(afterAllFunction) { - currentDeclarationSuite.afterAll({ fn: afterAllFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }); + currentDeclarationSuite.afterAll({ fn: afterAllFunction, isAfterAll: true, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }); }; this.pending = function() { @@ -1581,6 +1583,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { this.catchException = attrs.catchException || function() { return true; }; this.userContext = attrs.userContext || {}; this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; + this.reporter = attrs.reporter; } QueueRunner.prototype.execute = function() { @@ -1588,7 +1591,8 @@ getJasmineRequireObj().QueueRunner = function(j$) { }; QueueRunner.prototype.run = function(queueableFns, recursiveIndex) { - var length = queueableFns.length, + var runner = this, + length = queueableFns.length, self = this, iterativeIndex; @@ -1611,6 +1615,9 @@ getJasmineRequireObj().QueueRunner = function(j$) { try { queueableFn.fn.call(self.userContext); } catch (e) { + if(queueableFn.isAfterAll){ + runner.reporter.afterAllException(e); + } handleException(e); } } @@ -1635,6 +1642,9 @@ getJasmineRequireObj().QueueRunner = function(j$) { try { queueableFn.fn.call(self.userContext, next); } catch (e) { + if(queueableFn.isAfterAll) { + runner.reporter.afterAllException(e); + } handleException(e); next(); } diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index 6f8e0dbb..7010c043 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -307,7 +307,7 @@ describe("Env integration", function() { expect(reporter.specDone.calls.argsFor(1)[0].failedExpectations[0].message) .toEqual("Expected 1 to be 2."); done(); - }); + }); env.addReporter(reporter); @@ -328,6 +328,58 @@ describe("Env integration", function() { env.execute(); }); + it("reports when afterAll throws an exception", function(done) { + var env = new j$.Env(), + error = new Error('After All Exception'), + reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllException']); + + + reporter.jasmineDone.and.callFake(function() { + expect(reporter.afterAllException).toHaveBeenCalledWith(error); + done(); + }); + + env.addReporter(reporter); + + env.describe('my suite', function() { + env.it('my spec', function() { + }); + + env.afterAll(function() { + throw error; + }); + }); + + env.execute(); + }); + + it("reports when an async afterAll throws an exception", function(done) { + var env = new j$.Env(), + error = new Error('After All Exception'), + reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','afterAllException']); + + + reporter.jasmineDone.and.callFake(function() { + expect(reporter.afterAllException).toHaveBeenCalledWith(error); + done(); + }); + + env.addReporter(reporter); + + env.describe('my suite', function() { + env.it('my spec', function() { + }); + + env.afterAll(function(done) { + throw error; + }); + }); + + env.execute(); + }); + + + it("Allows specifying which specs and suites to run", function(done) { var env = new j$.Env(), calls = [], diff --git a/spec/html/HtmlReporterSpec.js b/spec/html/HtmlReporterSpec.js index 0919f3ed..25b4ae71 100644 --- a/spec/html/HtmlReporterSpec.js +++ b/spec/html/HtmlReporterSpec.js @@ -130,6 +130,27 @@ describe("New HtmlReporter", function() { }); }); + describe("when afterAllException is called", function () { + it("sends a console error", function(){ + var env = new j$.Env(), + error = new Error('After all exception!'), + container = document.createElement('div'), + getContainer = function () { return container; }, + reporter = new j$.HtmlReporter({ + env: env, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); }, + getContainer: getContainer + }); + + reporter.initialize(); + + spyOn(window.console, 'error'); + reporter.afterAllException(error); + expect(window.console.error).toHaveBeenCalled(); + }); + }); + describe("when Jasmine is done", function() { it("reports the run time", function() { var env = new j$.Env(), diff --git a/src/core/Env.js b/src/core/Env.js index fc2b6e80..59ed8767 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -34,7 +34,8 @@ getJasmineRequireObj().Env = function(j$) { 'suiteStarted', 'suiteDone', 'specStarted', - 'specDone' + 'specDone', + 'afterAllException' ]); this.specFilter = function() { @@ -165,6 +166,7 @@ getJasmineRequireObj().Env = function(j$) { var queueRunnerFactory = function(options) { options.catchException = catchException; + options.reporter = reporter; options.clearStack = options.clearStack || clearStack; options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; @@ -347,7 +349,7 @@ getJasmineRequireObj().Env = function(j$) { }; this.afterAll = function(afterAllFunction) { - currentDeclarationSuite.afterAll({ fn: afterAllFunction, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }); + currentDeclarationSuite.afterAll({ fn: afterAllFunction, isAfterAll: true, timeout: function() { return j$.DEFAULT_TIMEOUT_INTERVAL; } }); }; this.pending = function() { diff --git a/src/core/QueueRunner.js b/src/core/QueueRunner.js index 1ec3c16e..726591f4 100644 --- a/src/core/QueueRunner.js +++ b/src/core/QueueRunner.js @@ -18,6 +18,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { this.catchException = attrs.catchException || function() { return true; }; this.userContext = attrs.userContext || {}; this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; + this.reporter = attrs.reporter; } QueueRunner.prototype.execute = function() { @@ -25,7 +26,8 @@ getJasmineRequireObj().QueueRunner = function(j$) { }; QueueRunner.prototype.run = function(queueableFns, recursiveIndex) { - var length = queueableFns.length, + var runner = this, + length = queueableFns.length, self = this, iterativeIndex; @@ -48,6 +50,9 @@ getJasmineRequireObj().QueueRunner = function(j$) { try { queueableFn.fn.call(self.userContext); } catch (e) { + if(queueableFn.isAfterAll){ + runner.reporter.afterAllException(e); + } handleException(e); } } @@ -72,6 +77,9 @@ getJasmineRequireObj().QueueRunner = function(j$) { try { queueableFn.fn.call(self.userContext, next); } catch (e) { + if(queueableFn.isAfterAll) { + runner.reporter.afterAllException(e); + } handleException(e); next(); } diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js index a81f6583..e03b8948 100644 --- a/src/html/HtmlReporter.js +++ b/src/html/HtmlReporter.js @@ -64,6 +64,10 @@ jasmineRequire.HtmlReporter = function(j$) { currentParent.addChild(result, 'spec'); }; + this.afterAllException = function(error) { + console.error(error); + }; + var failures = []; this.specDone = function(result) { if (result.status != 'disabled') {