Skip to content

Commit

Permalink
✅ [RUMF-731] add some error collection E2E tests (#1258)
Browse files Browse the repository at this point in the history
* ✅ [RUMF-731] add some error collection E2E tests

* 👌 replace `btn` by `button`
  • Loading branch information
BenoitZugmeyer authored Jan 10, 2022
1 parent 5b24a08 commit 4fa9924
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 15 deletions.
6 changes: 3 additions & 3 deletions test/e2e/scenario/eventBridge.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ describe('bridge present', () => {
html`
<button>click me</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
btn.setAttribute('data-clicked', 'true')
const button = document.querySelector('button')
button.addEventListener('click', () => {
button.setAttribute('data-clicked', 'true')
})
</script>
`
Expand Down
10 changes: 5 additions & 5 deletions test/e2e/scenario/rum/actions.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ describe('action collection', () => {
html`
<button>click me</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
btn.setAttribute('data-clicked', 'true')
const button = document.querySelector('button')
button.addEventListener('click', () => {
button.setAttribute('data-clicked', 'true')
})
</script>
`
Expand Down Expand Up @@ -47,8 +47,8 @@ describe('action collection', () => {
html`
<button>click me</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
const button = document.querySelector('button')
button.addEventListener('click', () => {
fetch('/ok')
})
</script>
Expand Down
153 changes: 146 additions & 7 deletions test/e2e/scenario/rum/errors.scenario.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,159 @@
import { createTest } from '../../lib/framework'
import { browserExecute, withBrowserLogs } from '../../lib/helpers/browser'
import { RumErrorEvent } from '@datadog/browser-rum-core'
import { createTest, html } from '../../lib/framework'
import { withBrowserLogs } from '../../lib/helpers/browser'
import { flushEvents } from '../../lib/helpers/flushEvents'

// Note: using `browserExecute` to throw exceptions may result in "Script error." being reported,
// because WDIO is evaluating the script in a different context than the page.
function createBody(errorGenerator: string) {
return html`
<button>click me</button>
<script>
const button = document.querySelector('button')
button.addEventListener('click', function handler() {
${errorGenerator}
})
function foo() {
return new Error('oh snap')
}
</script>
`
}

describe('rum errors', () => {
createTest('send console.error errors')
.withRum()
.run(async ({ serverEvents }) => {
await browserExecute(() => {
console.error('oh snap')
.withBody(createBody('console.error("oh snap")'))
.run(async ({ serverEvents, baseUrl }) => {
const button = await $('button')
await button.click()

await flushEvents()
expect(serverEvents.rumErrors.length).toBe(1)
expectError(serverEvents.rumErrors[0].error, {
message: 'console error: oh snap',
source: 'console',
handlingStack: ['Error: ', `handler @ ${baseUrl}/:`],
handling: 'handled',
})
await withBrowserLogs((browserLogs) => {
expect(browserLogs.length).toEqual(1)
})
})

createTest('pass Error instance to console.error')
.withRum()
.withBody(createBody('console.error("Foo:", foo())'))
.run(async ({ serverEvents, baseUrl }) => {
const button = await $('button')
await button.click()

await flushEvents()
expect(serverEvents.rumErrors.length).toBe(1)
expect(serverEvents.rumErrors[0].error.message).toBe('console error: oh snap')
expect(serverEvents.rumErrors[0].error.source).toBe('console')
expectError(serverEvents.rumErrors[0].error, {
message: 'console error: Foo: Error: oh snap',
source: 'console',
stack: ['Error: oh snap', `at foo @ ${baseUrl}/:`, `handler @ ${baseUrl}/:`],
handlingStack: ['Error: ', `handler @ ${baseUrl}/:`],
handling: 'handled',
})
await withBrowserLogs((browserLogs) => {
expect(browserLogs.length).toEqual(1)
})
})

createTest('send uncaught exceptions')
.withRum()
.withBody(createBody('throw foo()'))
.run(async ({ serverEvents, baseUrl }) => {
const button = await $('button')
await button.click()

await flushEvents()
expect(serverEvents.rumErrors.length).toBe(1)
expectError(serverEvents.rumErrors[0].error, {
message: 'oh snap',
source: 'source',
stack: ['Error: oh snap', `at foo @ ${baseUrl}/:`, `handler @ ${baseUrl}/:`],
handling: 'unhandled',
})
await withBrowserLogs((browserLogs) => {
expect(browserLogs.length).toEqual(1)
})
})

createTest('send unhandled rejections')
.withRum()
.withBody(createBody('Promise.reject(foo())'))
.run(async ({ serverEvents, baseUrl }) => {
const button = await $('button')
await button.click()

await flushEvents()
expect(serverEvents.rumErrors.length).toBe(1)
expectError(serverEvents.rumErrors[0].error, {
message: 'oh snap',
source: 'source',
stack: ['Error: oh snap', `at foo @ ${baseUrl}/:`, `handler @ ${baseUrl}/:`],
handling: 'unhandled',
})
await withBrowserLogs((browserLogs) => {
expect(browserLogs.length).toEqual(1)
})
})

createTest('send custom errors')
.withRum()
.withBody(createBody('DD_RUM.addError(foo())'))
.run(async ({ serverEvents, baseUrl }) => {
const button = await $('button')
await button.click()

await flushEvents()
expect(serverEvents.rumErrors.length).toBe(1)
expectError(serverEvents.rumErrors[0].error, {
message: 'oh snap',
source: 'custom',
stack: ['Error: oh snap', `at foo @ ${baseUrl}/:`, `handler @ ${baseUrl}/:`],
handlingStack: ['Error: ', `handler @ ${baseUrl}/:`],
handling: 'handled',
})
await withBrowserLogs((browserLogs) => {
expect(browserLogs.length).toEqual(0)
})
})
})

function expectError(
error: RumErrorEvent['error'],
expected: {
message: string
source: string
stack?: string[]
handlingStack?: string[]
handling: 'handled' | 'unhandled'
}
) {
expect(error.message).toBe(expected.message)
expect(error.source).toBe(expected.source)
expectStack(error.stack, expected.stack)
expectStack(error.handling_stack, expected.handlingStack)
expect(error.handling).toBe(expected.handling)
}

function expectStack(stack: string | undefined, expectedLines?: string[]) {
if (expectedLines === undefined) {
expect(stack).toBeUndefined()
} else {
expect(stack).toBeDefined()
const actualLines = stack!.split('\n')
expect(actualLines.length).toBe(expectedLines.length)
expectedLines.forEach((line, i) => {
if (i === 0) {
expect(actualLines[i]).toBe(line)
} else {
expect(actualLines[i]).toContain(line)
}
})
}
}

0 comments on commit 4fa9924

Please sign in to comment.