Commit 27ad7cbd authored by Vignesh Mohankumar's avatar Vignesh Mohankumar Committed by GitHub

test: move all tests to beforeSend (#6513)

* beforeSend tests

* fix

* refactor: filterKnownErrors -> shouldRejectError (#6547)

* refactor: filterKnownErrors -> shouldRejectError

* no unknown

* comments
parent 01e5de43
import { ErrorEvent, Event } from '@sentry/types'
import { beforeSend, filterKnownErrors } from './errors'
import { beforeSend } from './errors'
Object.defineProperty(window.performance, 'getEntriesByType', {
writable: true,
......@@ -61,39 +61,36 @@ describe('beforeSend', () => {
expect((beforeSend(ERROR, { originalException }) as Event).tags?.chunkResponseStatus).toBe(200)
})
})
})
describe('filterKnownErrors', () => {
const ERROR = {} as ErrorEvent
it('propagates an error', () => {
expect(filterKnownErrors(ERROR, {})).toBe(ERROR)
expect(beforeSend(ERROR, {})).toBe(ERROR)
})
it('propagates an error with generic text', () => {
const originalException = new Error('generic error copy')
expect(filterKnownErrors(ERROR, { originalException })).toBe(ERROR)
expect(beforeSend(ERROR, { originalException })).toBe(ERROR)
})
it('propagates user rejected request errors', () => {
const originalException = new Error('user rejected transaction')
expect(filterKnownErrors(ERROR, { originalException })).toBe(ERROR)
expect(beforeSend(ERROR, { originalException })).toBe(ERROR)
})
it('filters block number polling errors', () => {
const originalException = new (class extends Error {
requestBody = JSON.stringify({ method: 'eth_blockNumber' })
})()
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
it('filters network change errors', () => {
const originalException = new Error('underlying network changed')
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
it('filters invalid HTML response errors', () => {
const originalException = new SyntaxError("Unexpected token '<'")
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
it('filters chrome-extension errors', () => {
......@@ -104,7 +101,7 @@ describe('filterKnownErrors', () => {
at da(chrome-extension://kbjhmlgclljgdhmhffjofbobmficicjp/proxy-window-evm.a5430696.js:22:212968)
at a(../../../../src/helpers.ts:98:1)
`
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
describe('OneKey', () => {
......@@ -115,7 +112,7 @@ describe('filterKnownErrors', () => {
at JSON.parse(<anonymous>)
at _d._handleAccountChange(/Applications/OneKey.app/Contents/Resources/static/preload.js:2:1634067)
`
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
it('filter OneKey errors (Windows users)', () => {
const originalException = new Error()
......@@ -124,7 +121,7 @@ describe('filterKnownErrors', () => {
at JSON.parse(<anonymous>)
vd._handleAccountChange(C:\\Users\\example\\AppData\\Local\\Programs\\OneKey\\resources\\static\\preload.js:2:1626130
`
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
})
......@@ -133,26 +130,26 @@ describe('filterKnownErrors', () => {
const originalException = new Error(
"Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"script-src 'self' https://www.google-analytics.com https://www.googletagmanager.com 'unsafe-inlin..."
)
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
it('filters CSP unsafe-eval compile/instatiate errors', () => {
const originalException = new Error(
"Refused to compile or instantiate WebAssembly module because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"script-src 'self' https://www.google-a..."
)
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
it('filters WebAssembly compilation errors', () => {
const originalException = new Error(
'Aborted(CompileError: WebAssembly.instantiate(): Wasm code generation disallowed by embedder). Build with -sASSERTIONS for more info.'
)
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
})
it('filters AbortErrors', () => {
const originalException = new DOMException('The user aborted a request.', 'AbortError')
expect(filterKnownErrors(ERROR, { originalException })).toBeNull()
expect(beforeSend(ERROR, { originalException })).toBeNull()
})
})
......@@ -8,10 +8,19 @@ declare global {
}
}
export function beforeSend(event: ErrorEvent, hint: EventHint) {
/**
* Filters known (ignorable) errors out before sending them to Sentry. Also, adds tags to the event.
* Intended as a {@link ClientOptions.beforeSend} callback. Returning null filters the error from Sentry.
*/
export const beforeSend: Required<ClientOptions>['beforeSend'] = (event: ErrorEvent, hint: EventHint) => {
if (shouldRejectError(hint.originalException)) {
return null
}
updateRequestUrl(event)
addChunkResponseStatusTag(event, hint)
return filterKnownErrors(event, hint)
return event
}
/** Identifies ethers request errors (as thrown by {@type import(@ethersproject/web).fetchJson}). */
......@@ -62,52 +71,47 @@ function getChunkResponseStatus(asset?: string): number | undefined {
return resource?.responseStatus
}
/**
* Filters known (ignorable) errors out before sending them to Sentry.
* Intended as a {@link ClientOptions.beforeSend} callback. Returning null filters the error from Sentry.
*/
export const filterKnownErrors: Required<ClientOptions>['beforeSend'] = (event: ErrorEvent, hint: EventHint) => {
const error = hint.originalException
function shouldRejectError(error: EventHint['originalException']) {
if (error instanceof Error) {
// ethers aggressively polls for block number, and it sometimes fails (whether spuriously or through rate-limiting).
// If block number polling, it should not be considered an exception.
if (isEthersRequestError(error)) {
const method = JSON.parse(error.requestBody).method
if (method === 'eth_blockNumber') return null
if (method === 'eth_blockNumber') return true
}
// If the error is a network change, it should not be considered an exception.
if (error.message.match(/underlying network changed/)) return null
if (error.message.match(/underlying network changed/)) return true
// This is caused by HTML being returned for a chunk from Cloudflare.
// Usually, it's the result of a 499 exception right before it, which should be handled.
// Therefore, this can be ignored.
if (error.message.match(/Unexpected token '<'/)) return null
if (error.message.match(/Unexpected token '<'/)) return true
// Errors coming from a Chrome Extension can be ignored for now. These errors are usually caused by extensions injecting
// scripts into the page, which we cannot control.
if (error.stack?.match(/chrome-extension:\/\//i)) return null
if (error.stack?.match(/chrome-extension:\/\//i)) return true
// Errors coming from OneKey (a desktop wallet) can be ignored for now.
// These errors are either application-specific, or they will be thrown separately outside of OneKey.
if (error.stack?.match(/OneKey/i)) return null
if (error.stack?.match(/OneKey/i)) return true
// Content security policy 'unsafe-eval' errors can be filtered out because there are expected failures.
// For example, if a user runs an eval statement in console this error would still get thrown.
// TODO(INFRA-176): We should extend this to filter out any type of CSP error.
if (error.message.match(/'unsafe-eval'.*content security policy/i)) {
return null
return true
}
// WebAssembly compilation fails because we do not allow 'unsafe-eval' in our CSP.
// Any thrown errors are due to 3P extensions/applications, so we do not need to handle them.
if (error.message.match(/WebAssembly.instantiate\(\): Wasm code generation disallowed by embedder/)) {
return null
return true
}
// These are caused by user navigation away from the page before a request has finished.
if (error instanceof DOMException && error.name === 'AbortError') return null
if (error instanceof DOMException && error.name === 'AbortError') return true
}
return event
return false
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment