-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react): React Router v7 support (library) (#14513)
- Loading branch information
Showing
22 changed files
with
1,018 additions
and
399 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
dev-packages/e2e-tests/test-applications/react-router-7-spa/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
/test-results/ | ||
/playwright-report/ | ||
/playwright/.cache/ | ||
|
||
!*.d.ts |
2 changes: 2 additions & 0 deletions
2
dev-packages/e2e-tests/test-applications/react-router-7-spa/.npmrc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
@sentry:registry=http://127.0.0.1:4873 | ||
@sentry-internal:registry=http://127.0.0.1:4873 |
13 changes: 13 additions & 0 deletions
13
dev-packages/e2e-tests/test-applications/react-router-7-spa/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite + React + TS</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
60 changes: 60 additions & 0 deletions
60
dev-packages/e2e-tests/test-applications/react-router-7-spa/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
{ | ||
"name": "react-router-7-spa", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"@sentry/react": "latest || *", | ||
"@types/react": "18.3.1", | ||
"@types/react-dom": "18.3.1", | ||
"react": "18.3.1", | ||
"react-dom": "18.3.1", | ||
"react-router": "^7.0.1" | ||
}, | ||
"devDependencies": { | ||
"@playwright/test": "^1.44.1", | ||
"@sentry-internal/test-utils": "link:../../../test-utils", | ||
"vite": "^6.0.1", | ||
"@vitejs/plugin-react": "^4.3.4", | ||
"typescript": "4.9.5" | ||
}, | ||
"scripts": { | ||
"build": "vite build", | ||
"dev": "vite", | ||
"preview": "vite preview", | ||
"test": "playwright test", | ||
"clean": "npx rimraf node_modules pnpm-lock.yaml", | ||
"test:build": "pnpm install && npx playwright install && pnpm build", | ||
"test:build-ts3.8": "pnpm install && pnpm add [email protected] && npx playwright install && pnpm build", | ||
"test:build-canary": "pnpm install && pnpm add react@canary react-dom@canary && npx playwright install && pnpm build", | ||
"test:assert": "pnpm test" | ||
}, | ||
"eslintConfig": { | ||
"extends": [ | ||
"react-app", | ||
"react-app/jest" | ||
] | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
}, | ||
"volta": { | ||
"extends": "../../package.json" | ||
}, | ||
"sentryTest": { | ||
"variants": [ | ||
{ | ||
"build-command": "test:build-ts3.8", | ||
"label": "react-router-7-spa (TS 3.8)" | ||
} | ||
] | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
dev-packages/e2e-tests/test-applications/react-router-7-spa/playwright.config.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { getPlaywrightConfig } from '@sentry-internal/test-utils'; | ||
|
||
const config = getPlaywrightConfig({ | ||
startCommand: `pnpm preview --port 3030`, | ||
port: 3030, | ||
}); | ||
|
||
export default config; |
5 changes: 5 additions & 0 deletions
5
dev-packages/e2e-tests/test-applications/react-router-7-spa/src/globals.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
interface Window { | ||
recordedTransactions?: string[]; | ||
capturedExceptionId?: string; | ||
sentryReplayId?: string; | ||
} |
55 changes: 55 additions & 0 deletions
55
dev-packages/e2e-tests/test-applications/react-router-7-spa/src/main.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import * as Sentry from '@sentry/react'; | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom/client'; | ||
import { | ||
BrowserRouter, | ||
Route, | ||
Routes, | ||
createRoutesFromChildren, | ||
matchRoutes, | ||
useLocation, | ||
useNavigationType, | ||
} from 'react-router'; | ||
import Index from './pages/Index'; | ||
import SSE from './pages/SSE'; | ||
import User from './pages/User'; | ||
|
||
const replay = Sentry.replayIntegration(); | ||
|
||
Sentry.init({ | ||
environment: 'qa', // dynamic sampling bias to keep transactions | ||
dsn: import.meta.env.PUBLIC_E2E_TEST_DSN, | ||
integrations: [ | ||
Sentry.reactRouterV7BrowserTracingIntegration({ | ||
useEffect: React.useEffect, | ||
useLocation, | ||
useNavigationType, | ||
createRoutesFromChildren, | ||
matchRoutes, | ||
trackFetchStreamPerformance: true, | ||
}), | ||
replay, | ||
], | ||
// We recommend adjusting this value in production, or using tracesSampler | ||
// for finer control | ||
tracesSampleRate: 1.0, | ||
release: 'e2e-test', | ||
|
||
// Always capture replays, so we can test this properly | ||
replaysSessionSampleRate: 1.0, | ||
replaysOnErrorSampleRate: 0.0, | ||
tunnel: 'http://localhost:3031', | ||
}); | ||
|
||
const SentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes); | ||
|
||
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); | ||
root.render( | ||
<BrowserRouter> | ||
<SentryRoutes> | ||
<Route path="/" element={<Index />} /> | ||
<Route path="/user/:id" element={<User />} /> | ||
<Route path="/sse" element={<SSE />} /> | ||
</SentryRoutes> | ||
</BrowserRouter>, | ||
); |
23 changes: 23 additions & 0 deletions
23
dev-packages/e2e-tests/test-applications/react-router-7-spa/src/pages/Index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// biome-ignore lint/nursery/noUnusedImports: Need React import for JSX | ||
import * as React from 'react'; | ||
import { Link } from 'react-router'; | ||
|
||
const Index = () => { | ||
return ( | ||
<> | ||
<input | ||
type="button" | ||
value="Capture Exception" | ||
id="exception-button" | ||
onClick={() => { | ||
throw new Error('I am an error!'); | ||
}} | ||
/> | ||
<Link to="/user/5" id="navigation"> | ||
navigate | ||
</Link> | ||
</> | ||
); | ||
}; | ||
|
||
export default Index; |
59 changes: 59 additions & 0 deletions
59
dev-packages/e2e-tests/test-applications/react-router-7-spa/src/pages/SSE.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import * as Sentry from '@sentry/react'; | ||
// biome-ignore lint/nursery/noUnusedImports: Need React import for JSX | ||
import * as React from 'react'; | ||
|
||
const fetchSSE = async ({ timeout, abort = false }: { timeout: boolean; abort?: boolean }) => { | ||
Sentry.startSpanManual({ name: 'sse stream using fetch' }, async span => { | ||
const controller = new AbortController(); | ||
|
||
const res = await Sentry.startSpan({ name: 'sse fetch call' }, async () => { | ||
const endpoint = `http://localhost:8080/${timeout ? 'sse-timeout' : 'sse'}`; | ||
|
||
const signal = controller.signal; | ||
return await fetch(endpoint, { signal }); | ||
}); | ||
|
||
const stream = res.body; | ||
const reader = stream?.getReader(); | ||
|
||
const readChunk = async () => { | ||
if (abort) { | ||
controller.abort(); | ||
} | ||
const readRes = await reader?.read(); | ||
if (readRes?.done) { | ||
return; | ||
} | ||
|
||
new TextDecoder().decode(readRes?.value); | ||
|
||
await readChunk(); | ||
}; | ||
|
||
try { | ||
await readChunk(); | ||
} catch (error) { | ||
console.error('Could not fetch sse', error); | ||
} | ||
|
||
span.end(); | ||
}); | ||
}; | ||
|
||
const SSE = () => { | ||
return ( | ||
<> | ||
<button id="fetch-button" onClick={() => fetchSSE({ timeout: false })}> | ||
Fetch SSE | ||
</button> | ||
<button id="fetch-timeout-button" onClick={() => fetchSSE({ timeout: true })}> | ||
Fetch timeout SSE | ||
</button> | ||
<button id="fetch-sse-abort" onClick={() => fetchSSE({ timeout: false, abort: true })}> | ||
Fetch SSE with error | ||
</button> | ||
</> | ||
); | ||
}; | ||
|
||
export default SSE; |
8 changes: 8 additions & 0 deletions
8
dev-packages/e2e-tests/test-applications/react-router-7-spa/src/pages/User.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// biome-ignore lint/nursery/noUnusedImports: Need React import for JSX | ||
import * as React from 'react'; | ||
|
||
const User = () => { | ||
return <p>I am a blank page :)</p>; | ||
}; | ||
|
||
export default User; |
6 changes: 6 additions & 0 deletions
6
dev-packages/e2e-tests/test-applications/react-router-7-spa/start-event-proxy.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { startEventProxyServer } from '@sentry-internal/test-utils'; | ||
|
||
startEventProxyServer({ | ||
port: 3031, | ||
proxyServerName: 'react-router-7-spa', | ||
}); |
59 changes: 59 additions & 0 deletions
59
dev-packages/e2e-tests/test-applications/react-router-7-spa/tests/errors.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { expect, test } from '@playwright/test'; | ||
import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; | ||
|
||
test('Sends correct error event', async ({ page, baseURL }) => { | ||
const errorEventPromise = waitForError('react-router-7-spa', event => { | ||
return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; | ||
}); | ||
|
||
await page.goto('/'); | ||
|
||
const exceptionButton = page.locator('id=exception-button'); | ||
await exceptionButton.click(); | ||
|
||
const errorEvent = await errorEventPromise; | ||
|
||
expect(errorEvent.exception?.values).toHaveLength(1); | ||
expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); | ||
|
||
expect(errorEvent.request).toEqual({ | ||
headers: expect.any(Object), | ||
url: 'http://localhost:3030/', | ||
}); | ||
|
||
expect(errorEvent.transaction).toEqual('/'); | ||
|
||
expect(errorEvent.contexts?.trace).toEqual({ | ||
trace_id: expect.any(String), | ||
span_id: expect.any(String), | ||
}); | ||
}); | ||
|
||
test('Sets correct transactionName', async ({ page }) => { | ||
const transactionPromise = waitForTransaction('react-router-7-spa', async transactionEvent => { | ||
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; | ||
}); | ||
|
||
const errorEventPromise = waitForError('react-router-7-spa', event => { | ||
return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; | ||
}); | ||
|
||
await page.goto('/'); | ||
const transactionEvent = await transactionPromise; | ||
|
||
// Only capture error once transaction was sent | ||
const exceptionButton = page.locator('id=exception-button'); | ||
await exceptionButton.click(); | ||
|
||
const errorEvent = await errorEventPromise; | ||
|
||
expect(errorEvent.exception?.values).toHaveLength(1); | ||
expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); | ||
|
||
expect(errorEvent.transaction).toEqual('/'); | ||
|
||
expect(errorEvent.contexts?.trace).toEqual({ | ||
trace_id: transactionEvent.contexts?.trace?.trace_id, | ||
span_id: expect.not.stringContaining(transactionEvent.contexts?.trace?.span_id || ''), | ||
}); | ||
}); |
Oops, something went wrong.