From 9e652eb9f24ab27c2c1ee3963ebe6863a8e315a5 Mon Sep 17 00:00:00 2001 From: JP Bochi Date: Fri, 27 Sep 2013 02:50:42 -0300 Subject: [PATCH] introduced mocha.throwError for better async error handling --- mocha.js | 20 +++++++++++++++++++- support/tail.js | 20 +++++++++++++++++++- test/browser/large.js | 17 +++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/mocha.js b/mocha.js index d11f34191d..58b4d0948b 100644 --- a/mocha.js +++ b/mocha.js @@ -5510,13 +5510,18 @@ var process = {}; process.exit = function(status){}; process.stdout = {}; +var uncaughtExceptionHandlers = []; + /** * Remove uncaughtException listener. */ -process.removeListener = function(e){ +process.removeListener = function(e, fn){ if ('uncaughtException' == e) { global.onerror = function() {}; + + var indexOfFn = uncaughtExceptionHandlers.indexOf(fn); + if (indexOfFn != -1) { uncaughtExceptionHandlers.splice(indexOfFn, 1); } } }; @@ -5529,6 +5534,7 @@ process.on = function(e, fn){ global.onerror = function(err, url, line){ fn(new Error(err + ' (' + url + ':' + line + ')')); }; + uncaughtExceptionHandlers.push(fn); } }; @@ -5565,6 +5571,18 @@ Mocha.Runner.immediately = function(callback) { } }; +/** + * Function to allow assertion libraries to throw errors directly into mocha. + * This is useful when running tests in a browser because window.onerror will + * only receive the 'message' attribute of the Error. + */ +mocha.throwError = function(err) { + uncaughtExceptionHandlers.forEach(function (fn) { + fn(err); + }); + throw err; +}; + /** * Override ui to ensure that the ui functions are initialized. * Normally this would happen in Mocha.prototype.loadFiles. diff --git a/support/tail.js b/support/tail.js index 4dcdebe097..3f1193a127 100644 --- a/support/tail.js +++ b/support/tail.js @@ -24,13 +24,18 @@ var process = {}; process.exit = function(status){}; process.stdout = {}; +var uncaughtExceptionHandlers = []; + /** * Remove uncaughtException listener. */ -process.removeListener = function(e){ +process.removeListener = function(e, fn){ if ('uncaughtException' == e) { global.onerror = function() {}; + + var indexOfFn = uncaughtExceptionHandlers.indexOf(fn); + if (indexOfFn != -1) { uncaughtExceptionHandlers.splice(indexOfFn, 1); } } }; @@ -43,6 +48,7 @@ process.on = function(e, fn){ global.onerror = function(err, url, line){ fn(new Error(err + ' (' + url + ':' + line + ')')); }; + uncaughtExceptionHandlers.push(fn); } }; @@ -79,6 +85,18 @@ Mocha.Runner.immediately = function(callback) { } }; +/** + * Function to allow assertion libraries to throw errors directly into mocha. + * This is useful when running tests in a browser because window.onerror will + * only receive the 'message' attribute of the Error. + */ +mocha.throwError = function(err) { + uncaughtExceptionHandlers.forEach(function (fn) { + fn(err) ; + }); + throw err; +}; + /** * Override ui to ensure that the ui functions are initialized. * Normally this would happen in Mocha.prototype.loadFiles. diff --git a/test/browser/large.js b/test/browser/large.js index 7974bb6f90..1250abaef4 100644 --- a/test/browser/large.js +++ b/test/browser/large.js @@ -29,4 +29,21 @@ describe('something', function(){ done(); }, 1); }) + + it('should provide an even better error on phantomjs', function(done){ + setTimeout(function(){ + var AssertionError = function(message, actual, expected) { + this.message = message; + this.actual = actual; + this.expected = expected; + this.showDiff = true; + }; + AssertionError.prototype = Object.create(Error.prototype); + AssertionError.prototype.name = 'AssertionError'; + AssertionError.prototype.constructor = AssertionError; + + mocha.throwError(new AssertionError('kabooom', 'text with a typo', 'text without a typo')); + done(); + }, 1); + }) }) \ No newline at end of file