diff --git a/eslint-local-rules/disallowSideEffects.js b/eslint-local-rules/disallowSideEffects.js
index 8bd1a9d8d4..890c5852df 100644
--- a/eslint-local-rules/disallowSideEffects.js
+++ b/eslint-local-rules/disallowSideEffects.js
@@ -35,6 +35,7 @@ const pathsWithSideEffect = new Set([
const packagesWithoutSideEffect = new Set([
'@datadog/browser-core',
'@datadog/browser-rum-core',
+ '@datadog/browser-rum-react/internal',
'react',
'react-router-dom',
'vue',
diff --git a/package.json b/package.json
index 82da504c7d..64e413b88d 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"build:apps": "node scripts/build/build-test-apps.ts",
"build:docs:json": "typedoc --logLevel Verbose --json ./generated-docs.json",
"build:docs:html": "typedoc --out ./generated-docs",
- "pack": "yarn workspaces foreach --all --parallel --include '@datadog/*' exec yarn pack",
+ "pack": "yarn workspaces foreach --all --parallel --topological --include '@datadog/*' exec yarn pack",
"format": "prettier --check .",
"lint": "NODE_OPTIONS='--max-old-space-size=4096' eslint .",
"typecheck": "tsc -b --noEmit true",
diff --git a/packages/rum-nextjs/package.json b/packages/rum-nextjs/package.json
index af0a91c39f..defb831a66 100644
--- a/packages/rum-nextjs/package.json
+++ b/packages/rum-nextjs/package.json
@@ -11,7 +11,8 @@
},
"dependencies": {
"@datadog/browser-core": "6.31.0",
- "@datadog/browser-rum-core": "6.31.0"
+ "@datadog/browser-rum-core": "6.31.0",
+ "@datadog/browser-rum-react": "6.31.0"
},
"peerDependencies": {
"next": ">=13.0.0",
@@ -36,6 +37,7 @@
"devDependencies": {
"@types/react": "19.2.11",
"next": "15.5.10",
- "react": "19.2.4"
+ "react": "19.2.4",
+ "react-dom": "19.2.4"
}
}
diff --git a/packages/rum-nextjs/src/domain/error/errorBoundary.spec.tsx b/packages/rum-nextjs/src/domain/error/errorBoundary.spec.tsx
new file mode 100644
index 0000000000..123aede1a5
--- /dev/null
+++ b/packages/rum-nextjs/src/domain/error/errorBoundary.spec.tsx
@@ -0,0 +1,42 @@
+import React from 'react'
+
+import { disableJasmineUncaughtExceptionTracking, ignoreConsoleLogs } from '@datadog/browser-core/test'
+import { appendComponent } from '../../../../rum-react/test/appendComponent'
+import { initReactOldBrowsersSupport } from '../../../../rum-react/test/reactOldBrowsersSupport'
+import { initializeNextjsPlugin } from '../../../test/initializeNextjsPlugin'
+import { ErrorBoundary } from './errorBoundary'
+
+// Component behavior (renders children, fallback, resetError) is tested via createErrorBoundary
+// in packages/rum-react/src/domain/error/errorBoundary.spec.tsx
+
+describe('NextjsErrorBoundary', () => {
+ it('reports the error through addNextjsError', () => {
+ ignoreConsoleLogs('error', 'Error: error')
+ disableJasmineUncaughtExceptionTracking()
+ initReactOldBrowsersSupport()
+
+ const addErrorSpy = jasmine.createSpy()
+ initializeNextjsPlugin({ addError: addErrorSpy })
+ const originalError = new Error('error')
+ const ComponentSpy = jasmine.createSpy().and.throwError(originalError)
+ ;(ComponentSpy as any).displayName = 'ComponentSpy'
+
+ appendComponent(
+ null}>
+
+
+ )
+
+ expect(addErrorSpy).toHaveBeenCalledOnceWith(
+ jasmine.objectContaining({
+ error: originalError,
+ handlingStack: jasmine.any(String),
+ startClocks: jasmine.any(Object),
+ context: jasmine.objectContaining({
+ framework: 'nextjs',
+ }),
+ componentStack: jasmine.stringContaining('ComponentSpy'),
+ })
+ )
+ })
+})
diff --git a/packages/rum-nextjs/src/domain/error/errorBoundary.ts b/packages/rum-nextjs/src/domain/error/errorBoundary.ts
new file mode 100644
index 0000000000..67ad094d54
--- /dev/null
+++ b/packages/rum-nextjs/src/domain/error/errorBoundary.ts
@@ -0,0 +1,22 @@
+'use client'
+import { createErrorBoundary } from '@datadog/browser-rum-react/internal'
+export type { ErrorBoundaryFallback, ErrorBoundaryProps } from '@datadog/browser-rum-react/internal'
+import { addNextjsError } from './addNextjsError'
+
+/**
+ * ErrorBoundary component to report React errors to Datadog using the Next.js error context.
+ *
+ * For more advanced error handling, you can use the {@link addNextjsError} function.
+ *
+ * @category Error
+ * @example
+ * ```ts
+ * import { ErrorBoundary } from '@datadog/browser-rum-nextjs'
+ *
+ * null}>
+ *
+ *
+ * ```
+ */
+// eslint-disable-next-line local-rules/disallow-side-effects
+export const ErrorBoundary = createErrorBoundary(addNextjsError)
diff --git a/packages/rum-nextjs/src/entries/main.ts b/packages/rum-nextjs/src/entries/main.ts
index d6bdb2237f..70f1d03311 100644
--- a/packages/rum-nextjs/src/entries/main.ts
+++ b/packages/rum-nextjs/src/entries/main.ts
@@ -3,3 +3,5 @@ export type { NextjsPlugin } from '../domain/nextjsPlugin'
export { DatadogAppRouter } from '../domain/nextJSRouter/datadogAppRouter'
export { DatadogPagesRouter } from '../domain/nextJSRouter/datadogPagesRouter'
export { addNextjsError } from '../domain/error/addNextjsError'
+export { ErrorBoundary } from '../domain/error/errorBoundary'
+export type { ErrorBoundaryFallback, ErrorBoundaryProps } from '../domain/error/errorBoundary'
diff --git a/test/apps/angular-app/yarn.lock b/test/apps/angular-app/yarn.lock
index 5c3c417df6..7070b9c168 100644
--- a/test/apps/angular-app/yarn.lock
+++ b/test/apps/angular-app/yarn.lock
@@ -296,14 +296,14 @@ __metadata:
"@datadog/browser-core@file:../../../packages/core/package.tgz::locator=angular-app%40workspace%3A.":
version: 6.31.0
- resolution: "@datadog/browser-core@file:../../../packages/core/package.tgz#../../../packages/core/package.tgz::hash=d110af&locator=angular-app%40workspace%3A."
- checksum: 10c0/1e3797a56310fde499578396bd2594c4e0ac891610e7d57ddac2164a8c29a97177b3eac938f6a8480192bb31b5d798acaf2ea26de1778047d43c010ff0124dc0
+ resolution: "@datadog/browser-core@file:../../../packages/core/package.tgz#../../../packages/core/package.tgz::hash=6201e3&locator=angular-app%40workspace%3A."
+ checksum: 10c0/a019713374971a2dd35c63318cecd76e38d08348a24ca5b88abb8fca8501d17589e187bd4e68c7358f3523dd3fd08d110b307647854a620b0f3371f2c7db14ca
languageName: node
linkType: hard
"@datadog/browser-rum-angular@file:../../../packages/rum-angular/package.tgz::locator=angular-app%40workspace%3A.":
version: 0.0.0
- resolution: "@datadog/browser-rum-angular@file:../../../packages/rum-angular/package.tgz#../../../packages/rum-angular/package.tgz::hash=1db391&locator=angular-app%40workspace%3A."
+ resolution: "@datadog/browser-rum-angular@file:../../../packages/rum-angular/package.tgz#../../../packages/rum-angular/package.tgz::hash=004229&locator=angular-app%40workspace%3A."
dependencies:
"@datadog/browser-core": "npm:6.31.0"
"@datadog/browser-rum-core": "npm:6.31.0"
@@ -311,27 +311,22 @@ __metadata:
"@angular/core": ">=15 <=21"
"@angular/router": ">=15 <=21"
rxjs: ">=7"
- peerDependenciesMeta:
- "@angular/core":
- optional: true
- "@angular/router":
- optional: true
- checksum: 10c0/837488f8f27aee3c58e0be4f91039b2de9c3bc00e655f6f65bd5992c1101443ae48fbeedc68c95ef4281535c3a4de8c3e3073974b2938ebb493cf23e3a91f5a6
+ checksum: 10c0/ec9054d51805f45cb4618bcbc6fa00049ba5d1597048aa3c354aea14a15a06275ee0ba06b3de7d77fbd0d2f009f74159a88e10f2f6b9e629eeed0a5ca30a27ae
languageName: node
linkType: hard
"@datadog/browser-rum-core@file:../../../packages/rum-core/package.tgz::locator=angular-app%40workspace%3A.":
version: 6.31.0
- resolution: "@datadog/browser-rum-core@file:../../../packages/rum-core/package.tgz#../../../packages/rum-core/package.tgz::hash=638808&locator=angular-app%40workspace%3A."
+ resolution: "@datadog/browser-rum-core@file:../../../packages/rum-core/package.tgz#../../../packages/rum-core/package.tgz::hash=0334b6&locator=angular-app%40workspace%3A."
dependencies:
"@datadog/browser-core": "npm:6.31.0"
- checksum: 10c0/f57c5d9fdbc7243f373afba6912bb75a90f3b65ab036750a858aa7776ed30b8921e456eff32a02e7dc021c192cd7bc220ea7b124459eacb7685c5c5ba0cca1c5
+ checksum: 10c0/3ece55e0ca0bc0691fd91c557433c806e2871b56e3a0008c01b6e369809c9130fa384952b22ee6464d49d182d3e4e5bd66f51b6b629d4024d6e482f7e64d13c8
languageName: node
linkType: hard
"@datadog/browser-rum@file:../../../packages/rum/package.tgz::locator=angular-app%40workspace%3A.":
version: 6.31.0
- resolution: "@datadog/browser-rum@file:../../../packages/rum/package.tgz#../../../packages/rum/package.tgz::hash=920d70&locator=angular-app%40workspace%3A."
+ resolution: "@datadog/browser-rum@file:../../../packages/rum/package.tgz#../../../packages/rum/package.tgz::hash=033900&locator=angular-app%40workspace%3A."
dependencies:
"@datadog/browser-core": "npm:6.31.0"
"@datadog/browser-rum-core": "npm:6.31.0"
@@ -340,7 +335,7 @@ __metadata:
peerDependenciesMeta:
"@datadog/browser-logs":
optional: true
- checksum: 10c0/135a2cdf999ea9505e08031ae7069f4d6a236a88e6203ef7105c784a77ae23a23fbabc648d793305dcb4b960cbe4a535fab2d688748efb5824137597f4de84b5
+ checksum: 10c0/ac0080efb7f664a5664162a64e618b885d2c4d2d06426db0ad076c855dd02cbc84f1ba6fc30913db8db74d50a511d0a0a62ba1ad7bb9e8de5c3ef0c03e3f9c56
languageName: node
linkType: hard
diff --git a/test/apps/nextjs/pages/pages-router/error-test.tsx b/test/apps/nextjs/pages/pages-router/error-test.tsx
new file mode 100644
index 0000000000..9ec73b34d1
--- /dev/null
+++ b/test/apps/nextjs/pages/pages-router/error-test.tsx
@@ -0,0 +1,35 @@
+import { ErrorBoundary } from '@datadog/browser-rum-nextjs'
+import type { ErrorBoundaryFallback } from '@datadog/browser-rum-nextjs'
+import { useState } from 'react'
+import Link from 'next/link'
+
+function ErrorThrower() {
+ const [shouldThrow, setShouldThrow] = useState(false)
+ if (shouldThrow) throw new Error('Pages Router error from NextjsErrorBoundary')
+ return (
+ setShouldThrow(true)}>
+ Trigger Error
+
+ )
+}
+
+const ErrorFallback: ErrorBoundaryFallback = ({ error, resetError }) => (
+
+
{error.message}
+
+ Reset
+
+
+)
+
+export default function ErrorTestPage() {
+ return (
+
+ ← Back to Home
+
Error Test
+
+
+
+
+ )
+}
diff --git a/test/apps/nextjs/pages/pages-router/index.tsx b/test/apps/nextjs/pages/pages-router/index.tsx
index cc03d59a47..2d31b81838 100644
--- a/test/apps/nextjs/pages/pages-router/index.tsx
+++ b/test/apps/nextjs/pages/pages-router/index.tsx
@@ -11,6 +11,9 @@ export default function HomePage() {
Go to Guides 123
+
+ Go to Error Test
+
)
diff --git a/test/apps/nextjs/pages/pages-router/user/[id].tsx b/test/apps/nextjs/pages/pages-router/user/[id].tsx
index 54efa0f286..ef36c9180e 100644
--- a/test/apps/nextjs/pages/pages-router/user/[id].tsx
+++ b/test/apps/nextjs/pages/pages-router/user/[id].tsx
@@ -10,9 +10,15 @@ export default function UserPage() {
← Back to Home
User {id}
This is a dynamic route testing view name normalization.
- Go to User 999
- Change query params
- Go to Section
+
+ Go to User 999
+
+
+ Change query params
+
+
+ Go to Section
+
)
}
diff --git a/test/apps/nextjs/yarn.lock b/test/apps/nextjs/yarn.lock
index 350c54ea6d..2b2d9e7166 100644
--- a/test/apps/nextjs/yarn.lock
+++ b/test/apps/nextjs/yarn.lock
@@ -7,8 +7,8 @@ __metadata:
"@datadog/browser-core@file:../../../packages/core/package.tgz::locator=nextjs%40workspace%3A.":
version: 6.31.0
- resolution: "@datadog/browser-core@file:../../../packages/core/package.tgz#../../../packages/core/package.tgz::hash=d35e3a&locator=nextjs%40workspace%3A."
- checksum: 10c0/e35c0d98c72fa3ed46dcbd42615c156fcb13f4622681906145aac91630c291adc7a166861568e61a09f6301baed1adaf5c95b675b9407c72fbe936129f305253
+ resolution: "@datadog/browser-core@file:../../../packages/core/package.tgz#../../../packages/core/package.tgz::hash=6201e3&locator=nextjs%40workspace%3A."
+ checksum: 10c0/a019713374971a2dd35c63318cecd76e38d08348a24ca5b88abb8fca8501d17589e187bd4e68c7358f3523dd3fd08d110b307647854a620b0f3371f2c7db14ca
languageName: node
linkType: hard
@@ -23,10 +23,11 @@ __metadata:
"@datadog/browser-rum-nextjs@file:../../../packages/rum-nextjs/package.tgz::locator=nextjs%40workspace%3A.":
version: 0.0.0
- resolution: "@datadog/browser-rum-nextjs@file:../../../packages/rum-nextjs/package.tgz#../../../packages/rum-nextjs/package.tgz::hash=0643d8&locator=nextjs%40workspace%3A."
+ resolution: "@datadog/browser-rum-nextjs@file:../../../packages/rum-nextjs/package.tgz#../../../packages/rum-nextjs/package.tgz::hash=33a720&locator=nextjs%40workspace%3A."
dependencies:
"@datadog/browser-core": "npm:6.31.0"
"@datadog/browser-rum-core": "npm:6.31.0"
+ "@datadog/browser-rum-react": "npm:6.31.0"
peerDependencies:
next: ">=13.0.0"
react: ">=18.0.0"
@@ -35,13 +36,13 @@ __metadata:
optional: true
react:
optional: true
- checksum: 10c0/8f1ae5ce76730608a77b924f6c25cc9b325f314621fa1d03ed29a9a6d6a084dcfa61e9a36bb1f2005ff5939b5137dbe11ff5b27af09d41b3a5dcdbc0e0ef4ace
+ checksum: 10c0/5bd3c94fa2fa71d0c19626b8a8cdfa933da6bd0626a99abbd5d0bb07374c9bca9554eba05c427baf35fe0e0fbf4f891dd741822908a4cebe30ca4ea502ae9355
languageName: node
linkType: hard
"@datadog/browser-rum-react@file:../../../packages/rum-react/package.tgz::locator=nextjs%40workspace%3A.":
version: 6.31.0
- resolution: "@datadog/browser-rum-react@file:../../../packages/rum-react/package.tgz#../../../packages/rum-react/package.tgz::hash=2dd471&locator=nextjs%40workspace%3A."
+ resolution: "@datadog/browser-rum-react@file:../../../packages/rum-react/package.tgz#../../../packages/rum-react/package.tgz::hash=ff7bfc&locator=nextjs%40workspace%3A."
dependencies:
"@datadog/browser-core": "npm:6.31.0"
"@datadog/browser-rum-core": "npm:6.31.0"
@@ -66,7 +67,7 @@ __metadata:
"@datadog/browser-rum@file:../../../packages/rum/package.tgz::locator=nextjs%40workspace%3A.":
version: 6.31.0
- resolution: "@datadog/browser-rum@file:../../../packages/rum/package.tgz#../../../packages/rum/package.tgz::hash=439f60&locator=nextjs%40workspace%3A."
+ resolution: "@datadog/browser-rum@file:../../../packages/rum/package.tgz#../../../packages/rum/package.tgz::hash=033900&locator=nextjs%40workspace%3A."
dependencies:
"@datadog/browser-core": "npm:6.31.0"
"@datadog/browser-rum-core": "npm:6.31.0"
@@ -75,7 +76,7 @@ __metadata:
peerDependenciesMeta:
"@datadog/browser-logs":
optional: true
- checksum: 10c0/be73607a3c5602407ad824b7e149c633c9bfebf3e6fd543b56598a4067afcbbf28e6324be430b6e846aef8bee0c588e4bd258ae3671a1419a3fdaa31efa5e3f1
+ checksum: 10c0/ac0080efb7f664a5664162a64e618b885d2c4d2d06426db0ad076c855dd02cbc84f1ba6fc30913db8db74d50a511d0a0a62ba1ad7bb9e8de5c3ef0c03e3f9c56
languageName: node
linkType: hard
@@ -415,18 +416,18 @@ __metadata:
linkType: hard
"baseline-browser-mapping@npm:^2.8.3":
- version: 2.10.7
- resolution: "baseline-browser-mapping@npm:2.10.7"
+ version: 2.10.8
+ resolution: "baseline-browser-mapping@npm:2.10.8"
bin:
baseline-browser-mapping: dist/cli.cjs
- checksum: 10c0/fe2988088ede5a2dc7936f0a718d4b500b2a28a7ee3e11e2a3844a9444dd217a95a070c00508d8130da73c4fe576d677b21844bc078f6cd7867fb0e1be60caf0
+ checksum: 10c0/a77882e8ac37a900a9a0757b9bf4e50f407829ed17ee7630273ab5da0ae10d9c64ed4c5a1e03afb3490e39713440092417ded4bb856eeb9bd44856eacbd97497
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001579":
- version: 1.0.30001778
- resolution: "caniuse-lite@npm:1.0.30001778"
- checksum: 10c0/830042e0a6af0796d3da4d9575f60966b92308c5504577993b618dd196c835d023dbd725fa8b47c33b74c487d75ce01ee3ebd6e7a078714989513110e8ff80e5
+ version: 1.0.30001780
+ resolution: "caniuse-lite@npm:1.0.30001780"
+ checksum: 10c0/8a88f39758a228852d6f3ac92362ecb7694b1b2b022f194d8dfe59123ad40a5de6202bf2dff0fe316bb3d5ca9caf316c22056e0da693459c3be2771cde4f4bf9
languageName: node
linkType: hard
diff --git a/test/e2e/scenario/nextjsPlugin.scenario.ts b/test/e2e/scenario/nextjsPlugin.scenario.ts
index ac4795f49b..395e695c71 100644
--- a/test/e2e/scenario/nextjsPlugin.scenario.ts
+++ b/test/e2e/scenario/nextjsPlugin.scenario.ts
@@ -14,6 +14,7 @@ const routerConfigs = [
router: 'pages' as const,
viewPrefix: '/pages-router',
homeUrlPattern: /\/pages-router(\?|$)/,
+ clientErrorMessage: 'Pages Router error from NextjsErrorBoundary',
},
]
@@ -200,71 +201,77 @@ test.describe('nextjs - router', () => {
})
test.describe('nextjs - errors', () => {
- const { name, viewPrefix, clientErrorMessage, router } = routerConfigs[0]
-
- test.describe(name, () => {
- createTest('should report client-side error')
- .withRum()
- .withNextjsApp(router)
- .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
- await page.click('text=Go to Error Test')
- await page.waitForURL(`**${viewPrefix}/error-test`)
+ routerConfigs.forEach(({ name, router, viewPrefix, clientErrorMessage }) => {
+ test.describe(name, () => {
+ createTest('should report client-side error')
+ .withRum()
+ .withNextjsApp(router)
+ .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs, browserName }) => {
+ test.skip(
+ browserName === 'firefox',
+ 'firefox is sending the errors in two separate batches, however the last batch is delayed making the test setup to miss it'
+ )
+ await page.click('text=Go to Error Test')
+ await page.waitForURL(`**${viewPrefix}/error-test`)
- await page.click('[data-testid="trigger-error"]')
- await page.waitForSelector('[data-testid="error-boundary"]')
+ await page.click('[data-testid="trigger-error"]')
+ await page.waitForSelector('[data-testid="error-boundary"]')
- await flushEvents()
+ await flushEvents()
- const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')
- expect(customErrors).toHaveLength(1)
- expect(customErrors[0].error.message).toBe(clientErrorMessage)
- expect(customErrors[0].error.handling_stack).toBeDefined()
- expect(customErrors[0].context).toMatchObject({ framework: 'nextjs' })
+ const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')
+ expect(customErrors).toHaveLength(1)
+ expect(customErrors[0].error.message).toBe(clientErrorMessage)
+ expect(customErrors[0].error.handling_stack).toBeDefined()
+ expect(customErrors[0].context).toMatchObject({ framework: 'nextjs' })
- withBrowserLogs((browserLogs) => {
- expect(browserLogs.length).toBeGreaterThan(0)
- })
- })
-
- createTest('should report a server error with digest via addNextjsError')
- .withRum()
- .withNextjsApp(router)
- .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
- await page.click('text=Go to Server Error')
- await page.waitForSelector('[data-testid="error-boundary"]')
-
- await flushEvents()
-
- const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')
- expect(customErrors).toHaveLength(1)
- expect(customErrors[0].error.handling_stack).toBeDefined()
- expect(customErrors[0].context).toMatchObject({
- framework: 'nextjs',
- nextjs: { digest: expect.any(String) },
+ withBrowserLogs((browserLogs) => {
+ expect(browserLogs.length).toBeGreaterThan(0)
+ })
})
- withBrowserLogs((browserLogs) => {
- expect(browserLogs.length).toBeGreaterThan(0)
- })
- })
+ if (router === 'app') {
+ createTest('should report a server error with digest via addNextjsError')
+ .withRum()
+ .withNextjsApp(router)
+ .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
+ await page.click('text=Go to Server Error')
+ await page.waitForSelector('[data-testid="error-boundary"]')
- createTest('should report global error via global-error.tsx')
- .withRum()
- .withNextjsApp(router)
- .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
- await page.click('text=Go to Global Error')
- await page.waitForSelector('[data-testid="global-error-boundary"]')
+ await flushEvents()
- await flushEvents()
+ const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')
+ expect(customErrors).toHaveLength(1)
+ expect(customErrors[0].error.handling_stack).toBeDefined()
+ expect(customErrors[0].context).toMatchObject({
+ framework: 'nextjs',
+ nextjs: { digest: expect.any(String) },
+ })
+
+ withBrowserLogs((browserLogs) => {
+ expect(browserLogs.length).toBeGreaterThan(0)
+ })
+ })
- const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')
- expect(customErrors).toHaveLength(1)
- expect(customErrors[0].error.handling_stack).toBeDefined()
- expect(customErrors[0].context).toMatchObject({ framework: 'nextjs' })
+ createTest('should report global error via global-error.tsx')
+ .withRum()
+ .withNextjsApp(router)
+ .run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
+ await page.click('text=Go to Global Error')
+ await page.waitForSelector('[data-testid="global-error-boundary"]')
- withBrowserLogs((browserLogs) => {
- expect(browserLogs.length).toBeGreaterThan(0)
- })
- })
+ await flushEvents()
+
+ const customErrors = intakeRegistry.rumErrorEvents.filter((e) => e.error.source === 'custom')
+ expect(customErrors).toHaveLength(1)
+ expect(customErrors[0].error.handling_stack).toBeDefined()
+ expect(customErrors[0].context).toMatchObject({ framework: 'nextjs' })
+
+ withBrowserLogs((browserLogs) => {
+ expect(browserLogs.length).toBeGreaterThan(0)
+ })
+ })
+ }
+ })
})
})
diff --git a/yarn.lock b/yarn.lock
index 23f62ff94e..47fe7cada0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -372,9 +372,11 @@ __metadata:
dependencies:
"@datadog/browser-core": "npm:6.31.0"
"@datadog/browser-rum-core": "npm:6.31.0"
+ "@datadog/browser-rum-react": "npm:6.31.0"
"@types/react": "npm:19.2.11"
next: "npm:15.5.10"
react: "npm:19.2.4"
+ react-dom: "npm:19.2.4"
peerDependencies:
next: ">=13.0.0"
react: ">=18.0.0"
@@ -386,7 +388,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@datadog/browser-rum-react@workspace:packages/rum-react":
+"@datadog/browser-rum-react@npm:6.31.0, @datadog/browser-rum-react@workspace:packages/rum-react":
version: 0.0.0-use.local
resolution: "@datadog/browser-rum-react@workspace:packages/rum-react"
dependencies: