From f1ebe05f1dadc6306cb6fd159410ed81f82d815f Mon Sep 17 00:00:00 2001 From: johnjbarton Date: Wed, 21 Feb 2018 07:23:20 -0800 Subject: [PATCH] Report unhandled rejections as globalErrors. Extend existing support for uncaughtExceptions to unhandledRejections now that many tests are async. --- spec/core/GlobalErrorsSpec.js | 32 +++++++++++++++++++++++++++++++- src/core/GlobalErrors.js | 31 +++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/spec/core/GlobalErrorsSpec.js b/spec/core/GlobalErrorsSpec.js index 56ea1a20..a8014131 100644 --- a/spec/core/GlobalErrorsSpec.js +++ b/spec/core/GlobalErrorsSpec.js @@ -78,7 +78,7 @@ describe("GlobalErrors", function() { errors.uninstall(); }); - it("works in node.js", function() { + it("reports uncaughtException in node.js", function() { var fakeGlobal = { process: { on: jasmine.createSpy('process.on'), @@ -107,4 +107,34 @@ describe("GlobalErrors", function() { expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith('uncaughtException', addedListener); expect(fakeGlobal.process.on).toHaveBeenCalledWith('uncaughtException', 'foo'); }); + + it("reports unhandledRejection in node.js", function() { + var fakeGlobal = { + process: { + on: jasmine.createSpy('process.on'), + removeListener: jasmine.createSpy('process.removeListener'), + listeners: jasmine.createSpy('process.listeners').and.returnValue(['foo']), + removeAllListeners: jasmine.createSpy('process.removeAllListeners') + } + }, + handler = jasmine.createSpy('errorHandler'), + errors = new jasmineUnderTest.GlobalErrors(fakeGlobal); + + errors.install(); + expect(fakeGlobal.process.on).toHaveBeenCalledWith('unhandledRejection', jasmine.any(Function)); + expect(fakeGlobal.process.listeners).toHaveBeenCalledWith('unhandledRejection'); + expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith('unhandledRejection'); + + errors.pushListener(handler); + + var addedListener = fakeGlobal.process.on.calls.argsFor(0)[1]; + addedListener(new Error('bar')); + + expect(handler).toHaveBeenCalledWith(new Error('bar')); + + errors.uninstall(); + + expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith('unhandledRejection', addedListener); + expect(fakeGlobal.process.on).toHaveBeenCalledWith('unhandledRejection', 'foo'); + }); }); diff --git a/src/core/GlobalErrors.js b/src/core/GlobalErrors.js index 3eaec399..06f8daa0 100644 --- a/src/core/GlobalErrors.js +++ b/src/core/GlobalErrors.js @@ -13,18 +13,29 @@ getJasmineRequireObj().GlobalErrors = function(j$) { } }; + this.originalHandlers = {}; + this.installOne_ = function installOne_(errorType) { + this.originalHandlers[errorType] = global.process.listeners(errorType); + global.process.removeAllListeners(errorType); + global.process.on(errorType, onerror); + + this.uninstall = function uninstall() { + var errorTypes = Object.keys(this.originalHandlers); + for (var iType = 0; iType < errorTypes.length; iType++) { + var errorType = errorTypes[iType]; + global.process.removeListener(errorType, onerror); + for (var i = 0; i < this.originalHandlers[errorType].length; i++) { + global.process.on(errorType, this.originalHandlers[errorType][i]); + } + delete this.originalHandlers[errorType]; + } + }; + }; + this.install = function install() { if (global.process && global.process.listeners && j$.isFunction_(global.process.on)) { - var originalHandlers = global.process.listeners('uncaughtException'); - global.process.removeAllListeners('uncaughtException'); - global.process.on('uncaughtException', onerror); - - this.uninstall = function uninstall() { - global.process.removeListener('uncaughtException', onerror); - for (var i = 0; i < originalHandlers.length; i++) { - global.process.on('uncaughtException', originalHandlers[i]); - } - }; + this.installOne_('uncaughtException'); + this.installOne_('unhandledRejection'); } else { var originalHandler = global.onerror; global.onerror = onerror;