-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react): Add TanStack Router integration (#12095)
Co-authored-by: Luca Forstner <luca.forstner@sentry.io>
- Loading branch information
Showing
16 changed files
with
1,458 additions
and
0 deletions.
There are no files selected for viewing
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
24 changes: 24 additions & 0 deletions
24
dev-packages/e2e-tests/test-applications/tanstack-router/.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,24 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
2 changes: 2 additions & 0 deletions
2
dev-packages/e2e-tests/test-applications/tanstack-router/.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 |
12 changes: 12 additions & 0 deletions
12
dev-packages/e2e-tests/test-applications/tanstack-router/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,12 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Tanstack Example</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
34 changes: 34 additions & 0 deletions
34
dev-packages/e2e-tests/test-applications/tanstack-router/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,34 @@ | ||
{ | ||
"name": "tanstack-router-e2e-test-application", | ||
"private": true, | ||
"version": "0.0.1", | ||
"type": "module", | ||
"scripts": { | ||
"build": "vite build", | ||
"start": "vite preview", | ||
"test": "playwright test", | ||
"clean": "npx rimraf node_modules pnpm-lock.yaml", | ||
"test:build": "pnpm install && npx playwright install && pnpm build", | ||
"test:assert": "pnpm test" | ||
}, | ||
"dependencies": { | ||
"@sentry/react": "latest || *", | ||
"@tanstack/react-router": "1.34.5", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "^18.2.66", | ||
"@types/react-dom": "^18.2.22", | ||
"@typescript-eslint/eslint-plugin": "^7.2.0", | ||
"@typescript-eslint/parser": "^7.2.0", | ||
"@vitejs/plugin-react-swc": "^3.5.0", | ||
"typescript": "^5.2.2", | ||
"vite": "^5.2.0", | ||
"@playwright/test": "^1.41.1", | ||
"@sentry-internal/event-proxy-server": "link:../../../event-proxy-server" | ||
}, | ||
"volta": { | ||
"extends": "../../package.json" | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.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,66 @@ | ||
import type { PlaywrightTestConfig } from '@playwright/test'; | ||
import { devices } from '@playwright/test'; | ||
|
||
const appPort = 3030; | ||
const eventProxyPort = 3031; | ||
|
||
/** | ||
* See https://playwright.dev/docs/test-configuration. | ||
*/ | ||
const config: PlaywrightTestConfig = { | ||
testDir: './tests', | ||
/* Maximum time one test can run for. */ | ||
timeout: 150_000, | ||
expect: { | ||
/** | ||
* Maximum time expect() should wait for the condition to be met. | ||
* For example in `await expect(locator).toHaveText();` | ||
*/ | ||
timeout: 5000, | ||
}, | ||
/* Run tests in files in parallel */ | ||
fullyParallel: true, | ||
/* Fail the build on CI if you accidentally left test.only in the source code. */ | ||
forbidOnly: !!process.env.CI, | ||
/* Retry on CI only */ | ||
retries: 0, | ||
/* Opt out of parallel tests on CI. */ | ||
workers: 1, | ||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */ | ||
reporter: 'list', | ||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ | ||
use: { | ||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ | ||
actionTimeout: 0, | ||
|
||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ | ||
trace: 'on-first-retry', | ||
|
||
baseURL: `http://localhost:${appPort}`, | ||
}, | ||
|
||
/* Configure projects for major browsers */ | ||
projects: [ | ||
{ | ||
name: 'chromium', | ||
use: { | ||
...devices['Desktop Chrome'], | ||
}, | ||
}, | ||
], | ||
|
||
/* Run your local dev server before starting the tests */ | ||
|
||
webServer: [ | ||
{ | ||
command: 'node start-event-proxy.mjs', | ||
port: eventProxyPort, | ||
}, | ||
{ | ||
command: 'pnpm start', | ||
port: appPort, | ||
}, | ||
], | ||
}; | ||
|
||
export default config; |
99 changes: 99 additions & 0 deletions
99
dev-packages/e2e-tests/test-applications/tanstack-router/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,99 @@ | ||
import * as Sentry from '@sentry/react'; | ||
import { Link, Outlet, RouterProvider, createRootRoute, createRoute, createRouter } from '@tanstack/react-router'; | ||
import { StrictMode } from 'react'; | ||
import ReactDOM from 'react-dom/client'; | ||
|
||
const rootRoute = createRootRoute({ | ||
component: () => ( | ||
<> | ||
<ul> | ||
<li> | ||
<Link to="/">Home</Link> | ||
</li> | ||
<li> | ||
<Link to="/posts/$postId" params={{ postId: '1' }}> | ||
Post 1 | ||
</Link> | ||
</li> | ||
<li> | ||
<Link to="/posts/$postId" params={{ postId: '2' }} id="nav-link"> | ||
Post 2 | ||
</Link> | ||
</li> | ||
</ul> | ||
<hr /> | ||
<Outlet /> | ||
</> | ||
), | ||
}); | ||
|
||
const indexRoute = createRoute({ | ||
getParentRoute: () => rootRoute, | ||
path: '/', | ||
component: function Index() { | ||
return ( | ||
<div> | ||
<h3>Welcome Home!</h3> | ||
</div> | ||
); | ||
}, | ||
}); | ||
|
||
const postsRoute = createRoute({ | ||
getParentRoute: () => rootRoute, | ||
path: 'posts/', | ||
}); | ||
|
||
const postIdRoute = createRoute({ | ||
getParentRoute: () => postsRoute, | ||
path: '$postId', | ||
shouldReload() { | ||
return true; | ||
}, | ||
loader: ({ params }) => { | ||
return Sentry.startSpan({ name: `loading-post-${params.postId}` }, async () => { | ||
await new Promise(resolve => setTimeout(resolve, 1000)); | ||
}); | ||
}, | ||
component: function Post() { | ||
const { postId } = postIdRoute.useParams(); | ||
return <div>Post ID: {postId}</div>; | ||
}, | ||
}); | ||
|
||
const routeTree = rootRoute.addChildren([indexRoute, postsRoute.addChildren([postIdRoute])]); | ||
|
||
const router = createRouter({ routeTree }); | ||
|
||
declare const __APP_DSN__: string; | ||
|
||
Sentry.init({ | ||
environment: 'qa', // dynamic sampling bias to keep transactions | ||
dsn: __APP_DSN__, | ||
integrations: [Sentry.tanstackRouterBrowserTracingIntegration(router)], | ||
// We recommend adjusting this value in production, or using tracesSampler | ||
// for finer control | ||
tracesSampleRate: 1.0, | ||
release: 'e2e-test', | ||
tunnel: 'http://localhost:3031/', // proxy server | ||
|
||
// Always capture replays, so we can test this properly | ||
replaysSessionSampleRate: 1.0, | ||
replaysOnErrorSampleRate: 0.0, | ||
}); | ||
|
||
declare module '@tanstack/react-router' { | ||
interface Register { | ||
router: typeof router; | ||
} | ||
} | ||
|
||
const rootElement = document.getElementById('root')!; | ||
if (!rootElement.innerHTML) { | ||
const root = ReactDOM.createRoot(rootElement); | ||
root.render( | ||
<StrictMode> | ||
<RouterProvider router={router} /> | ||
</StrictMode>, | ||
); | ||
} |
6 changes: 6 additions & 0 deletions
6
dev-packages/e2e-tests/test-applications/tanstack-router/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/event-proxy-server'; | ||
|
||
startEventProxyServer({ | ||
port: 3031, | ||
proxyServerName: 'tanstack-router', | ||
}); |
78 changes: 78 additions & 0 deletions
78
...ackages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.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,78 @@ | ||
import { expect, test } from '@playwright/test'; | ||
import { waitForTransaction } from '@sentry-internal/event-proxy-server'; | ||
|
||
test('sends a pageload transaction with a parameterized URL', async ({ page }) => { | ||
const transactionPromise = waitForTransaction('tanstack-router', async transactionEvent => { | ||
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; | ||
}); | ||
|
||
await page.goto(`/posts/456`); | ||
|
||
const rootSpan = await transactionPromise; | ||
|
||
expect(rootSpan).toMatchObject({ | ||
contexts: { | ||
trace: { | ||
data: { | ||
'sentry.source': 'route', | ||
'sentry.origin': 'auto.pageload.react.tanstack_router', | ||
'sentry.op': 'pageload', | ||
'url.path.params.postId': '456', | ||
}, | ||
op: 'pageload', | ||
origin: 'auto.pageload.react.tanstack_router', | ||
}, | ||
}, | ||
transaction: '/posts/$postId', | ||
transaction_info: { | ||
source: 'route', | ||
}, | ||
spans: expect.arrayContaining([ | ||
expect.objectContaining({ | ||
description: 'loading-post-456', | ||
}), | ||
]), | ||
}); | ||
}); | ||
|
||
test('sends a navigation transaction with a parameterized URL', async ({ page }) => { | ||
const pageloadTxnPromise = waitForTransaction('tanstack-router', async transactionEvent => { | ||
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; | ||
}); | ||
|
||
const navigationTxnPromise = waitForTransaction('tanstack-router', async transactionEvent => { | ||
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; | ||
}); | ||
|
||
await page.goto(`/`); | ||
await pageloadTxnPromise; | ||
|
||
await page.waitForTimeout(5000); | ||
await page.locator('#nav-link').click(); | ||
|
||
const navigationTxn = await navigationTxnPromise; | ||
|
||
expect(navigationTxn).toMatchObject({ | ||
contexts: { | ||
trace: { | ||
data: { | ||
'sentry.source': 'route', | ||
'sentry.origin': 'auto.navigation.react.tanstack_router', | ||
'sentry.op': 'navigation', | ||
'url.path.params.postId': '2', | ||
}, | ||
op: 'navigation', | ||
origin: 'auto.navigation.react.tanstack_router', | ||
}, | ||
}, | ||
transaction: '/posts/$postId', | ||
transaction_info: { | ||
source: 'route', | ||
}, | ||
spans: expect.arrayContaining([ | ||
expect.objectContaining({ | ||
description: 'loading-post-2', | ||
}), | ||
]), | ||
}); | ||
}); |
25 changes: 25 additions & 0 deletions
25
dev-packages/e2e-tests/test-applications/tanstack-router/tsconfig.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,25 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "ES2020", | ||
"useDefineForClassFields": true, | ||
"lib": ["ES2020", "DOM", "DOM.Iterable"], | ||
"module": "ESNext", | ||
"skipLibCheck": true, | ||
|
||
/* Bundler mode */ | ||
"moduleResolution": "bundler", | ||
"allowImportingTsExtensions": true, | ||
"resolveJsonModule": true, | ||
"isolatedModules": true, | ||
"noEmit": true, | ||
"jsx": "react-jsx", | ||
|
||
/* Linting */ | ||
"strict": true, | ||
"noUnusedLocals": true, | ||
"noUnusedParameters": true, | ||
"noFallthroughCasesInSwitch": true | ||
}, | ||
"include": ["src"], | ||
"references": [{ "path": "./tsconfig.node.json" }] | ||
} |
11 changes: 11 additions & 0 deletions
11
dev-packages/e2e-tests/test-applications/tanstack-router/tsconfig.node.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,11 @@ | ||
{ | ||
"compilerOptions": { | ||
"composite": true, | ||
"skipLibCheck": true, | ||
"module": "ESNext", | ||
"moduleResolution": "bundler", | ||
"allowSyntheticDefaultImports": true, | ||
"strict": true | ||
}, | ||
"include": ["vite.config.ts"] | ||
} |
13 changes: 13 additions & 0 deletions
13
dev-packages/e2e-tests/test-applications/tanstack-router/vite.config.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,13 @@ | ||
import react from '@vitejs/plugin-react-swc'; | ||
import { defineConfig } from 'vite'; | ||
|
||
// https://vitejs.dev/config/ | ||
export default defineConfig({ | ||
plugins: [react()], | ||
define: { | ||
__APP_DSN__: JSON.stringify(process.env.E2E_TEST_DSN), | ||
}, | ||
preview: { | ||
port: 3030, | ||
}, | ||
}); |
Oops, something went wrong.