Skip to content

Commit

Permalink
Merge pull request #880 from bugsnag/convert-plugin-window-unhandled-…
Browse files Browse the repository at this point in the history
…rejection

test(plugin-window-unhandled-rejection): convert to jest
  • Loading branch information
bengourley authored Jun 15, 2020
2 parents 5d981ae + 5fe83a3 commit a92275d
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 39 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = {
testsForPackage('plugin-vue'),
testsForPackage('plugin-browser-context'),
testsForPackage('plugin-browser-device'),
testsForPackage('plugin-window-unhandled-rejection'),
testsForPackage('plugin-window-onerror'),
testsForPackage('plugin-strip-query-string')
]
Expand Down
4 changes: 2 additions & 2 deletions packages/core/event.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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
};
Expand Down
7 changes: 1 addition & 6 deletions packages/plugin-window-unhandled-rejection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
Original file line number Diff line number Diff line change
@@ -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<typeof window.addEventListener>).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)
Expand All @@ -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 => ({
Expand All @@ -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
Expand Down Expand Up @@ -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 => ({
Expand All @@ -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)
})
})
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"packages/plugin-express",
"packages/plugin-koa",
"packages/plugin-restify",
"packages/plugin-window-unhandled-rejection",
"packages/plugin-window-onerror",
"packages/plugin-strip-query-string",
"packages/plugin-strip-project-root",
Expand Down

0 comments on commit a92275d

Please sign in to comment.