Skip to content

Commit

Permalink
feat: dedupe consecutive captured console errors
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Oct 18, 2024
1 parent c82f8e6 commit 5d2e74f
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { isHydrationError } from '../../../is-hydration-error'

// Dedupe the two consecutive errors: If the previous one is same as current one, ignore the current one.
export function enqueueConsecutiveDedupedError(
queue: Array<Error>,
error: Error
) {
const isFront = isHydrationError(error)
const previousError = isFront ? queue[0] : queue[queue.length - 1]
// Only check message to see if it's the same error, as message is representative display in the console.
if (previousError && previousError.message === error.message) {
return
}
// TODO: change all to push error into errorQueue,
// currently there's a async api error is always erroring while hydration error showing up.
// Move hydration error to the front of the queue to unblock.
if (isFront) {
queue.unshift(error)
} else {
queue.push(error)
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useEffect } from 'react'
import { isHydrationError } from '../../../is-hydration-error'
import { attachHydrationErrorState } from './attach-hydration-error-state'
import { isNextRouterError } from '../../../is-next-router-error'
import { storeHydrationErrorStateFromConsoleArgs } from './hydration-error-info'
import { formatConsoleArgs } from '../../../../lib/console'
import isError from '../../../../../lib/is-error'
import { ConsoleError } from './console-error'
import { enqueueConsecutiveDedupedError } from './enqueue-client-error'

export type ErrorHandler = (error: Error) => void

Expand All @@ -30,14 +30,7 @@ export function handleClientError(
storeHydrationErrorStateFromConsoleArgs(...consoleErrorArgs)
attachHydrationErrorState(error)

// TODO: change all to push error into errorQueue,
// currently there's a async api error is always erroring while hydration error showing up.
// Move hydration error to the front of the queue to unblock.
if (isHydrationError(error)) {
errorQueue.unshift(error)
} else {
errorQueue.push(error)
}
enqueueConsecutiveDedupedError(errorQueue, error)
for (const handler of errorHandlers) {
handler(error)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client'

export default function Page() {
console.error('trigger an console.error in render')
return <p>render</p>
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('app-dir - capture-console-error', () => {
})

it('should capture browser console error and format the error message', async () => {
const browser = await next.browser('/browser')
const browser = await next.browser('/browser/event')
await browser.elementByCss('button').click()

await waitForAndOpenRuntimeError(browser)
Expand All @@ -42,7 +42,7 @@ describe('app-dir - capture-console-error', () => {
"callStacks": "",
"count": 1,
"description": "trigger an console <error>",
"source": "app/browser/page.js (7:17) @ onClick
"source": "app/browser/event/page.js (7:17) @ onClick
5 | <button
6 | onClick={() => {
Expand All @@ -59,7 +59,7 @@ describe('app-dir - capture-console-error', () => {
"callStacks": "",
"count": 1,
"description": "trigger an console <error>",
"source": "app/browser/page.js (7:17) @ error
"source": "app/browser/event/page.js (7:17) @ error
5 | <button
6 | onClick={() => {
Expand All @@ -73,6 +73,51 @@ describe('app-dir - capture-console-error', () => {
}
})

it('should capture browser console error in render and dedupe if necessary', async () => {
const browser = await next.browser('/browser/render')

await waitForAndOpenRuntimeError(browser)
await assertHasRedbox(browser)

const result = await getRedboxResult(browser)

if (process.env.TURBOPACK) {
expect(result).toMatchInlineSnapshot(`
{
"callStacks": "",
"count": 1,
"description": "trigger an console.error in render",
"source": "app/browser/render/page.js (4:11) @ Page
2 |
3 | export default function Page() {
> 4 | console.error('trigger an console.error in render')
| ^
5 | return <p>render</p>
6 | }
7 |",
}
`)
} else {
expect(result).toMatchInlineSnapshot(`
{
"callStacks": "",
"count": 1,
"description": "trigger an console.error in render",
"source": "app/browser/render/page.js (4:11) @ error
2 |
3 | export default function Page() {
> 4 | console.error('trigger an console.error in render')
| ^
5 | return <p>render</p>
6 | }
7 |",
}
`)
}
})

it('should capture server replay console error', async () => {
const browser = await next.browser('/ssr')

Expand All @@ -85,7 +130,7 @@ describe('app-dir - capture-console-error', () => {
expect(result).toMatchInlineSnapshot(`
{
"callStacks": "",
"count": 2,
"count": 1,
"description": "ssr console error:client",
"source": "app/ssr/page.js (4:11) @ Page
Expand All @@ -102,7 +147,7 @@ describe('app-dir - capture-console-error', () => {
expect(result).toMatchInlineSnapshot(`
{
"callStacks": "",
"count": 2,
"count": 1,
"description": "ssr console error:client",
"source": "app/ssr/page.js (4:11) @ error
Expand Down

0 comments on commit 5d2e74f

Please sign in to comment.