From 58c63e98bb32a37fe4eb3e0644b262f64ec8fa07 Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Mon, 20 Jan 2020 10:50:42 -0800 Subject: [PATCH] Include stack traces in unhandled promise rejection messages --- lib/jasmine-core/jasmine.js | 7 ++- spec/core/GlobalErrorsSpec.js | 83 +++++++++++++++++++++++++---------- src/core/GlobalErrors.js | 8 +++- 3 files changed, 74 insertions(+), 24 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index e1e7615a..6761367b 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -3855,7 +3855,12 @@ getJasmineRequireObj().GlobalErrors = function(j$) { global.onerror = onerror; var browserRejectionHandler = function browserRejectionHandler(event) { - onerror('Unhandled Rejection: ' + event.reason); + if (j$.isError_(event.reason)) { + event.reason.jasmineMessage = 'Unhandled promise rejection: ' + event.reason; + onerror(event.reason); + } else { + onerror('Unhandled promise rejection: ' + event.reason); + } }; if (global.addEventListener) { diff --git a/spec/core/GlobalErrorsSpec.js b/spec/core/GlobalErrorsSpec.js index 42f9f37c..16ca8371 100644 --- a/spec/core/GlobalErrorsSpec.js +++ b/spec/core/GlobalErrorsSpec.js @@ -194,33 +194,72 @@ describe('GlobalErrors', function() { ); }); - it('reports unhandledRejection in browser', function() { - var fakeGlobal = { - addEventListener: jasmine.createSpy('addEventListener'), - removeEventListener: jasmine.createSpy('removeEventListener'), - onerror: jasmine.createSpy('onerror') - }, - handler = jasmine.createSpy('errorHandler'), - errors = new jasmineUnderTest.GlobalErrors(fakeGlobal); + describe('Reporting unhandled promise rejections in the browser', function() { + it('subscribes and unsubscribes from the unhandledrejection event', function() { + var fakeGlobal = jasmine.createSpyObj('globalErrors', [ + 'addEventListener', + 'removeEventListener', + 'onerror' + ]), + errors = new jasmineUnderTest.GlobalErrors(fakeGlobal); - errors.install(); - expect(fakeGlobal.addEventListener).toHaveBeenCalledWith( - 'unhandledrejection', - jasmine.any(Function) - ); + errors.install(); + expect(fakeGlobal.addEventListener).toHaveBeenCalledWith( + 'unhandledrejection', + jasmine.any(Function) + ); - errors.pushListener(handler); + var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1]; + errors.uninstall(); - var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1]; - addedListener({ reason: new Error('bar') }); + expect(fakeGlobal.removeEventListener).toHaveBeenCalledWith( + 'unhandledrejection', + addedListener + ); + }); - expect(handler).toHaveBeenCalledWith('Unhandled Rejection: Error: bar'); + it('reports rejections whose reason is a string', function() { + var fakeGlobal = jasmine.createSpyObj('globalErrors', [ + 'addEventListener', + 'removeEventListener', + 'onerror' + ]), + handler = jasmine.createSpy('errorHandler'), + errors = new jasmineUnderTest.GlobalErrors(fakeGlobal); - errors.uninstall(); + errors.install(); + errors.pushListener(handler); - expect(fakeGlobal.removeEventListener).toHaveBeenCalledWith( - 'unhandledrejection', - addedListener - ); + var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1]; + addedListener({ reason: 'nope' }); + + expect(handler).toHaveBeenCalledWith('Unhandled promise rejection: nope'); + }); + + it('reports rejections whose reason is an Error', function() { + var fakeGlobal = jasmine.createSpyObj('globalErrors', [ + 'addEventListener', + 'removeEventListener', + 'onerror' + ]), + handler = jasmine.createSpy('errorHandler'), + errors = new jasmineUnderTest.GlobalErrors(fakeGlobal); + + errors.install(); + errors.pushListener(handler); + + var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1]; + var reason = new Error('bar'); + addedListener({ reason: reason }); + + var expectedError = Object.create(reason); + expectedError.jasmineMessage = expect(handler).toHaveBeenCalledWith( + jasmine.objectContaining({ + jasmineMessage: 'Unhandled promise rejection: Error: bar', + message: reason.message, + stack: reason.stack + }) + ); + }); }); }); diff --git a/src/core/GlobalErrors.js b/src/core/GlobalErrors.js index 2fe4725d..282eb262 100644 --- a/src/core/GlobalErrors.js +++ b/src/core/GlobalErrors.js @@ -64,7 +64,13 @@ getJasmineRequireObj().GlobalErrors = function(j$) { global.onerror = onerror; var browserRejectionHandler = function browserRejectionHandler(event) { - onerror('Unhandled Rejection: ' + event.reason); + if (j$.isError_(event.reason)) { + event.reason.jasmineMessage = + 'Unhandled promise rejection: ' + event.reason; + onerror(event.reason); + } else { + onerror('Unhandled promise rejection: ' + event.reason); + } }; if (global.addEventListener) {