Skip to content

Commit

Permalink
test: e2e test for sentry integration (#3291)
Browse files Browse the repository at this point in the history
* test: e2e test for sentry integration

* fix: use the fixed sentry integration

* feat: make sure we have no console errors

* chore: turn off actually sending events to sentry

this avoids a browser log error, which we check for in the test
  • Loading branch information
TkDodo authored Jan 31, 2025
1 parent d50d291 commit c5b3f54
Show file tree
Hide file tree
Showing 13 changed files with 651 additions and 19 deletions.
10 changes: 10 additions & 0 deletions e2e/react-router/sentry-integration/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules
.DS_Store
dist
dist-ssr
*.local

/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
12 changes: 12 additions & 0 deletions e2e/react-router/sentry-integration/index.html
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>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
33 changes: 33 additions & 0 deletions e2e/react-router/sentry-integration/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "tanstack-router-e2e-sentry-integration",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port 3000",
"dev:e2e": "vite",
"build": "vite build && tsc --noEmit",
"serve": "vite preview",
"start": "vite",
"test:e2e": "playwright test --project=chromium"
},
"dependencies": {
"@sentry/react": "^8.53.0",
"@sentry/tracing": "^7.120.3",
"@sentry/vite-plugin": "^3.1.1",
"@tanstack/react-router": "workspace:^",
"@tanstack/router-devtools": "workspace:^",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"redaxios": "^0.5.1",
"postcss": "^8.5.1",
"autoprefixer": "^10.4.20",
"tailwindcss": "^3.4.17"
},
"devDependencies": {
"@playwright/test": "^1.50.0",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"@vitejs/plugin-react": "^4.3.4",
"vite": "^6.0.11"
}
}
34 changes: 34 additions & 0 deletions e2e/react-router/sentry-integration/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { defineConfig, devices } from '@playwright/test'
import { derivePort } from '../../utils.js'
import packageJson from './package.json' with { type: 'json' }

const PORT = derivePort(packageJson.name)
const baseURL = `http://localhost:${PORT}`
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
workers: 1,

reporter: [['line']],

use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL,
},

webServer: {
command: `VITE_SERVER_PORT=${PORT} pnpm build && VITE_SERVER_PORT=${PORT} pnpm start --port ${PORT}`,
url: baseURL,
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
},

projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})
6 changes: 6 additions & 0 deletions e2e/react-router/sentry-integration/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
92 changes: 92 additions & 0 deletions e2e/react-router/sentry-integration/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import ReactDOM from 'react-dom/client'
import * as Sentry from '@sentry/react'
import {
Link,
Outlet,
RouterProvider,
createRootRoute,
createRoute,
createRouter,
} from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
import './styles.css'

const rootRoute = createRootRoute({
component: RootComponent,
notFoundComponent: () => {
return (
<div>
<p>This is the notFoundComponent configured on root route</p>
<Link to="/">Start Over</Link>
</div>
)
},
})

function RootComponent() {
return (
<>
<div className="p-2 flex gap-2 text-lg border-b">
<Link
to="/"
activeProps={{
className: 'font-bold',
}}
activeOptions={{ exact: true }}
>
Home
</Link>
</div>
<Outlet />
<TanStackRouterDevtools position="bottom-right" />
</>
)
}
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: IndexComponent,
})

function IndexComponent() {
return (
<div className="p-2">
<h3>Welcome Home!</h3>
</div>
)
}

const routeTree = rootRoute.addChildren([indexRoute])

// Set up a Router instance
const router = createRouter({
routeTree,
defaultPreload: 'intent',
defaultStaleTime: 5000,
})

// Register things for typesafety
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}

Sentry.init({
dsn: 'https://[email protected]/0',
integrations: [Sentry.tanstackRouterBrowserTracingIntegration(router)],
transport: () => ({
send: (): Promise<any> => Promise.resolve(),
flush: () => Promise.resolve(true),
}),
tracesSampleRate: 0.2,
sendClientReports: false,
})

const rootElement = document.getElementById('app')!

if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)

root.render(<RouterProvider router={router} />)
}
13 changes: 13 additions & 0 deletions e2e/react-router/sentry-integration/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

html {
color-scheme: light dark;
}
* {
@apply border-gray-200 dark:border-gray-800;
}
body {
@apply bg-gray-50 text-gray-950 dark:bg-gray-900 dark:text-gray-200;
}
4 changes: 4 additions & 0 deletions e2e/react-router/sentry-integration/tailwind.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{js,jsx,ts,tsx}', './index.html'],
}
11 changes: 11 additions & 0 deletions e2e/react-router/sentry-integration/tests/app.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { expect } from '@playwright/test'

import { test } from './fixture'

test.beforeEach(async ({ page }) => {
await page.goto('/')
})

test('should load', async ({ page }) => {
await expect(page.getByRole('heading')).toContainText('Welcome Home!')
})
28 changes: 28 additions & 0 deletions e2e/react-router/sentry-integration/tests/fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { test as base, expect } from '@playwright/test'

export interface TestFixtureOptions {
whitelistErrors: Array<RegExp | string>
}
export const test = base.extend<TestFixtureOptions>({
whitelistErrors: [[], { option: true }],
page: async ({ page, whitelistErrors }, use) => {
const errorMessages: Array<string> = []
page.on('console', (m) => {
if (m.type() === 'error') {
const text = m.text()
for (const whitelistError of whitelistErrors) {
if (
(typeof whitelistError === 'string' &&
text.includes(whitelistError)) ||
(whitelistError instanceof RegExp && whitelistError.test(text))
) {
return
}
}
errorMessages.push(text)
}
})
await use(page)
expect(errorMessages).toEqual([])
},
})
14 changes: 14 additions & 0 deletions e2e/react-router/sentry-integration/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"target": "ESNext",
"moduleResolution": "Bundler",
"module": "ESNext",
"resolveJsonModule": true,
"allowJs": true,
"skipLibCheck": true
},
"exclude": ["node_modules", "dist"]
}
8 changes: 8 additions & 0 deletions e2e/react-router/sentry-integration/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { sentryVitePlugin } from '@sentry/vite-plugin'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), sentryVitePlugin()],
})
Loading

0 comments on commit c5b3f54

Please sign in to comment.