diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json b/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json
index 3dea78b20080..0e108f6fa56e 100644
--- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json
+++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json
@@ -15,6 +15,7 @@
},
"scripts": {
"build": "react-scripts build",
+ "dev": "react-scripts start",
"start": "serve -s build",
"test": "playwright test",
"clean": "npx rimraf node_modules pnpm-lock.yaml",
diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx
index 2ad9490ccd57..f8612e225eb7 100644
--- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx
+++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx
@@ -11,6 +11,11 @@ import {
} from 'react-router-dom';
import Index from './pages/Index';
import User from './pages/User';
+import Group from './pages/Group';
+import Post from './pages/Post';
+import PostFeatured from './pages/PostFeatured';
+import PostRelated from './pages/PostRelated';
+import PostIndex from './pages/PostIndex';
const replay = Sentry.replayIntegration();
@@ -52,8 +57,29 @@ const router = sentryCreateHashRouter([
path: '/user/:id',
element:
Group page
; +}; + +export default Group; diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/Index.tsx b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/Index.tsx index 1000dd53df27..ac877db7b812 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/Index.tsx +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/Index.tsx @@ -15,6 +15,21 @@ const Index = () => { navigate + + Post 1 + + + Post 1 featured + + + Post 1 related + + + Group 1 + + + Group 1 user 5 + > ); }; diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/Post.tsx b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/Post.tsx new file mode 100644 index 000000000000..9b844b17ff68 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/Post.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; +import { Outlet } from 'react-router-dom'; + +const Post = () => { + return ( + <> +Post V2 page
+Post featured page
; +}; + +export default PostFeatured; diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/PostIndex.tsx b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/PostIndex.tsx new file mode 100644 index 000000000000..ad3efaa9216a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/PostIndex.tsx @@ -0,0 +1,7 @@ +import * as React from 'react'; + +const PostIndex = () => { + returnPost index page
; +}; + +export default PostIndex; diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/PostRelated.tsx b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/PostRelated.tsx new file mode 100644 index 000000000000..ff8d05f6f6f9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/pages/PostRelated.tsx @@ -0,0 +1,7 @@ +import * as React from 'react'; + +const PostRelated = () => { + returnPost related page
; +}; + +export default PostRelated; diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts index 920506838080..bfc07adcc4eb 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts @@ -14,9 +14,9 @@ test('Captures a pageload transaction', async ({ page }) => { deviceMemory: expect.any(String), effectiveConnectionType: expect.any(String), hardwareConcurrency: expect.any(String), - 'lcp.element': 'body > div#root > input#exception-button[type="button"]', - 'lcp.id': 'exception-button', - 'lcp.size': 1650, + 'lcp.element': expect.any(String), + 'lcp.id': expect.any(String), + 'lcp.size': expect.any(Number), 'sentry.idle_span_finish_reason': 'idleTimeout', 'sentry.op': 'pageload', 'sentry.origin': 'auto.pageload.react.reactrouter_v6', @@ -150,3 +150,213 @@ test('Captures a navigation transaction', async ({ page }) => { expect(transactionEvent.spans).toEqual([]); }); + +test('Captures a parameterized path pageload transaction', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'pageload'; + }); + + await page.goto('/#/v2/post/1'); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/v2/post/:post', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path pageload transaction for nested route', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'pageload'; + }); + + await page.goto('/#/v2/post/1/featured'); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/v2/post/:post/featured', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path pageload transaction for nested route with absolute path', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'pageload'; + }); + + await page.goto('/#/v2/post/1/related'); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/v2/post/:post/related', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path navigation transaction', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'navigation'; + }); + + await page.goto('/'); + const linkElement = page.locator('id=navigation-post-1'); + await linkElement.click(); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/v2/post/:post', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path navigation transaction for nested route', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'navigation'; + }); + + await page.goto('/'); + const linkElement = page.locator('id=navigation-post-1-featured'); + await linkElement.click(); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/v2/post/:post/featured', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path navigation transaction for nested route with absolute path', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'navigation'; + }); + + await page.goto('/'); + const linkElement = page.locator('id=navigation-post-1-related'); + await linkElement.click(); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/v2/post/:post/related', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path pageload transaction for group route', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'pageload'; + }); + + await page.goto('/#/group/1'); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/group/:group/:user?', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path navigation transaction for group route', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'navigation'; + }); + + await page.goto('/'); + const linkElement = page.locator('id=navigation-group-1'); + await linkElement.click(); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/group/:group/:user?', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path pageload transaction for nested group route', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'pageload'; + }); + + await page.goto('/#/group/1/5'); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/group/:group/:user?', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +}); + +test('Captures a parameterized path navigation transaction for nested group route', async ({ page }) => { + const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { + return event.contexts?.trace?.op === 'navigation'; + }); + + await page.goto('/'); + const linkElement = page.locator('id=navigation-group-1-user-5'); + await linkElement.click(); + + const transactionEvent = await transactionEventPromise; + + expect(transactionEvent).toEqual( + expect.objectContaining({ + transaction: '/group/:group/:user?', + type: 'transaction', + transaction_info: { + source: 'route', + }, + }), + ); +});