diff --git a/test/apps/angular-app/main.ts b/test/apps/angular-app/main.ts
index 0779c2423d..21a57e7bde 100644
--- a/test/apps/angular-app/main.ts
+++ b/test/apps/angular-app/main.ts
@@ -27,11 +27,11 @@ if (window.RUM_CONTEXT) {
imports: [RouterLink],
template: `
Initial Route
- Go to User 42
- Go to Guides 123
- Go to Error Test
- Go to Nested Route
- Go to Wildcard Route
+ Go to User 42
+ Go to Guides 123
+ Go to Error Test
+ Go to Nested Route
+ Go to Wildcard Route
Throw Error
Throw Error With Context
`,
@@ -54,10 +54,14 @@ class InitialRouteComponent {
imports: [RouterLink],
template: `
User Page
- Back to Home
- Go to Section
- Change query params
- Go to User 999
+ Back to Home
+ Go to Section
+ Change query params
+ Go to User 999
`,
})
class UserRouteComponent {
@@ -70,7 +74,7 @@ class UserRouteComponent {
imports: [RouterLink],
template: `
Guides
- Back to Home
+ Back to Home
`,
})
class GuidesRouteComponent {}
diff --git a/test/apps/nextjs/app/guides/[...slug]/page.tsx b/test/apps/nextjs/app/guides/[...slug]/page.tsx
index 0b9003d978..6e4f2931fa 100644
--- a/test/apps/nextjs/app/guides/[...slug]/page.tsx
+++ b/test/apps/nextjs/app/guides/[...slug]/page.tsx
@@ -5,7 +5,9 @@ export default async function GuidesPage({ params }: { params: Promise<{ slug: s
return (
- Back to Home
+
+ Back to Home
+
Guides: {slug.join('/')}
)
diff --git a/test/apps/nextjs/app/page.tsx b/test/apps/nextjs/app/page.tsx
index 9d80fd5b82..42e978560f 100644
--- a/test/apps/nextjs/app/page.tsx
+++ b/test/apps/nextjs/app/page.tsx
@@ -6,19 +6,29 @@ export default function HomePage() {
Home
- Go to User 42
+
+ Go to User 42
+
- Go to Guides 123
+
+ Go to Guides 123
+
- Go to Error Test
+
+ Go to Error Test
+
- Go to Server Error
+
+ Go to Server Error
+
- Go to Global Error
+
+ Go to Global Error
+
diff --git a/test/apps/nextjs/app/user/[id]/page.tsx b/test/apps/nextjs/app/user/[id]/page.tsx
index d3832f7cf0..6f1dc8eaba 100644
--- a/test/apps/nextjs/app/user/[id]/page.tsx
+++ b/test/apps/nextjs/app/user/[id]/page.tsx
@@ -5,16 +5,24 @@ export default async function UserPage({ params }: { params: Promise<{ id: strin
return (
-
← Back to Home
+
+ ← Back to Home
+
User {id}
- Go to User 999
+
+ Go to User 999
+
- Change query params
+
+ Change query params
+
- Go to Section
+
+ Go to Section
+
)
diff --git a/test/apps/nextjs/pages/pages-router/guides/[...slug].tsx b/test/apps/nextjs/pages/pages-router/guides/[...slug].tsx
index e54ea7d828..f406a1cc26 100644
--- a/test/apps/nextjs/pages/pages-router/guides/[...slug].tsx
+++ b/test/apps/nextjs/pages/pages-router/guides/[...slug].tsx
@@ -8,7 +8,9 @@ export default function GuidesPage() {
return (
- ← Back to Home
+
+ ← Back to Home
+
Guides: {slugParts.join('/')}
)
diff --git a/test/apps/nextjs/pages/pages-router/index.tsx b/test/apps/nextjs/pages/pages-router/index.tsx
index 2d31b81838..b64c2730b5 100644
--- a/test/apps/nextjs/pages/pages-router/index.tsx
+++ b/test/apps/nextjs/pages/pages-router/index.tsx
@@ -6,13 +6,19 @@ export default function HomePage() {
Home
- Go to User 42
+
+ Go to User 42
+
- Go to Guides 123
+
+ Go to Guides 123
+
- Go to Error Test
+
+ 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 929a5104d2..e276e76042 100644
--- a/test/apps/nextjs/pages/pages-router/user/[id].tsx
+++ b/test/apps/nextjs/pages/pages-router/user/[id].tsx
@@ -7,16 +7,24 @@ export default function UserPage() {
return (
-
← Back to Home
+
+ ← Back to Home
+
User {id}
- Go to User 999
+
+ Go to User 999
+
- Change query params
+
+ Change query params
+
- Go to Section
+
+ Go to Section
+
)
diff --git a/test/apps/nuxt-app/pages/guides/[...slug].vue b/test/apps/nuxt-app/pages/guides/[...slug].vue
index 9e5817691b..57dbfb70dd 100644
--- a/test/apps/nuxt-app/pages/guides/[...slug].vue
+++ b/test/apps/nuxt-app/pages/guides/[...slug].vue
@@ -1,6 +1,6 @@
Guides
- Back to Home
+ Back to Home
diff --git a/test/apps/nuxt-app/pages/index.vue b/test/apps/nuxt-app/pages/index.vue
index 4669277f20..47ea1f3007 100644
--- a/test/apps/nuxt-app/pages/index.vue
+++ b/test/apps/nuxt-app/pages/index.vue
@@ -1,8 +1,8 @@
Home
- Go to User 42
- Go to Guides 123
- Go to Error Test
+ Go to User 42
+ Go to Guides 123
+ Go to Error Test
diff --git a/test/apps/nuxt-app/pages/user/[id].vue b/test/apps/nuxt-app/pages/user/[id].vue
index 22c76dd2f8..39c2088ea4 100644
--- a/test/apps/nuxt-app/pages/user/[id].vue
+++ b/test/apps/nuxt-app/pages/user/[id].vue
@@ -5,9 +5,11 @@ const route = useRoute()
User {{ route.params.id }}
- Back to Home
- Go to Section
- Change query params
- Go to User 999
+ Back to Home
+ Go to Section
+ Change query params
+ Go to User 999
diff --git a/test/apps/nuxt-app/yarn.lock b/test/apps/nuxt-app/yarn.lock
index 3f5c01f111..c8998634d4 100644
--- a/test/apps/nuxt-app/yarn.lock
+++ b/test/apps/nuxt-app/yarn.lock
@@ -347,8 +347,8 @@ __metadata:
"@datadog/browser-core@file:../../../packages/core/package.tgz::locator=nuxt-app%40workspace%3A.":
version: 6.32.0
- resolution: "@datadog/browser-core@file:../../../packages/core/package.tgz#../../../packages/core/package.tgz::hash=3139c3&locator=nuxt-app%40workspace%3A."
- checksum: 10c0/043726d1ed47fc37dc7f38bf1a79db8ddc191eb07602e347e96d02c4f837d5773ed548dd8c07a8e92f121d460da68d84088489030c7f88120194927c77b4ac09
+ resolution: "@datadog/browser-core@file:../../../packages/core/package.tgz#../../../packages/core/package.tgz::hash=2bcbab&locator=nuxt-app%40workspace%3A."
+ checksum: 10c0/d184c9c1b22336ceebe73f9e7b74c1d8fc955610171d9d765e2032baf4ce3fc1b63bea4950a0bd99a73e212d75e064b9161dad6df9cefdaf8fdbe54d4ad29ecd
languageName: node
linkType: hard
@@ -363,7 +363,7 @@ __metadata:
"@datadog/browser-rum-nuxt@file:../../../packages/rum-nuxt/package.tgz::locator=nuxt-app%40workspace%3A.":
version: 0.0.0
- resolution: "@datadog/browser-rum-nuxt@file:../../../packages/rum-nuxt/package.tgz#../../../packages/rum-nuxt/package.tgz::hash=e895b3&locator=nuxt-app%40workspace%3A."
+ resolution: "@datadog/browser-rum-nuxt@file:../../../packages/rum-nuxt/package.tgz#../../../packages/rum-nuxt/package.tgz::hash=293201&locator=nuxt-app%40workspace%3A."
dependencies:
"@datadog/browser-core": "npm:6.32.0"
"@datadog/browser-rum-core": "npm:6.32.0"
@@ -382,7 +382,7 @@ __metadata:
optional: true
vue-router:
optional: true
- checksum: 10c0/8c760e9dbd337296a5f4d55980616dc37a47b98676887e7db50aa8ff6cb70b7979ae647229c58daeea9bf3053eb1fc701e637e8c4783aacb9eedc769bb994383
+ checksum: 10c0/ee8d7b559120abea1056e7c984e731cd9cac8edf83d8840bcbabd65e9f0fb51725f9a7ccbab22a396cd73116964091067aaa09e36d2ea0e2113548c89ddeba9a
languageName: node
linkType: hard
diff --git a/test/apps/react-router-v6-app/app.tsx b/test/apps/react-router-v6-app/app.tsx
index e0f9aea8f1..3da3afd722 100644
--- a/test/apps/react-router-v6-app/app.tsx
+++ b/test/apps/react-router-v6-app/app.tsx
@@ -25,15 +25,25 @@ function HomePage() {
return (
Home
- Go to User 42
+
+ Go to User 42
+
- Go to Guides 123
+
+ Go to Guides 123
+
- Go to Wildcard
+
+ Go to Wildcard
+
- Go to Error Test
+
+ Go to Error Test
+
- Go to Tracked
+
+ Go to Tracked
+
)
}
@@ -43,13 +53,21 @@ function UserPage() {
return (
User {id}
- Back to Home
+
+ Back to Home
+
- Go to Section
+
+ Go to Section
+
- Change query params
+
+ Change query params
+
- Go to User 999
+
+ Go to User 999
+
)
}
@@ -58,7 +76,9 @@ function GuidesPage() {
return (
Guides
- Back to Home
+
+ Back to Home
+
)
}
@@ -68,7 +88,9 @@ function WildcardPage() {
return (
Wildcard: {splatPath}
- Back to Home
+
+ Back to Home
+
)
}
diff --git a/test/apps/vue-router-app/src/pages/GuidesPage.vue b/test/apps/vue-router-app/src/pages/GuidesPage.vue
index 175e982d4f..545da0153e 100644
--- a/test/apps/vue-router-app/src/pages/GuidesPage.vue
+++ b/test/apps/vue-router-app/src/pages/GuidesPage.vue
@@ -1,6 +1,6 @@
Guides
- Back to Home
+ Back to Home
diff --git a/test/apps/vue-router-app/src/pages/HomePage.vue b/test/apps/vue-router-app/src/pages/HomePage.vue
index 6fae5a7ea1..3c4f64a664 100644
--- a/test/apps/vue-router-app/src/pages/HomePage.vue
+++ b/test/apps/vue-router-app/src/pages/HomePage.vue
@@ -1,8 +1,8 @@
Home
- Go to User 42
- Go to Guides 123
- Go to Error Test
+ Go to User 42
+ Go to Guides 123
+ Go to Error Test
diff --git a/test/apps/vue-router-app/src/pages/UserPage.vue b/test/apps/vue-router-app/src/pages/UserPage.vue
index 3dcd166c10..b342791dc3 100644
--- a/test/apps/vue-router-app/src/pages/UserPage.vue
+++ b/test/apps/vue-router-app/src/pages/UserPage.vue
@@ -5,9 +5,11 @@ const route = useRoute()
User {{ route.params.id }}
- Back to Home
- Go to Section
- Change query params
- Go to User 999
+ Back to Home
+ Go to Section
+ Change query params
+ Go to User 999
diff --git a/test/e2e/scenario/browser-extensions/browserExtensions.scenario.ts b/test/e2e/scenario/browser-extensions/browserExtensions.scenario.ts
index 0bb5b571cd..f894f4f89f 100644
--- a/test/e2e/scenario/browser-extensions/browserExtensions.scenario.ts
+++ b/test/e2e/scenario/browser-extensions/browserExtensions.scenario.ts
@@ -92,7 +92,7 @@ test.describe('browser extensions', () => {
*/
createTest('should not warn - edge case simulating NextJs with an extension that override `appendChild`')
.withExtension(createExtension(path.join(BASE_PATH, 'appendChild-extension')))
- .withRum()
+ .withRum({ sessionReplaySampleRate: 0 })
.withLogs()
.withSetup((options, servers) => {
const { rumScriptUrl, logsScriptUrl } = createCrossOriginScriptUrls(servers, options)
diff --git a/test/e2e/scenario/plugins/angularPlugin.scenario.ts b/test/e2e/scenario/plugins/angularPlugin.scenario.ts
index 89bc229b69..1fbad247a6 100644
--- a/test/e2e/scenario/plugins/angularPlugin.scenario.ts
+++ b/test/e2e/scenario/plugins/angularPlugin.scenario.ts
@@ -1,7 +1,8 @@
import { test, expect } from '@playwright/test'
import { createTest } from '../../lib/framework'
import { runBasePluginErrorTests } from './basePluginErrorTests'
-import { runBasePluginRouterTests } from './basePluginRouterTests'
+import { createBasePluginRouterConfig, runBasePluginRouterTests } from './basePluginRouterTests'
+import { clickAndWaitForURL } from './navigationUtils'
const angularAppName = 'angular-app'
const angularBasePluginConfig = {
@@ -13,12 +14,13 @@ const angularBasePluginConfig = {
runBasePluginRouterTests([
{
...angularBasePluginConfig,
- router: {
+ router: createBasePluginRouterConfig({
homeViewName: '/',
homeUrlPattern: '**/',
userRouteName: '/user/:id',
guidesRouteName: '/guides/:slug',
- },
+ viewPrefix: '',
+ }),
},
])
@@ -38,26 +40,28 @@ test.describe('plugin: angular', () => {
.withRum()
.withApp(angularAppName)
.run(async ({ page, flushEvents, intakeRegistry }) => {
- await page.click('text=Go to Nested Route')
+ await clickAndWaitForURL(page, '[data-testid="go-to-nested-route"]', '**/parent/nested')
await flushEvents()
- const viewEvents = intakeRegistry.rumViewEvents
- expect(viewEvents.length).toBeGreaterThan(0)
- const lastView = viewEvents[viewEvents.length - 1]
- expect(lastView.view.name).toBe('/parent/nested')
- expect(lastView.view.url).toContain('/parent/nested')
+
+ const nestedView = intakeRegistry.rumViewEvents.find(
+ (event) => event.view.name === '/parent/nested' && event.view.url?.includes('/parent/nested')
+ )
+ expect(nestedView).toBeDefined()
+ expect(nestedView?.view.url).toContain('/parent/nested')
})
createTest('should define a view name with the actual path for wildcard routes')
.withRum()
.withApp(angularAppName)
.run(async ({ page, flushEvents, intakeRegistry }) => {
- await page.click('text=Go to Wildcard Route')
+ await clickAndWaitForURL(page, '[data-testid="go-to-wildcard"]', '**/unknown/page')
await flushEvents()
- const viewEvents = intakeRegistry.rumViewEvents
- expect(viewEvents.length).toBeGreaterThan(0)
- const lastView = viewEvents[viewEvents.length - 1]
- expect(lastView.view.name).toBe('/unknown/page')
- expect(lastView.view.url).toContain('/unknown/page')
+
+ const wildcardView = intakeRegistry.rumViewEvents.find(
+ (event) => event.view.name === '/unknown/page' && event.view.url?.includes('/unknown/page')
+ )
+ expect(wildcardView).toBeDefined()
+ expect(wildcardView?.view.url).toContain('/unknown/page')
})
createTest('should report errors caught by provideDatadogErrorHandler')
diff --git a/test/e2e/scenario/plugins/basePluginErrorTests.ts b/test/e2e/scenario/plugins/basePluginErrorTests.ts
index 3f709c6b41..644b1c8233 100644
--- a/test/e2e/scenario/plugins/basePluginErrorTests.ts
+++ b/test/e2e/scenario/plugins/basePluginErrorTests.ts
@@ -1,5 +1,6 @@
import { test, expect } from '@playwright/test'
import { createTest } from '../../lib/framework'
+import { clickAndWait, clickAndWaitForURL } from './navigationUtils'
type TestBuilder = ReturnType
@@ -8,6 +9,7 @@ interface ErrorConfig {
expectedFramework: string
expectsBrowserConsoleErrors?: boolean
expectsComponentStack?: boolean
+ errorHandledSelector?: string
}
interface ErrorPluginTestConfig {
@@ -23,11 +25,16 @@ export function runBasePluginErrorTests(configs: ErrorPluginTestConfig[]) {
test.describe('errors', () => {
loadApp(createTest('should report client-side error').withRum()).run(
async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
- 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-handled"]')
+ await clickAndWaitForURL(
+ page,
+ '[data-testid="go-to-error-test"]',
+ `**${viewPrefix}/error-test`,
+ '[data-testid="trigger-error"]'
+ )
+
+ await clickAndWait(page, '[data-testid="trigger-error"]', {
+ readySelector: error.errorHandledSelector ?? '[data-testid="error-handled"]',
+ })
await flushEvents()
diff --git a/test/e2e/scenario/plugins/basePluginRouterTests.ts b/test/e2e/scenario/plugins/basePluginRouterTests.ts
index 4aa8978477..07032e31a6 100644
--- a/test/e2e/scenario/plugins/basePluginRouterTests.ts
+++ b/test/e2e/scenario/plugins/basePluginRouterTests.ts
@@ -1,13 +1,26 @@
+import type { Page } from '@playwright/test'
import { test, expect } from '@playwright/test'
import { createTest } from '../../lib/framework'
+import type { NavigationTarget, UrlPattern } from './navigationUtils'
+import { clickAndWaitForURL, goHome } from './navigationUtils'
type TestBuilder = ReturnType
+interface RouteNavigation extends NavigationTarget {
+ urlPattern: UrlPattern
+}
+
interface RouterConfig {
homeViewName: string
- homeUrlPattern: string | RegExp
+ homeNavigation: RouteNavigation
userRouteName: string
guidesRouteName: string
+ navigation: {
+ guides: RouteNavigation
+ user: RouteNavigation
+ queryChange: RouteNavigation
+ otherUser: RouteNavigation
+ }
}
interface RouterPluginTestConfig {
@@ -17,9 +30,76 @@ interface RouterPluginTestConfig {
router: RouterConfig
}
+interface RouteFixtures {
+ guideSlug: string
+ userId: string
+ otherUserId: string
+}
+
+interface CreateBasePluginRouterConfigParams {
+ homeViewName: string
+ homeUrlPattern: UrlPattern
+ userRouteName: string
+ guidesRouteName: string
+ viewPrefix: string
+ fixtures?: Partial
+}
+
+const DEFAULT_ROUTE_FIXTURES: RouteFixtures = {
+ guideSlug: '123',
+ userId: '42',
+ otherUserId: '999',
+}
+
+export function createBasePluginRouterConfig({
+ homeViewName,
+ homeUrlPattern,
+ userRouteName,
+ guidesRouteName,
+ viewPrefix,
+ fixtures,
+}: CreateBasePluginRouterConfigParams): RouterConfig {
+ const { guideSlug, userId, otherUserId } = { ...DEFAULT_ROUTE_FIXTURES, ...fixtures }
+
+ return {
+ homeViewName,
+ homeNavigation: {
+ clickSelector: '[data-testid="back-to-home"]',
+ urlPattern: homeUrlPattern,
+ readySelector: '[data-testid="go-to-user"]',
+ },
+ userRouteName,
+ guidesRouteName,
+ navigation: {
+ guides: {
+ clickSelector: '[data-testid="go-to-guides"]',
+ urlPattern: `**${viewPrefix}/guides/${guideSlug}`,
+ readySelector: '[data-testid="back-to-home"]',
+ },
+ user: {
+ clickSelector: '[data-testid="go-to-user"]',
+ urlPattern: `**${viewPrefix}/user/${userId}?admin=true`,
+ readySelector: '[data-testid="back-to-home"]',
+ },
+ queryChange: {
+ clickSelector: '[data-testid="change-query-params"]',
+ urlPattern: `**${viewPrefix}/user/${userId}?admin=false`,
+ },
+ otherUser: {
+ clickSelector: '[data-testid="go-to-other-user"]',
+ urlPattern: `**${viewPrefix}/user/${otherUserId}?admin=true`,
+ },
+ },
+ }
+}
+
+async function clickAndWaitForNavigation(page: Page, navigation: RouteNavigation) {
+ await clickAndWaitForURL(page, navigation.clickSelector, navigation.urlPattern, navigation.readySelector)
+}
+
export function runBasePluginRouterTests(configs: RouterPluginTestConfig[]) {
for (const { name, loadApp, viewPrefix, router } of configs) {
- const { homeViewName, homeUrlPattern, userRouteName, guidesRouteName } = router
+ const { homeViewName, homeNavigation, userRouteName, guidesRouteName, navigation } = router
test.describe(`base plugin: ${name}`, () => {
test.describe('router', () => {
@@ -28,9 +108,10 @@ export function runBasePluginRouterTests(configs: RouterPluginTestConfig[]) {
const viewEvents = intakeRegistry.rumViewEvents
expect(viewEvents.length).toBeGreaterThan(0)
- const firstView = viewEvents[0]
- expect(firstView.view.name).toBe(homeViewName)
- expect(firstView.view.loading_type).toBe('initial_load')
+ const initialHomeView = viewEvents.find(
+ (e) => e.view.name === homeViewName && e.view.loading_type === 'initial_load'
+ )
+ expect(initialHomeView).toBeDefined()
})
loadApp(createTest('should normalize dynamic routes and preserve real URLs and referrers').withRum()).run(
@@ -38,17 +119,13 @@ export function runBasePluginRouterTests(configs: RouterPluginTestConfig[]) {
const baseOrigin = new URL(baseUrl).origin
// Home → Guides → Home → User → Home
- await page.click('text=Go to Guides 123')
- await page.waitForURL('**/guides/123')
+ await clickAndWaitForNavigation(page, navigation.guides)
- await page.click('text=Back to Home')
- await page.waitForURL(homeUrlPattern)
+ await goHome(page, homeNavigation)
- await page.click('text=Go to User 42')
- await page.waitForURL('**/user/42?admin=true')
+ await clickAndWaitForNavigation(page, navigation.user)
- await page.click('text=Back to Home')
- await page.waitForURL(homeUrlPattern)
+ await goHome(page, homeNavigation)
await flushEvents()
@@ -74,11 +151,9 @@ export function runBasePluginRouterTests(configs: RouterPluginTestConfig[]) {
loadApp(createTest('should track SPA navigation with loading_time').withRum()).run(
async ({ page, flushEvents, intakeRegistry }) => {
await page.waitForLoadState('networkidle')
- await page.click('text=Go to User 42')
- await page.waitForURL('**/user/42?admin=true')
+ await clickAndWaitForNavigation(page, navigation.user)
- await page.click('text=Back to Home')
- await page.waitForURL(homeUrlPattern)
+ await goHome(page, homeNavigation)
await flushEvents()
@@ -95,14 +170,9 @@ export function runBasePluginRouterTests(configs: RouterPluginTestConfig[]) {
loadApp(createTest('should not create a new view when query params change').withRum()).run(
async ({ page, flushEvents, intakeRegistry }) => {
- await page.click('text=Go to User 42')
- await page.waitForURL('**/user/42?admin=true')
+ await clickAndWaitForNavigation(page, navigation.user)
- await page.click('text=Change query params')
- await page.waitForURL('**/user/42?admin=false')
-
- await page.click('text=Back to Home')
- await page.waitForURL(homeUrlPattern)
+ await clickAndWaitForNavigation(page, navigation.queryChange)
await flushEvents()
@@ -117,14 +187,9 @@ export function runBasePluginRouterTests(configs: RouterPluginTestConfig[]) {
loadApp(
createTest('should track navigations between different concrete URLs of the same dynamic route').withRum()
).run(async ({ page, flushEvents, intakeRegistry }) => {
- await page.click('text=Go to User 42')
- await page.waitForURL('**/user/42?admin=true')
-
- await page.click('text=Go to User 999')
- await page.waitForURL('**/user/999?admin=true')
+ await clickAndWaitForNavigation(page, navigation.user)
- await page.click('text=Back to Home')
- await page.waitForURL(homeUrlPattern)
+ await clickAndWaitForNavigation(page, navigation.otherUser)
await flushEvents()
diff --git a/test/e2e/scenario/plugins/navigationUtils.ts b/test/e2e/scenario/plugins/navigationUtils.ts
new file mode 100644
index 0000000000..80b56c3dba
--- /dev/null
+++ b/test/e2e/scenario/plugins/navigationUtils.ts
@@ -0,0 +1,40 @@
+import type { Page } from '@playwright/test'
+
+export type UrlPattern = string | RegExp
+
+interface ClickAndWaitOptions {
+ urlPattern?: UrlPattern
+ readySelector?: string
+}
+
+export interface NavigationTarget extends ClickAndWaitOptions {
+ clickSelector: string
+}
+
+export async function clickAndWait(
+ page: Page,
+ selector: string,
+ { urlPattern, readySelector }: ClickAndWaitOptions = {}
+) {
+ if (urlPattern !== undefined) {
+ await Promise.all([page.waitForURL(urlPattern), page.click(selector)])
+ } else {
+ await page.click(selector)
+ }
+
+ if (readySelector) {
+ await page.waitForSelector(readySelector)
+ }
+}
+
+export async function navigate(page: Page, navigation: NavigationTarget) {
+ await clickAndWait(page, navigation.clickSelector, navigation)
+}
+
+export async function clickAndWaitForURL(page: Page, selector: string, urlPattern: UrlPattern, readySelector?: string) {
+ await clickAndWait(page, selector, { urlPattern, readySelector })
+}
+
+export async function goHome(page: Page, homeNavigation: NavigationTarget) {
+ await navigate(page, homeNavigation)
+}
diff --git a/test/e2e/scenario/plugins/nextjsPlugin.scenario.ts b/test/e2e/scenario/plugins/nextjsPlugin.scenario.ts
index 9dcd70e1b3..fa251e025b 100644
--- a/test/e2e/scenario/plugins/nextjsPlugin.scenario.ts
+++ b/test/e2e/scenario/plugins/nextjsPlugin.scenario.ts
@@ -1,7 +1,8 @@
import { test, expect } from '@playwright/test'
import { createTest } from '../../lib/framework'
import { runBasePluginErrorTests } from './basePluginErrorTests'
-import { runBasePluginRouterTests } from './basePluginRouterTests'
+import { createBasePluginRouterConfig, runBasePluginRouterTests } from './basePluginRouterTests'
+import { clickAndWaitForURL, goHome } from './navigationUtils'
const nextjsVariants = [
{
@@ -25,12 +26,13 @@ runBasePluginRouterTests(
name,
loadApp: (b: ReturnType) => b.withNextjsApp(routerType),
viewPrefix,
- router: {
+ router: createBasePluginRouterConfig({
homeViewName: viewPrefix || '/',
homeUrlPattern,
userRouteName: '/user/[id]',
guidesRouteName: '/guides/[...slug]',
- },
+ viewPrefix,
+ }),
}))
)
@@ -43,6 +45,7 @@ runBasePluginErrorTests(
clientErrorMessage,
expectedFramework: 'nextjs',
expectsBrowserConsoleErrors: true,
+ errorHandledSelector: '[data-testid="error-handled"][data-error-reported]',
},
}))
)
@@ -55,12 +58,20 @@ test.describe('plugin: nextjs', () => {
await page.waitForSelector('[data-testid="sidebar"]')
expect(await page.textContent('[data-testid="sidebar"]')).toContain('Sidebar: Home')
- await page.click('text=Go to User 42')
- await page.waitForURL('**/user/42?admin=true')
+ await clickAndWaitForURL(
+ page,
+ '[data-testid="go-to-user"]',
+ '**/user/42?admin=true',
+ '[data-testid="change-query-params"]'
+ )
expect(await page.textContent('[data-testid="sidebar"]')).toContain('Sidebar: User 42')
- await page.click('text=Back to Home')
+ await goHome(page, {
+ clickSelector: '[data-testid="back-to-home"]',
+ urlPattern: '**/',
+ readySelector: '[data-testid="go-to-user"]',
+ })
await flushEvents()
@@ -79,8 +90,12 @@ test.describe('plugin: nextjs', () => {
.withRum()
.withNextjsApp('app')
.run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
- await page.click('text=Go to Server Error')
- await page.waitForSelector('[data-testid="error-handled"]')
+ await clickAndWaitForURL(
+ page,
+ '[data-testid="go-to-server-error"]',
+ '**/error-test/server-error?throw=true',
+ '[data-testid="error-handled"][data-error-reported]'
+ )
await flushEvents()
@@ -101,8 +116,12 @@ test.describe('plugin: nextjs', () => {
.withRum()
.withNextjsApp('app')
.run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
- await page.click('text=Go to Global Error')
- await page.waitForSelector('[data-testid="global-error-boundary"]')
+ await clickAndWaitForURL(
+ page,
+ '[data-testid="go-to-global-error"]',
+ '**/global-error-test?throw=true',
+ '[data-testid="global-error-boundary"]'
+ )
await flushEvents()
diff --git a/test/e2e/scenario/plugins/nuxtPlugin.scenario.ts b/test/e2e/scenario/plugins/nuxtPlugin.scenario.ts
index 2fd026a900..30201b65c6 100644
--- a/test/e2e/scenario/plugins/nuxtPlugin.scenario.ts
+++ b/test/e2e/scenario/plugins/nuxtPlugin.scenario.ts
@@ -1,6 +1,6 @@
import { test, expect } from '@playwright/test'
import { createTest } from '../../lib/framework'
-import { runBasePluginRouterTests } from './basePluginRouterTests'
+import { createBasePluginRouterConfig, runBasePluginRouterTests } from './basePluginRouterTests'
const nuxtBasePluginConfig = {
name: 'nuxt',
@@ -11,12 +11,13 @@ const nuxtBasePluginConfig = {
runBasePluginRouterTests([
{
...nuxtBasePluginConfig,
- router: {
+ router: createBasePluginRouterConfig({
homeViewName: '/',
homeUrlPattern: '**/',
userRouteName: '/user/[id]',
guidesRouteName: '/guides/[...slug]',
- },
+ viewPrefix: '',
+ }),
},
])
@@ -25,10 +26,10 @@ test.describe('plugin: nuxt router', () => {
.withRum()
.withNuxtApp()
.run(async ({ page, flushEvents, intakeRegistry }) => {
- await page.click('text=Go to User 42')
+ await page.click('[data-testid="go-to-user"]')
await page.waitForURL('**/user/42?admin=true')
- await page.click('text=Go to Section')
+ await page.click('[data-testid="go-to-section"]')
await page.waitForURL('**/user/42#section')
await flushEvents()
diff --git a/test/e2e/scenario/plugins/reactPlugin.scenario.ts b/test/e2e/scenario/plugins/reactPlugin.scenario.ts
index fcafe3aeea..790c44bc8d 100644
--- a/test/e2e/scenario/plugins/reactPlugin.scenario.ts
+++ b/test/e2e/scenario/plugins/reactPlugin.scenario.ts
@@ -1,7 +1,8 @@
import { test, expect } from '@playwright/test'
import { createTest } from '../../lib/framework'
import { runBasePluginErrorTests } from './basePluginErrorTests'
-import { runBasePluginRouterTests } from './basePluginRouterTests'
+import { createBasePluginRouterConfig, runBasePluginRouterTests } from './basePluginRouterTests'
+import { clickAndWait, clickAndWaitForURL } from './navigationUtils'
const reactApps = [
{ appName: 'react-router-v6-app', description: 'React Router v6' },
@@ -19,12 +20,13 @@ runBasePluginRouterTests(
name,
loadApp,
viewPrefix,
- router: {
+ router: createBasePluginRouterConfig({
homeViewName: '/',
homeUrlPattern: '**/',
userRouteName: '/user/:id',
guidesRouteName: '/guides/:slug',
- },
+ viewPrefix,
+ }),
}))
)
@@ -49,7 +51,7 @@ test.describe('plugin: react', () => {
.withRum()
.withApp(appName)
.run(async ({ flushEvents, intakeRegistry, page }) => {
- await page.click('text=Go to Tracked')
+ await page.click('[data-testid="go-to-tracked"]')
await flushEvents()
const vitalEvents = intakeRegistry.rumVitalEvents[0]
@@ -61,8 +63,12 @@ test.describe('plugin: react', () => {
.withRum()
.withApp(appName)
.run(async ({ page, flushEvents, intakeRegistry }) => {
- await page.click('text=Go to Wildcard')
- await page.waitForURL('**/wildcard/foo/bar')
+ await clickAndWaitForURL(
+ page,
+ '[data-testid="go-to-wildcard"]',
+ '**/wildcard/foo/bar',
+ '[data-testid="back-to-home"]'
+ )
await flushEvents()
@@ -75,10 +81,13 @@ test.describe('plugin: react', () => {
.withRum()
.withApp(appName)
.run(async ({ page, flushEvents, intakeRegistry, withBrowserLogs }) => {
- await page.click('text=Go to Error Test')
- await page.waitForURL('**/error-test')
- await page.click('[data-testid="trigger-error"]')
- await page.waitForSelector('[data-testid="error-handled"]')
+ await clickAndWaitForURL(
+ page,
+ '[data-testid="go-to-error-test"]',
+ '**/error-test',
+ '[data-testid="trigger-error"]'
+ )
+ await clickAndWait(page, '[data-testid="trigger-error"]', { readySelector: '[data-testid="error-handled"]' })
await flushEvents()
diff --git a/test/e2e/scenario/plugins/vuePlugin.scenario.ts b/test/e2e/scenario/plugins/vuePlugin.scenario.ts
index b2ce0aec7e..11e1e66388 100644
--- a/test/e2e/scenario/plugins/vuePlugin.scenario.ts
+++ b/test/e2e/scenario/plugins/vuePlugin.scenario.ts
@@ -1,7 +1,8 @@
import { test, expect } from '@playwright/test'
import { createTest } from '../../lib/framework'
import { runBasePluginErrorTests } from './basePluginErrorTests'
-import { runBasePluginRouterTests } from './basePluginRouterTests'
+import { createBasePluginRouterConfig, runBasePluginRouterTests } from './basePluginRouterTests'
+import { clickAndWait, clickAndWaitForURL } from './navigationUtils'
const vueBasePluginConfig = {
name: 'vue',
@@ -12,12 +13,13 @@ const vueBasePluginConfig = {
runBasePluginRouterTests([
{
...vueBasePluginConfig,
- router: {
+ router: createBasePluginRouterConfig({
homeViewName: '/',
homeUrlPattern: '**/',
userRouteName: '/user/:id',
guidesRouteName: '/guides/:catchAll(.*)*',
- },
+ viewPrefix: '',
+ }),
},
])
@@ -37,8 +39,13 @@ test.describe('plugin: vue', () => {
.withRum()
.withVueApp()
.run(async ({ page, flushEvents, intakeRegistry }) => {
- await page.click('text=Go to Error Test')
- await page.click('[data-testid="trigger-error"]')
+ await clickAndWaitForURL(
+ page,
+ '[data-testid="go-to-error-test"]',
+ '**/error-test',
+ '[data-testid="trigger-error"]'
+ )
+ await clickAndWait(page, '[data-testid="trigger-error"]', { readySelector: '[data-testid="error-handled"]' })
await flushEvents()