From 480c145c905d602b3c335ca0ef12d07e0d7e91cd Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Mon, 1 Dec 2025 15:05:06 +0100 Subject: [PATCH 01/12] set up basic e2e test app --- .../tanstackstart-react/.gitignore | 24 ++++++++++ .../tanstackstart-react/.npmrc | 2 + .../tanstackstart-react/package.json | 37 +++++++++++++++ .../tanstackstart-react/playwright.config.mjs | 8 ++++ .../tanstackstart-react/src/router.tsx | 11 +++++ .../tanstackstart-react/src/routes/__root.tsx | 47 +++++++++++++++++++ .../tanstackstart-react/src/routes/index.tsx | 11 +++++ .../tanstackstart-react/start-event-proxy.mjs | 6 +++ .../tanstackstart-react/tests/errors.test.ts | 9 ++++ .../tanstackstart-react/tsconfig.json | 26 ++++++++++ .../tanstackstart-react/tsconfig.node.json | 11 +++++ .../tanstackstart-react/vite.config.ts | 19 ++++++++ 12 files changed, 211 insertions(+) create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/.gitignore create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/.npmrc create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.json create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.node.json create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/.gitignore b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.gitignore new file mode 100644 index 000000000000..a547bf36d8d1 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.gitignore @@ -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? diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/.npmrc b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://127.0.0.1:4873 +@sentry-internal:registry=http://127.0.0.1:4873 diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json new file mode 100644 index 000000000000..79a276c3c642 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json @@ -0,0 +1,37 @@ +{ + "name": "tanstackstart-react", + "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 && pnpm build", + "test:assert": "pnpm test" + }, + "dependencies": { + "@sentry/tanstackstart-react": "latest || *", + "@tanstack/react-start": "^1.139.12", + "@tanstack/react-router": "^1.64.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.66", + "@types/react-dom": "^18.2.22", + "@types/node": "^24.10.1", + "@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": "7.2.0", + "vite-tsconfig-paths": "^5.1.4", + "@playwright/test": "~1.53.2", + "@sentry-internal/test-utils": "link:../../../test-utils" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs new file mode 100644 index 000000000000..c170c2b37039 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, + port: 4173, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx new file mode 100644 index 000000000000..82a730704ad7 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx @@ -0,0 +1,11 @@ +import { createRouter } from '@tanstack/react-router' +import { routeTree } from './routeTree.gen' + +export function getRouter() { + const router = createRouter({ + routeTree, + scrollRestoration: true, + }) + + return router +} diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx new file mode 100644 index 000000000000..5caf16eb252c --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx @@ -0,0 +1,47 @@ +import type { ReactNode } from 'react' +import { + Outlet, + createRootRoute, + HeadContent, + Scripts, +} from '@tanstack/react-router' + +export const Route = createRootRoute({ + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + { + title: 'TanStack Start Starter', + }, + ], + }), + component: RootComponent, +}) + +function RootComponent() { + return ( + + + + ) +} + +function RootDocument({ children }: Readonly<{ children: ReactNode }>) { + return ( + + + + + + {children} + + + + ) +} diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx new file mode 100644 index 000000000000..fada985a80d0 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx @@ -0,0 +1,11 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/')({ + component: Home +}) + +function Home() { + return ( +
Hello World!
+ ) +} diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/start-event-proxy.mjs new file mode 100644 index 000000000000..a3f8045010bd --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'tanstackstart-react', +}); diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts new file mode 100644 index 000000000000..b1cf7d5febc1 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts @@ -0,0 +1,9 @@ +import { expect, test } from '@playwright/test'; + +test('runs the application', async ({ page }) => { + await page.goto(`/`); + + await page.waitForTimeout(1000); + + await expect(page.locator('div')).toContainText('Hello World!'); +}); diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.json new file mode 100644 index 000000000000..5dcdb1fa6f4a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "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, + "strictNullChecks": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.node.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.node.json new file mode 100644 index 000000000000..97ede7ee6f2d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts new file mode 100644 index 000000000000..67930bf9ff5b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vite' +import tsConfigPaths from 'vite-tsconfig-paths' +import { tanstackStart } from '@tanstack/react-start/plugin/vite' +import viteReact from '@vitejs/plugin-react-swc' + +export default defineConfig({ + server: { + port: 3000, + }, + preview: { + port: 4173, + }, + plugins: [ + tsConfigPaths(), + tanstackStart(), + // react's vite plugin must come after start's vite plugin + viteReact(), + ], +}) From cddb81e36ec6def6e1610c7b52d5882669eebd99 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 2 Dec 2025 10:21:14 +0100 Subject: [PATCH 02/12] start to instrument test app with sentry (not working yet) --- .../tanstackstart-react/instrument.server.mjs | 12 +++++++ .../tanstackstart-react/src/router.tsx | 22 +++++++++++-- .../tanstackstart-react/src/routes/index.tsx | 9 +++++- .../tanstackstart-react/tests/errors.test.ts | 32 +++++++++++++++++-- 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs new file mode 100644 index 000000000000..b21117d95091 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs @@ -0,0 +1,12 @@ +import * as Sentry from "@sentry/tanstackstart-react"; + +Sentry.init({ + environment: 'qa', // dynamic sampling bias to keep transactions + dsn: process.env.E2E_TEST_DSN, + tunnel: `http://localhost:3031/`, // proxy server + tracesSampleRate: 1, + transportOptions: { + // We expect the app to send a lot of events in a short time + bufferSize: 1000, + }, +}); diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx index 82a730704ad7..bfebb7cd805a 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx @@ -1,3 +1,4 @@ +import * as Sentry from "@sentry/tanstackstart-react" import { createRouter } from '@tanstack/react-router' import { routeTree } from './routeTree.gen' @@ -5,7 +6,24 @@ export function getRouter() { const router = createRouter({ routeTree, scrollRestoration: true, - }) + }); - return router + if (!router.isServer) { + Sentry.init({ + environment: 'qa', // dynamic sampling bias to keep transactions + dsn: process.env.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, + }); + } + + return router; } diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx index fada985a80d0..658f0b654d4b 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx @@ -6,6 +6,13 @@ export const Route = createFileRoute('/')({ function Home() { return ( -
Hello World!
+ ) } diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts index b1cf7d5febc1..46aae616965f 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts @@ -1,9 +1,35 @@ import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('Sends client-side error to Sentry', async ({ page }) => { + const errorEventPromise = waitForError('tanstackstart-react', errorEvent => { + console.log('errorEvent', errorEvent); + return errorEvent?.exception?.values?.[0]?.value === 'Sentry Test Error'; + }); -test('runs the application', async ({ page }) => { await page.goto(`/`); - await page.waitForTimeout(1000); + await expect(page.locator('button')).toContainText('Break the world'); + + await page.locator('button').click(); + console.log('clicked button'); + + const errorEvent = await errorEventPromise; + console.log('errorEvent', errorEvent); + + expect(errorEvent).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Sentry Test Error', + mechanism: { + handled: false, + }, + }, + ], + }, + }); - await expect(page.locator('div')).toContainText('Hello World!'); + expect(errorEvent.transaction).toBe('/'); }); From 99c2194b257640dfd5954ecf3bb1102127108cb7 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 2 Dec 2025 15:26:22 +0100 Subject: [PATCH 03/12] server side init works but the client init is never called --- .../tanstackstart-react/package.json | 16 ++++++++-------- .../tanstackstart-react/playwright.config.mjs | 2 +- .../tanstackstart-react/src/router.tsx | 8 +++++++- .../tanstackstart-react/vite.config.ts | 3 --- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json index 79a276c3c642..7e4a9dba4ef5 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "build": "vite build", - "start": "vite preview", + "start": "NODE_OPTIONS='--import ./instrument.server.mjs' vite dev", "test": "playwright test", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install && pnpm build", @@ -14,18 +14,18 @@ "dependencies": { "@sentry/tanstackstart-react": "latest || *", "@tanstack/react-start": "^1.139.12", - "@tanstack/react-router": "^1.64.0", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@tanstack/react-router": "^1.139.12", + "react": "^19.2.0", + "react-dom": "^19.2.0" }, "devDependencies": { - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@types/node": "^24.10.1", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "@types/node": "^24.10.0", "@typescript-eslint/eslint-plugin": "^7.2.0", "@typescript-eslint/parser": "^7.2.0", "@vitejs/plugin-react-swc": "^3.5.0", - "typescript": "^5.2.2", + "typescript": "^5.9.0", "vite": "7.2.0", "vite-tsconfig-paths": "^5.1.4", "@playwright/test": "~1.53.2", diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs index c170c2b37039..4ca3c24e7fda 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/playwright.config.mjs @@ -2,7 +2,7 @@ import { getPlaywrightConfig } from '@sentry-internal/test-utils'; const config = getPlaywrightConfig({ startCommand: `pnpm start`, - port: 4173, + port: 3000, }); export default config; diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx index bfebb7cd805a..7e7d0d2940a1 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx @@ -8,10 +8,16 @@ export function getRouter() { scrollRestoration: true, }); + console.log('CREATING ROUTER'); + console.log('E2E_TEST_DSN', process.env.E2E_TEST_DSN); + console.log('ROUTER IS SERVER', router.isServer); + if (!router.isServer) { + console.log('INITIALIZING SENTRY CLIENT'); Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions - dsn: process.env.APP_DSN, + debug: true, + dsn: process.env.E2E_TEST_DSN, integrations: [Sentry.tanstackRouterBrowserTracingIntegration(router)], // We recommend adjusting this value in production, or using tracesSampler // for finer control diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts index 67930bf9ff5b..4055c08c5cb7 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts @@ -7,9 +7,6 @@ export default defineConfig({ server: { port: 3000, }, - preview: { - port: 4173, - }, plugins: [ tsConfigPaths(), tanstackStart(), From fd19ba0a54dcb20dedb55969a7fa10d71b4038e8 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 2 Dec 2025 16:16:55 +0100 Subject: [PATCH 04/12] updates but client instrumentation still broken --- .../test-applications/tanstackstart-react/src/router.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx index 7e7d0d2940a1..aa8891b82a25 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx @@ -2,7 +2,7 @@ import * as Sentry from "@sentry/tanstackstart-react" import { createRouter } from '@tanstack/react-router' import { routeTree } from './routeTree.gen' -export function getRouter() { +export const getRouter = () => { const router = createRouter({ routeTree, scrollRestoration: true, @@ -24,10 +24,6 @@ export function getRouter() { 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, }); } From 4b1d66961782206bd2924c1022350cb347a44901 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 2 Dec 2025 16:42:25 +0100 Subject: [PATCH 05/12] dsn did not resolve in the browser not it works --- .../test-applications/tanstackstart-react/src/router.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx index aa8891b82a25..a5b1b1c14dec 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx @@ -8,16 +8,11 @@ export const getRouter = () => { scrollRestoration: true, }); - console.log('CREATING ROUTER'); - console.log('E2E_TEST_DSN', process.env.E2E_TEST_DSN); - console.log('ROUTER IS SERVER', router.isServer); - if (!router.isServer) { - console.log('INITIALIZING SENTRY CLIENT'); Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions debug: true, - dsn: process.env.E2E_TEST_DSN, + dsn: 'https://public@dsn.ingest.sentry.io/1337', integrations: [Sentry.tanstackRouterBrowserTracingIntegration(router)], // We recommend adjusting this value in production, or using tracesSampler // for finer control From 18f4303561103eaefd9b34fa5ea70f8ed011578d Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 2 Dec 2025 16:48:03 +0100 Subject: [PATCH 06/12] finish basic client side capture exception test --- .../test-applications/tanstackstart-react/src/router.tsx | 1 - .../test-applications/tanstackstart-react/tests/errors.test.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx index a5b1b1c14dec..dc7f28c07f7b 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx @@ -11,7 +11,6 @@ export const getRouter = () => { if (!router.isServer) { Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions - debug: true, dsn: 'https://public@dsn.ingest.sentry.io/1337', integrations: [Sentry.tanstackRouterBrowserTracingIntegration(router)], // We recommend adjusting this value in production, or using tracesSampler diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts index 46aae616965f..478d56c0f7c5 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts @@ -3,7 +3,6 @@ import { waitForError } from '@sentry-internal/test-utils'; test('Sends client-side error to Sentry', async ({ page }) => { const errorEventPromise = waitForError('tanstackstart-react', errorEvent => { - console.log('errorEvent', errorEvent); return errorEvent?.exception?.values?.[0]?.value === 'Sentry Test Error'; }); @@ -12,10 +11,8 @@ test('Sends client-side error to Sentry', async ({ page }) => { await expect(page.locator('button')).toContainText('Break the world'); await page.locator('button').click(); - console.log('clicked button'); const errorEvent = await errorEventPromise; - console.log('errorEvent', errorEvent); expect(errorEvent).toMatchObject({ exception: { From b9855a9f27fab5b5a6e2347a8fa641f69b6fc207 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 2 Dec 2025 16:51:13 +0100 Subject: [PATCH 07/12] yarn fix --- .../tanstackstart-react/instrument.server.mjs | 2 +- .../tanstackstart-react/src/router.tsx | 8 ++++---- .../tanstackstart-react/src/routes/__root.tsx | 15 +++++---------- .../tanstackstart-react/src/routes/index.tsx | 10 +++++----- .../tanstackstart-react/vite.config.ts | 10 +++++----- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs index b21117d95091..8bc20de7578b 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs @@ -1,4 +1,4 @@ -import * as Sentry from "@sentry/tanstackstart-react"; +import * as Sentry from '@sentry/tanstackstart-react'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx index dc7f28c07f7b..b1c6f7727a26 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/router.tsx @@ -1,6 +1,6 @@ -import * as Sentry from "@sentry/tanstackstart-react" -import { createRouter } from '@tanstack/react-router' -import { routeTree } from './routeTree.gen' +import * as Sentry from '@sentry/tanstackstart-react'; +import { createRouter } from '@tanstack/react-router'; +import { routeTree } from './routeTree.gen'; export const getRouter = () => { const router = createRouter({ @@ -22,4 +22,4 @@ export const getRouter = () => { } return router; -} +}; diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx index 5caf16eb252c..0a268a350e34 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/__root.tsx @@ -1,10 +1,5 @@ -import type { ReactNode } from 'react' -import { - Outlet, - createRootRoute, - HeadContent, - Scripts, -} from '@tanstack/react-router' +import type { ReactNode } from 'react'; +import { Outlet, createRootRoute, HeadContent, Scripts } from '@tanstack/react-router'; export const Route = createRootRoute({ head: () => ({ @@ -22,14 +17,14 @@ export const Route = createRootRoute({ ], }), component: RootComponent, -}) +}); function RootComponent() { return ( - ) + ); } function RootDocument({ children }: Readonly<{ children: ReactNode }>) { @@ -43,5 +38,5 @@ function RootDocument({ children }: Readonly<{ children: ReactNode }>) { - ) + ); } diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx index 658f0b654d4b..ca0e788acc51 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx @@ -1,18 +1,18 @@ -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/')({ - component: Home -}) + component: Home, +}); function Home() { return ( - ) + ); } diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts index 4055c08c5cb7..a986b9aaf4aa 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts @@ -1,7 +1,7 @@ -import { defineConfig } from 'vite' -import tsConfigPaths from 'vite-tsconfig-paths' -import { tanstackStart } from '@tanstack/react-start/plugin/vite' -import viteReact from '@vitejs/plugin-react-swc' +import { defineConfig } from 'vite'; +import tsConfigPaths from 'vite-tsconfig-paths'; +import { tanstackStart } from '@tanstack/react-start/plugin/vite'; +import viteReact from '@vitejs/plugin-react-swc'; export default defineConfig({ server: { @@ -13,4 +13,4 @@ export default defineConfig({ // react's vite plugin must come after start's vite plugin viteReact(), ], -}) +}); From 3171925c3a7464da9baa5f5c20f510dc7464b507 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Tue, 2 Dec 2025 17:59:10 +0100 Subject: [PATCH 08/12] use nitro --- .../test-applications/tanstackstart-react/package.json | 5 +++-- .../test-applications/tanstackstart-react/vite.config.ts | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json index 7e4a9dba4ef5..e44229cce78f 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json @@ -4,8 +4,8 @@ "version": "0.0.1", "type": "module", "scripts": { - "build": "vite build", - "start": "NODE_OPTIONS='--import ./instrument.server.mjs' vite dev", + "build": "vite build && cp instrument.server.mjs .output/server", + "start": "node --import ./.output/server/instrument.server.mjs .output/server/index.mjs", "test": "playwright test", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install && pnpm build", @@ -28,6 +28,7 @@ "typescript": "^5.9.0", "vite": "7.2.0", "vite-tsconfig-paths": "^5.1.4", + "nitro": "^3.0.0", "@playwright/test": "~1.53.2", "@sentry-internal/test-utils": "link:../../../test-utils" }, diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts index a986b9aaf4aa..4df9fbb14208 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/vite.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'vite'; import tsConfigPaths from 'vite-tsconfig-paths'; import { tanstackStart } from '@tanstack/react-start/plugin/vite'; import viteReact from '@vitejs/plugin-react-swc'; +import { nitro } from 'nitro/vite'; export default defineConfig({ server: { @@ -10,6 +11,7 @@ export default defineConfig({ plugins: [ tsConfigPaths(), tanstackStart(), + nitro(), // react's vite plugin must come after start's vite plugin viteReact(), ], From 3cf192d8266e8567827c19f79633316d2d9b34a6 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 3 Dec 2025 07:58:33 +0100 Subject: [PATCH 09/12] add test: browser calls server function with an error is reported --- .../tanstackstart-react/src/routes/index.tsx | 31 ++++++++++---- .../tanstackstart-react/tests/errors.test.ts | 40 ++++++++++++++++--- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx index ca0e788acc51..4fb6b75fcb29 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx @@ -1,4 +1,9 @@ import { createFileRoute } from '@tanstack/react-router'; +import { createServerFn } from '@tanstack/react-start'; + +const throwServerError = createServerFn().handler(async () => { + throw new Error('Sentry Server Function Test Error'); +}); export const Route = createFileRoute('/')({ component: Home, @@ -6,13 +11,23 @@ export const Route = createFileRoute('/')({ function Home() { return ( - +
+ + +
); } diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts index 478d56c0f7c5..db35eaab6652 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts @@ -1,16 +1,16 @@ import { expect, test } from '@playwright/test'; import { waitForError } from '@sentry-internal/test-utils'; -test('Sends client-side error to Sentry', async ({ page }) => { +test('Sends client-side error to Sentry with auto-instrumentation', async ({ page }) => { const errorEventPromise = waitForError('tanstackstart-react', errorEvent => { - return errorEvent?.exception?.values?.[0]?.value === 'Sentry Test Error'; + return errorEvent?.exception?.values?.[0]?.value === 'Sentry Client Test Error'; }); await page.goto(`/`); - await expect(page.locator('button')).toContainText('Break the world'); + await expect(page.locator('button').filter({ hasText: 'Break the client' })).toBeVisible(); - await page.locator('button').click(); + await page.locator('button').filter({ hasText: 'Break the client' }).click(); const errorEvent = await errorEventPromise; @@ -19,7 +19,37 @@ test('Sends client-side error to Sentry', async ({ page }) => { values: [ { type: 'Error', - value: 'Sentry Test Error', + value: 'Sentry Client Test Error', + mechanism: { + handled: false, + }, + }, + ], + }, + }); + + expect(errorEvent.transaction).toBe('/'); +}); + +test('Sends server-side function error to Sentry with auto-instrumentation', async ({ page }) => { + const errorEventPromise = waitForError('tanstackstart-react', errorEvent => { + return errorEvent?.exception?.values?.[0]?.value === 'Sentry Server Function Test Error'; + }); + + await page.goto(`/`); + + await expect(page.locator('button').filter({ hasText: 'Break server function' })).toBeVisible(); + + await page.locator('button').filter({ hasText: 'Break server function' }).click(); + + const errorEvent = await errorEventPromise; + + expect(errorEvent).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Sentry Server Function Test Error', mechanism: { handled: false, }, From 860af0e16b26b8a50136c5f7341a3cbcdc95b813 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 3 Dec 2025 08:13:44 +0100 Subject: [PATCH 10/12] add test: manual instrumentation works in server routes --- .../src/routes/api.error.ts | 18 +++++++++++ .../tanstackstart-react/src/routes/index.tsx | 8 +++++ .../tanstackstart-react/tests/errors.test.ts | 30 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts new file mode 100644 index 000000000000..9baad7de5269 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts @@ -0,0 +1,18 @@ +import * as Sentry from '@sentry/tanstackstart-react'; +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/api/error')({ + server: { + handlers: { + GET: async () => { + // This will throw a server-side error that Sentry should catch + try { + throw new Error('Sentry API Route Test Error'); + } catch (error) { + Sentry.captureException(error); + throw error; + } + }, + }, + }, +}); diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx index 4fb6b75fcb29..a92fabf20c4a 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/index.tsx @@ -28,6 +28,14 @@ function Home() { > Break server function + ); } diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts index db35eaab6652..f5d25febb7a4 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/errors.test.ts @@ -60,3 +60,33 @@ test('Sends server-side function error to Sentry with auto-instrumentation', asy expect(errorEvent.transaction).toBe('/'); }); + +test('Sends API route error to Sentry if manually instrumented', async ({ page }) => { + const errorEventPromise = waitForError('tanstackstart-react', errorEvent => { + return errorEvent?.exception?.values?.[0]?.value === 'Sentry API Route Test Error'; + }); + + await page.goto(`/`); + + await expect(page.locator('button').filter({ hasText: 'Break API route' })).toBeVisible(); + + await page.locator('button').filter({ hasText: 'Break API route' }).click(); + + const errorEvent = await errorEventPromise; + + expect(errorEvent).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Sentry API Route Test Error', + mechanism: { + handled: true, + }, + }, + ], + }, + }); + + expect(errorEvent.transaction).toBe('GET /api/error'); +}); From d4b97f470714beb8319be5f310f6a2345d8c5cb5 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 3 Dec 2025 08:14:51 +0100 Subject: [PATCH 11/12] yarn fix --- .../src/routes/api.error.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts index 9baad7de5269..636694d707e9 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts @@ -1,18 +1,18 @@ import * as Sentry from '@sentry/tanstackstart-react'; -import { createFileRoute } from '@tanstack/react-router' +import { createFileRoute } from '@tanstack/react-router'; export const Route = createFileRoute('/api/error')({ - server: { - handlers: { - GET: async () => { - // This will throw a server-side error that Sentry should catch - try { - throw new Error('Sentry API Route Test Error'); - } catch (error) { - Sentry.captureException(error); - throw error; - } - }, - }, + server: { + handlers: { + GET: async () => { + // This will throw a server-side error that Sentry should catch + try { + throw new Error('Sentry API Route Test Error'); + } catch (error) { + Sentry.captureException(error); + throw error; + } + }, }, + }, }); From b8f16a39843a2261a558ad9a3f3a5dd9a49482ee Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 3 Dec 2025 08:17:26 +0100 Subject: [PATCH 12/12] remove comment --- .../tanstackstart-react/src/routes/api.error.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts index 636694d707e9..470d53346ad7 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/src/routes/api.error.ts @@ -5,7 +5,6 @@ export const Route = createFileRoute('/api/error')({ server: { handlers: { GET: async () => { - // This will throw a server-side error that Sentry should catch try { throw new Error('Sentry API Route Test Error'); } catch (error) {