From bb8ec0eb970c4a54f344fc351c15897141c8afa0 Mon Sep 17 00:00:00 2001 From: Dan Skinner Date: Fri, 5 Jun 2020 17:17:20 +0100 Subject: [PATCH] test(plugin-window-unhandled-rejection): convert to jest --- jest.config.js | 3 +- packages/core/event.d.ts | 4 +- .../package.json | 7 +- ...on.test.js => unhandled-rejection.test.ts} | 78 +++++++++++-------- tsconfig.json | 1 + 5 files changed, 53 insertions(+), 40 deletions(-) rename packages/plugin-window-unhandled-rejection/test/{unhandled-rejection.test.js => unhandled-rejection.test.ts} (77%) diff --git a/jest.config.js b/jest.config.js index 87e962fce3..dea8cd12d9 100644 --- a/jest.config.js +++ b/jest.config.js @@ -14,7 +14,8 @@ module.exports = { testsForPackage('plugin-react'), testsForPackage('plugin-vue'), testsForPackage('plugin-browser-context'), - testsForPackage('plugin-browser-device') + testsForPackage('plugin-browser-device'), + testsForPackage('plugin-window-unhandled-rejection') ] }, { diff --git a/packages/core/event.d.ts b/packages/core/event.d.ts index 079fc7c50f..bc58a1de78 100644 --- a/packages/core/event.d.ts +++ b/packages/core/event.d.ts @@ -15,7 +15,7 @@ interface HandledState { */ export default class EventWithInternals extends Event { constructor (errorClass: string, errorMessage: string, stacktrace: any[], handledState?: HandledState, originalError?: Error) - _metadata: { [key: string]: {} } + _metadata: { [key: string]: any } _handledState: HandledState toJSON(): { payloadVersion: '4' @@ -32,7 +32,7 @@ export default class EventWithInternals extends Event { breadcrumbs: Breadcrumb[] context: string | undefined groupingHash: string | undefined - metaData: { [key: string]: {} } + metaData: { [key: string]: any } user: User session: Session }; diff --git a/packages/plugin-window-unhandled-rejection/package.json b/packages/plugin-window-unhandled-rejection/package.json index d375c4af1e..32f0da1859 100644 --- a/packages/plugin-window-unhandled-rejection/package.json +++ b/packages/plugin-window-unhandled-rejection/package.json @@ -14,14 +14,9 @@ "files": [ "*.js" ], - "scripts": { - "test": "nyc --reporter=lcov -- jasmine '!(node_modules)/**/*.test.js'" - }, "author": "Bugsnag", "license": "MIT", "devDependencies": { - "@bugsnag/core": "^7.1.1", - "jasmine": "^3.1.0", - "nyc": "^12.0.2" + "@bugsnag/core": "^7.1.1" } } diff --git a/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.js b/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.ts similarity index 77% rename from packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.js rename to packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.ts index df0b63a774..9b5b6da1c5 100644 --- a/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.js +++ b/packages/plugin-window-unhandled-rejection/test/unhandled-rejection.test.ts @@ -1,20 +1,23 @@ -const { describe, it, expect, spyOn } = global +/* eslint-disable jest/no-commented-out-tests */ +import plugin from '../' -const plugin = require('../') +import Client from '@bugsnag/core/client' -const Client = require('@bugsnag/core/client') +describe('plugin: unhandled rejection', () => { + beforeEach(() => { + jest.spyOn(window, 'addEventListener') + jest.spyOn(window, 'removeEventListener') + }) -let listener = null -const window = { - addEventListener: (evt, handler) => { - listener = handler - }, - removeEventListener: () => { - listener = null + afterEach(() => { + jest.restoreAllMocks() + }) + + function getUnhandledRejectionHandler () { + const handler = (window.addEventListener as jest.MockedFunction).mock.calls[0][1] + return handler as (payload: any) => void } -} -describe('plugin: unhandled rejection', () => { describe('window.onunhandledrejection function', () => { it('captures unhandled promise rejections', done => { const p = plugin(window) @@ -25,16 +28,24 @@ describe('plugin: unhandled rejection', () => { expect(event.severity).toBe('error') expect(event.unhandled).toBe(true) expect(event.severityReason).toEqual({ type: 'unhandledPromiseRejection' }) + // @ts-ignore p.destroy(window) done() - } + }, + sendSession: () => {} })) + expect(window.addEventListener).toHaveBeenCalledWith('unhandledrejection', expect.any(Function)) + expect(window.addEventListener).toHaveBeenCalledTimes(1) + + const handler = getUnhandledRejectionHandler() // simulate an UnhandledRejection event - listener({ reason: new Error('BAD_PROMISE') }) + handler({ reason: new Error('BAD_PROMISE') }) }) it('handles bad user input', done => { + expect.assertions(6) + const p = plugin(window) const client = new Client({ apiKey: 'API_KEY_YEAH', plugins: [p] }) client._setDelivery(client => ({ @@ -46,12 +57,16 @@ describe('plugin: unhandled rejection', () => { expect(event.exceptions[0].message).toBe('unhandledrejection handler received a non-error. See "unhandledrejection handler" tab for more detail.') expect(event.severityReason).toEqual({ type: 'unhandledPromiseRejection' }) expect(event.metaData['unhandledrejection handler']['non-error parameter']).toEqual('null') + // @ts-ignore p.destroy(window) done() - } + }, + sendSession: () => {} })) - listener({ reason: null }) + const handler = getUnhandledRejectionHandler() + + handler({ reason: null }) }) // TODO: it's very difficult to mock a DOMException so move this testing to maze-runner @@ -108,17 +123,22 @@ describe('plugin: unhandled rejection', () => { expect(event.exceptions[0].errorClass).toBe('Error') expect(event.exceptions[0].message).toBe('blah') expect(event.severityReason).toEqual({ type: 'unhandledPromiseRejection' }) + // @ts-ignore p.destroy(window) done() - } + }, + sendSession: () => {} })) + const handler = getUnhandledRejectionHandler() + const err = new Error('blah') + // @ts-expect-error err.stack = true - listener({ reason: err }) + handler({ reason: err }) }) - it('tolerates event.detail propties which throw', done => { + it('tolerates event.detail properties which throw', done => { const p = plugin(window) const client = new Client({ apiKey: 'API_KEY_YEAH', plugins: [p] }) client._setDelivery(client => ({ @@ -129,40 +149,36 @@ describe('plugin: unhandled rejection', () => { expect(event.exceptions[0].errorClass).toBe('Error') expect(event.exceptions[0].message).toBe('blah') expect(event.severityReason).toEqual({ type: 'unhandledPromiseRejection' }) + // @ts-ignore p.destroy(window) done() - } + }, + sendSession: () => {} })) + const handler = getUnhandledRejectionHandler() + const err = new Error('blah') const detail = {} Object.defineProperty(detail, 'reason', { get: () => { throw new Error('bad accessor') } }) - listener({ reason: err, detail }) + handler({ reason: err, detail }) }) it('is disabled when autoDetectErrors=false', () => { - const window = { - addEventListener: () => {} - } - const addEventListenerSpy = spyOn(window, 'addEventListener') const client = new Client({ apiKey: 'API_KEY_YEAH', autoDetectErrors: false, plugins: [plugin(window)] }) - expect(addEventListenerSpy).toHaveBeenCalledTimes(0) + expect(window.addEventListener).toHaveBeenCalledTimes(0) expect(client).toBe(client) }) it('is disabled when enabledErrorTypes.unhandledRejections=false', () => { - const window = { - addEventListener: () => {} - } - const addEventListenerSpy = spyOn(window, 'addEventListener') const client = new Client({ apiKey: 'API_KEY_YEAH', enabledErrorTypes: { unhandledExceptions: false, unhandledRejections: false }, plugins: [plugin(window)] }) - expect(addEventListenerSpy).toHaveBeenCalledTimes(0) + expect(window.addEventListener).toHaveBeenCalledTimes(0) expect(client).toBe(client) }) }) diff --git a/tsconfig.json b/tsconfig.json index 55bdce4227..d146fad31f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -71,5 +71,6 @@ "packages/plugin-express", "packages/plugin-koa", "packages/plugin-restify", + "packages/plugin-window-unhandled-rejection", ] }