diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/[xoxo]/error/route.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/[xoxo]/error/route.ts
new file mode 100644
index 000000000000..bdfb525fc735
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/[xoxo]/error/route.ts
@@ -0,0 +1,3 @@
+export async function GET() {
+ throw new Error('Route handler error');
+}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/[xoxo]/node/route.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/[xoxo]/node/route.ts
index 5bc418f077aa..a043231cebf3 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/[xoxo]/node/route.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/[xoxo]/node/route.ts
@@ -5,3 +5,7 @@ export const dynamic = 'force-dynamic';
export async function GET() {
return NextResponse.json({ message: 'Hello Node Route Handler' });
}
+
+export async function POST() {
+ return NextResponse.json({ name: 'Boop' }, { status: 400 });
+}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/static/route.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/static/route.ts
similarity index 67%
rename from dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/static/route.ts
rename to dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/static/route.ts
index c2407f908b8b..63710980b77a 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/static/route.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/app/route-handler/static/route.ts
@@ -1,5 +1,5 @@
import { NextResponse } from 'next/server';
-export async function GET(request: Request) {
+export async function GET() {
return NextResponse.json({ name: 'Static' });
}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/next.config.js b/dev-packages/e2e-tests/test-applications/nextjs-15/next.config.js
index 1098c2ce5a4f..55a7b9361b3a 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-15/next.config.js
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/next.config.js
@@ -5,4 +5,7 @@ const nextConfig = {};
module.exports = withSentryConfig(nextConfig, {
silent: true,
+ release: {
+ name: 'foobar123',
+ },
});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/pages/[param]/pages-router-client-trace-propagation.tsx b/dev-packages/e2e-tests/test-applications/nextjs-15/pages/[locale]/pages-router-client-trace-propagation.tsx
similarity index 86%
rename from dev-packages/e2e-tests/test-applications/nextjs-turbo/pages/[param]/pages-router-client-trace-propagation.tsx
rename to dev-packages/e2e-tests/test-applications/nextjs-15/pages/[locale]/pages-router-client-trace-propagation.tsx
index be0391c3618e..f9ec42bbffb1 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/pages/[param]/pages-router-client-trace-propagation.tsx
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/pages/[locale]/pages-router-client-trace-propagation.tsx
@@ -1,5 +1,5 @@
export default function Page() {
-
Hello World!
;
+ return Hello World!
;
}
// getServerSideProps makes this page dynamic and allows tracing data to be inserted
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/pages/_app.tsx b/dev-packages/e2e-tests/test-applications/nextjs-15/pages/_app.tsx
similarity index 100%
rename from dev-packages/e2e-tests/test-applications/nextjs-turbo/pages/_app.tsx
rename to dev-packages/e2e-tests/test-applications/nextjs-15/pages/_app.tsx
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/pages-router/client-trace-propagation.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/client-trace-propagation.test.ts
similarity index 73%
rename from dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/pages-router/client-trace-propagation.test.ts
rename to dev-packages/e2e-tests/test-applications/nextjs-15/tests/client-trace-propagation.test.ts
index 032aa55b3116..8f555d834a84 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/pages-router/client-trace-propagation.test.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/client-trace-propagation.test.ts
@@ -2,23 +2,22 @@ import { expect, test } from '@playwright/test';
import { waitForTransaction } from '@sentry-internal/test-utils';
import { parseSemver } from '@sentry/core';
-const packageJson = require('../../package.json');
+const packageJson = require('../package.json');
const nextjsVersion = packageJson.dependencies.next;
const { major, minor } = parseSemver(nextjsVersion);
test('Should propagate traces from server to client in pages router', async ({ page }) => {
- // TODO: Remove this skippage when Next.js 15.3.0 is released and bump version in package json to 15.3.0
test.skip(
major === 15 && minor !== undefined && minor < 3,
'Next.js version does not support clientside instrumentation',
);
- const serverTransactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return transactionEvent?.transaction === 'GET /[param]/pages-router-client-trace-propagation';
+ const serverTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
+ return transactionEvent?.transaction === 'GET /[locale]/pages-router-client-trace-propagation';
});
- const pageloadTransactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return transactionEvent?.transaction === '/[param]/pages-router-client-trace-propagation';
+ const pageloadTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
+ return transactionEvent?.transaction === '/[locale]/pages-router-client-trace-propagation';
});
await page.goto(`/123/pages-router-client-trace-propagation`);
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/route-handler.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/route-handler.test.ts
index d5566a100a5f..09def19c2af9 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/route-handler.test.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/route-handler.test.ts
@@ -1,5 +1,5 @@
import test, { expect } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
+import { waitForError, waitForTransaction } from '@sentry-internal/test-utils';
test('Should create a transaction for node route handlers', async ({ request }) => {
const routehandlerTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
@@ -37,3 +37,59 @@ test('Should create a transaction for edge route handlers', async ({ request })
expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
expect(routehandlerTransaction.contexts?.trace?.data?.['http.request.header.x_charly']).toBe('gomez');
});
+
+test('Should create a transaction for static route handlers', async ({ request }) => {
+ const routehandlerTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
+ return transactionEvent?.transaction === 'GET /route-handler/static';
+ });
+
+ const response = await request.get('/route-handler/static');
+ expect(await response.json()).toStrictEqual({ name: 'Static' });
+
+ const routehandlerTransaction = await routehandlerTransactionPromise;
+
+ expect(routehandlerTransaction.contexts?.trace?.status).toBe('ok');
+ expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
+});
+
+test('Should create a transaction for route handlers and correctly set span status depending on http status', async ({
+ request,
+}) => {
+ const routehandlerTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
+ return transactionEvent?.transaction === 'POST /route-handler/[xoxo]/node';
+ });
+
+ const response = await request.post('/route-handler/123/node');
+ expect(await response.json()).toStrictEqual({ name: 'Boop' });
+
+ const routehandlerTransaction = await routehandlerTransactionPromise;
+
+ expect(routehandlerTransaction.contexts?.trace?.status).toBe('invalid_argument');
+ expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
+});
+
+test('Should record exceptions and transactions for faulty route handlers', async ({ request }) => {
+ const errorEventPromise = waitForError('nextjs-15', errorEvent => {
+ return errorEvent?.exception?.values?.[0]?.value === 'Route handler error';
+ });
+
+ const routehandlerTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
+ return transactionEvent?.transaction === 'GET /route-handler/[xoxo]/error';
+ });
+
+ await request.get('/route-handler/123/error').catch(() => {});
+
+ const routehandlerTransaction = await routehandlerTransactionPromise;
+ const routehandlerError = await errorEventPromise;
+
+ expect(routehandlerTransaction.contexts?.trace?.status).toBe('internal_error');
+ expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
+ expect(routehandlerTransaction.contexts?.trace?.origin).toContain('auto');
+
+ expect(routehandlerError.exception?.values?.[0].value).toBe('Route handler error');
+
+ expect(routehandlerError.request?.method).toBe('GET');
+ expect(routehandlerError.request?.url).toContain('/route-handler/123/error');
+
+ expect(routehandlerError.transaction).toContain('/route-handler/[xoxo]/error');
+});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/.gitignore b/dev-packages/e2e-tests/test-applications/nextjs-turbo/.gitignore
deleted file mode 100644
index ebdbfc025b6a..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/.gitignore
+++ /dev/null
@@ -1,46 +0,0 @@
-# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-
-# dependencies
-/node_modules
-/.pnp
-.pnp.js
-
-# testing
-/coverage
-
-# next.js
-/.next/
-/out/
-
-# production
-/build
-
-# misc
-.DS_Store
-*.pem
-
-# debug
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-.pnpm-debug.log*
-
-# local env files
-.env*.local
-
-# vercel
-.vercel
-
-# typescript
-*.tsbuildinfo
-next-env.d.ts
-
-!*.d.ts
-
-# Sentry
-.sentryclirc
-
-.vscode
-
-test-results
-event-dumps
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/.npmrc b/dev-packages/e2e-tests/test-applications/nextjs-turbo/.npmrc
deleted file mode 100644
index c0bee06878d1..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/.npmrc
+++ /dev/null
@@ -1,8 +0,0 @@
-@sentry:registry=http://127.0.0.1:4873
-@sentry-internal:registry=http://127.0.0.1:4873
-
-# todo: check if this is still needed in upcoming versions
-# Hoist all dependencies to the root level due to issues with import-in-the-middle and require-in-the-middle
-# Just adding these as dependencies removed the warnings, but didn't fix the issue
-shamefully-hoist=true
-strict-peer-dependencies=false
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/[param]/rsc-page-error/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/[param]/rsc-page-error/page.tsx
deleted file mode 100644
index a6ae11918445..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/[param]/rsc-page-error/page.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-export const dynamic = 'force-dynamic';
-
-export default function Page() {
- if (Math.random() > -1) {
- throw new Error('page rsc render error');
- }
-
- return null;
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/global-error.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/global-error.tsx
deleted file mode 100644
index 20c175015b03..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/global-error.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-'use client';
-
-import * as Sentry from '@sentry/nextjs';
-import NextError from 'next/error';
-import { useEffect } from 'react';
-
-export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
- useEffect(() => {
- Sentry.captureException(error);
- }, [error]);
-
- return (
-
-
- {/* `NextError` is the default Next.js error page component. Its type
- definition requires a `statusCode` prop. However, since the App Router
- does not expose status codes for errors, we simply pass 0 to render a
- generic error message. */}
-
-
-
- );
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/layout.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/layout.tsx
deleted file mode 100644
index c8f9cee0b787..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/layout.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-export default function Layout({ children }: { children: React.ReactNode }) {
- return (
-
- {children}
-
- );
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/pageload-transaction/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/pageload-transaction/page.tsx
deleted file mode 100644
index 4d692cbabd9b..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/pageload-transaction/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function Page() {
- return Hello World!
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/beep/[two]/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/beep/[two]/page.tsx
deleted file mode 100644
index f34461c2bb07..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/beep/[two]/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function ParameterizedPage() {
- return Dynamic page two
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/beep/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/beep/page.tsx
deleted file mode 100644
index a7d9164c8c03..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/beep/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function BeepPage() {
- return Beep
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/page.tsx
deleted file mode 100644
index 9fa617a22381..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/[one]/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function ParameterizedPage() {
- return Dynamic page one
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/static/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/static/page.tsx
deleted file mode 100644
index 16ef0482d53b..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/parameterized/static/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function StaticPage() {
- return Static page
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/[param]/error/route.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/[param]/error/route.ts
deleted file mode 100644
index dbc0c6193131..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/[param]/error/route.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export async function GET(request: Request) {
- throw new Error('Dynamic route handler error');
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/[param]/route.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/[param]/route.ts
deleted file mode 100644
index 581a4d68b640..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/app/route-handlers/[param]/route.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { NextResponse } from 'next/server';
-
-export async function GET() {
- return NextResponse.json({ name: 'Beep' });
-}
-
-export async function POST() {
- return NextResponse.json({ name: 'Boop' }, { status: 400 });
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/globals.d.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/globals.d.ts
deleted file mode 100644
index 109dbcd55648..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/globals.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-interface Window {
- recordedTransactions?: string[];
- capturedExceptionId?: string;
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/instrumentation-client.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/instrumentation-client.ts
deleted file mode 100644
index 4870c64e7959..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/instrumentation-client.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import * as Sentry from '@sentry/nextjs';
-
-Sentry.init({
- environment: 'qa', // dynamic sampling bias to keep transactions
- dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN,
- tunnel: `http://localhost:3031/`, // proxy server
- tracesSampleRate: 1.0,
- sendDefaultPii: true,
-});
-
-export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/instrumentation.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/instrumentation.ts
deleted file mode 100644
index 964f937c439a..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/instrumentation.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as Sentry from '@sentry/nextjs';
-
-export async function register() {
- if (process.env.NEXT_RUNTIME === 'nodejs') {
- await import('./sentry.server.config');
- }
-
- if (process.env.NEXT_RUNTIME === 'edge') {
- await import('./sentry.edge.config');
- }
-}
-
-export const onRequestError = Sentry.captureRequestError;
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/next-env.d.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/next-env.d.ts
deleted file mode 100644
index 3cd7048ed947..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/next-env.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-///
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/next.config.js b/dev-packages/e2e-tests/test-applications/nextjs-turbo/next.config.js
deleted file mode 100644
index 55a7b9361b3a..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/next.config.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const { withSentryConfig } = require('@sentry/nextjs');
-
-/** @type {import('next').NextConfig} */
-const nextConfig = {};
-
-module.exports = withSentryConfig(nextConfig, {
- silent: true,
- release: {
- name: 'foobar123',
- },
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/package.json b/dev-packages/e2e-tests/test-applications/nextjs-turbo/package.json
deleted file mode 100644
index 999776fa6805..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/package.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": "create-next-app",
- "version": "0.1.0",
- "private": true,
- "scripts": {
- "build": "next build --turbopack > .tmp_build_stdout 2> .tmp_build_stderr || (cat .tmp_build_stdout && cat .tmp_build_stderr && exit 1)",
- "clean": "npx rimraf node_modules pnpm-lock.yaml",
- "test:prod": "TEST_ENV=production playwright test",
- "test:dev": "TEST_ENV=development playwright test",
- "test:build": "pnpm install && pnpm build",
- "test:build-canary": "pnpm install && pnpm add next@canary && pnpm add react@canary && pnpm add react-dom@canary && pnpm build",
- "test:build-latest": "pnpm install && pnpm add next@latest && pnpm build",
- "test:assert": "pnpm test:prod && pnpm test:dev"
- },
- "dependencies": {
- "@sentry/nextjs": "latest || *",
- "@types/node": "^18.19.1",
- "@types/react": "^19",
- "@types/react-dom": "^19",
- "next": "^15.5.10",
- "react": "^19",
- "react-dom": "^19",
- "typescript": "~5.0.0"
- },
- "devDependencies": {
- "@playwright/test": "~1.56.0",
- "@sentry-internal/test-utils": "link:../../../test-utils",
- "@sentry/core": "latest || *"
- },
- "volta": {
- "extends": "../../package.json"
- },
- "sentryTest": {
- "optional": true,
- "optionalVariants": [
- {
- "build-command": "pnpm test:build-canary",
- "label": "nextjs-turbo (canary)"
- },
- {
- "build-command": "pnpm test:build-latest",
- "label": "nextjs-turbo (latest)"
- }
- ]
- }
-}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/nextjs-turbo/playwright.config.mjs
deleted file mode 100644
index 9a74af430808..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/playwright.config.mjs
+++ /dev/null
@@ -1,19 +0,0 @@
-import { getPlaywrightConfig } from '@sentry-internal/test-utils';
-const testEnv = process.env.TEST_ENV;
-
-if (!testEnv) {
- throw new Error('No test env defined');
-}
-
-const config = getPlaywrightConfig(
- {
- startCommand: testEnv === 'development' ? 'pnpm next dev -p 3030 --turbopack' : 'pnpm next start -p 3030',
- port: 3030,
- },
- {
- // This comes with the risk of tests leaking into each other but the tests run quite slow so we should parallelize
- workers: '100%',
- },
-);
-
-export default config;
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/sentry.edge.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/sentry.edge.config.ts
deleted file mode 100644
index 067d2ead0b8b..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/sentry.edge.config.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as Sentry from '@sentry/nextjs';
-
-Sentry.init({
- environment: 'qa', // dynamic sampling bias to keep transactions
- dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN,
- tunnel: `http://localhost:3031/`, // proxy server
- tracesSampleRate: 1.0,
- sendDefaultPii: true,
- transportOptions: {
- // We are doing a lot of events at once in this test
- bufferSize: 1000,
- },
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/sentry.server.config.ts
deleted file mode 100644
index 067d2ead0b8b..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/sentry.server.config.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as Sentry from '@sentry/nextjs';
-
-Sentry.init({
- environment: 'qa', // dynamic sampling bias to keep transactions
- dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN,
- tunnel: `http://localhost:3031/`, // proxy server
- tracesSampleRate: 1.0,
- sendDefaultPii: true,
- transportOptions: {
- // We are doing a lot of events at once in this test
- bufferSize: 1000,
- },
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/nextjs-turbo/start-event-proxy.mjs
deleted file mode 100644
index 2773cf8fa977..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/start-event-proxy.mjs
+++ /dev/null
@@ -1,14 +0,0 @@
-import * as fs from 'fs';
-import * as path from 'path';
-import { startEventProxyServer } from '@sentry-internal/test-utils';
-
-const packageJson = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json')));
-
-startEventProxyServer({
- port: 3031,
- proxyServerName: 'nextjs-turbo',
- envelopeDumpPath: path.join(
- process.cwd(),
- `event-dumps/nextjs-turbo-${packageJson.dependencies.next}-${process.env.TEST_ENV}.dump`,
- ),
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/pageload-transaction.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/pageload-transaction.test.ts
deleted file mode 100644
index 62a072b4ae7f..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/pageload-transaction.test.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-import { parseSemver } from '@sentry/core';
-
-const packageJson = require('../../package.json');
-const nextjsVersion = packageJson.dependencies.next;
-const { major, minor } = parseSemver(nextjsVersion);
-
-test('Should record pageload transactions (this test verifies that the client SDK is initialized)', async ({
- page,
-}) => {
- // TODO: Remove this skippage when Next.js 15.3.0 is released and bump version in package json to 15.3.0
- test.skip(
- major === 15 && minor !== undefined && minor < 3,
- 'Next.js version does not support clientside instrumentation',
- );
-
- const pageloadTransactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return transactionEvent?.transaction === '/pageload-transaction';
- });
-
- await page.goto(`/pageload-transaction`);
-
- const pageloadTransaction = await pageloadTransactionPromise;
-
- expect(pageloadTransaction).toBeDefined();
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/parameterized-routes.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/parameterized-routes.test.ts
deleted file mode 100644
index 0a2f1dfc0c28..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/parameterized-routes.test.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-test('should create a parameterized transaction when the `app` directory is used', async ({ page }) => {
- const transactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return (
- transactionEvent.transaction === '/parameterized/:one' && transactionEvent.contexts?.trace?.op === 'pageload'
- );
- });
-
- await page.goto(`/parameterized/cappuccino`);
-
- const transaction = await transactionPromise;
-
- expect(transaction).toMatchObject({
- breadcrumbs: expect.arrayContaining([
- {
- category: 'navigation',
- data: { from: '/parameterized/cappuccino', to: '/parameterized/cappuccino' },
- timestamp: expect.any(Number),
- },
- ]),
- contexts: {
- react: { version: expect.any(String) },
- trace: {
- data: {
- 'sentry.op': 'pageload',
- 'sentry.origin': 'auto.pageload.nextjs.app_router_instrumentation',
- 'sentry.source': 'route',
- },
- op: 'pageload',
- origin: 'auto.pageload.nextjs.app_router_instrumentation',
- span_id: expect.stringMatching(/[a-f0-9]{16}/),
- trace_id: expect.stringMatching(/[a-f0-9]{32}/),
- },
- },
- environment: 'qa',
- request: {
- headers: expect.any(Object),
- url: expect.stringMatching(/\/parameterized\/cappuccino$/),
- },
- start_timestamp: expect.any(Number),
- timestamp: expect.any(Number),
- transaction: '/parameterized/:one',
- transaction_info: { source: 'route' },
- type: 'transaction',
- });
-});
-
-test('should create a static transaction when the `app` directory is used and the route is not parameterized', async ({
- page,
-}) => {
- const transactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return (
- transactionEvent.transaction === '/parameterized/static' && transactionEvent.contexts?.trace?.op === 'pageload'
- );
- });
-
- await page.goto(`/parameterized/static`);
-
- const transaction = await transactionPromise;
-
- expect(transaction).toMatchObject({
- breadcrumbs: expect.arrayContaining([
- {
- category: 'navigation',
- data: { from: '/parameterized/static', to: '/parameterized/static' },
- timestamp: expect.any(Number),
- },
- ]),
- contexts: {
- react: { version: expect.any(String) },
- trace: {
- data: {
- 'sentry.op': 'pageload',
- 'sentry.origin': 'auto.pageload.nextjs.app_router_instrumentation',
- 'sentry.source': 'url',
- },
- op: 'pageload',
- origin: 'auto.pageload.nextjs.app_router_instrumentation',
- span_id: expect.stringMatching(/[a-f0-9]{16}/),
- trace_id: expect.stringMatching(/[a-f0-9]{32}/),
- },
- },
- environment: 'qa',
- request: {
- headers: expect.any(Object),
- url: expect.stringMatching(/\/parameterized\/static$/),
- },
- start_timestamp: expect.any(Number),
- timestamp: expect.any(Number),
- transaction: '/parameterized/static',
- transaction_info: { source: 'url' },
- type: 'transaction',
- });
-});
-
-test('should create a partially parameterized transaction when the `app` directory is used', async ({ page }) => {
- const transactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return (
- transactionEvent.transaction === '/parameterized/:one/beep' && transactionEvent.contexts?.trace?.op === 'pageload'
- );
- });
-
- await page.goto(`/parameterized/cappuccino/beep`);
-
- const transaction = await transactionPromise;
-
- expect(transaction).toMatchObject({
- breadcrumbs: expect.arrayContaining([
- {
- category: 'navigation',
- data: { from: '/parameterized/cappuccino/beep', to: '/parameterized/cappuccino/beep' },
- timestamp: expect.any(Number),
- },
- ]),
- contexts: {
- react: { version: expect.any(String) },
- trace: {
- data: {
- 'sentry.op': 'pageload',
- 'sentry.origin': 'auto.pageload.nextjs.app_router_instrumentation',
- 'sentry.source': 'route',
- },
- op: 'pageload',
- origin: 'auto.pageload.nextjs.app_router_instrumentation',
- span_id: expect.stringMatching(/[a-f0-9]{16}/),
- trace_id: expect.stringMatching(/[a-f0-9]{32}/),
- },
- },
- environment: 'qa',
- request: {
- headers: expect.any(Object),
- url: expect.stringMatching(/\/parameterized\/cappuccino\/beep$/),
- },
- start_timestamp: expect.any(Number),
- timestamp: expect.any(Number),
- transaction: '/parameterized/:one/beep',
- transaction_info: { source: 'route' },
- type: 'transaction',
- });
-});
-
-test('should create a nested parameterized transaction when the `app` directory is used', async ({ page }) => {
- const transactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return (
- transactionEvent.transaction === '/parameterized/:one/beep/:two' &&
- transactionEvent.contexts?.trace?.op === 'pageload'
- );
- });
-
- await page.goto(`/parameterized/cappuccino/beep/espresso`);
-
- const transaction = await transactionPromise;
-
- expect(transaction).toMatchObject({
- breadcrumbs: expect.arrayContaining([
- {
- category: 'navigation',
- data: { from: '/parameterized/cappuccino/beep/espresso', to: '/parameterized/cappuccino/beep/espresso' },
- timestamp: expect.any(Number),
- },
- ]),
- contexts: {
- react: { version: expect.any(String) },
- trace: {
- data: {
- 'sentry.op': 'pageload',
- 'sentry.origin': 'auto.pageload.nextjs.app_router_instrumentation',
- 'sentry.source': 'route',
- },
- op: 'pageload',
- origin: 'auto.pageload.nextjs.app_router_instrumentation',
- span_id: expect.stringMatching(/[a-f0-9]{16}/),
- trace_id: expect.stringMatching(/[a-f0-9]{32}/),
- },
- },
- environment: 'qa',
- request: {
- headers: expect.any(Object),
- url: expect.stringMatching(/\/parameterized\/cappuccino\/beep\/espresso$/),
- },
- start_timestamp: expect.any(Number),
- timestamp: expect.any(Number),
- transaction: '/parameterized/:one/beep/:two',
- transaction_info: { source: 'route' },
- type: 'transaction',
- });
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/route-handlers.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/route-handlers.test.ts
deleted file mode 100644
index 13f4f5fa4a58..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/route-handlers.test.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForError, waitForTransaction } from '@sentry-internal/test-utils';
-
-test('Should create a transaction for dynamic route handlers', async ({ request }) => {
- const routehandlerTransactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return transactionEvent?.transaction === 'GET /route-handlers/[param]';
- });
-
- const response = await request.get('/route-handlers/foo');
- expect(await response.json()).toStrictEqual({ name: 'Beep' });
-
- const routehandlerTransaction = await routehandlerTransactionPromise;
-
- expect(routehandlerTransaction.contexts?.trace?.status).toBe('ok');
- expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
-});
-
-test('Should create a transaction for static route handlers', async ({ request }) => {
- const routehandlerTransactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return transactionEvent?.transaction === 'GET /route-handlers/static';
- });
-
- const response = await request.get('/route-handlers/static');
- expect(await response.json()).toStrictEqual({ name: 'Static' });
-
- const routehandlerTransaction = await routehandlerTransactionPromise;
-
- expect(routehandlerTransaction.contexts?.trace?.status).toBe('ok');
- expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
-});
-
-test('Should create a transaction for route handlers and correctly set span status depending on http status', async ({
- request,
-}) => {
- const routehandlerTransactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return transactionEvent?.transaction === 'POST /route-handlers/[param]';
- });
-
- const response = await request.post('/route-handlers/bar');
- expect(await response.json()).toStrictEqual({ name: 'Boop' });
-
- const routehandlerTransaction = await routehandlerTransactionPromise;
-
- expect(routehandlerTransaction.contexts?.trace?.status).toBe('invalid_argument');
- expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
-});
-
-test('Should record exceptions and transactions for faulty route handlers', async ({ request }) => {
- const errorEventPromise = waitForError('nextjs-turbo', errorEvent => {
- return errorEvent?.exception?.values?.[0]?.value === 'Dynamic route handler error';
- });
-
- const routehandlerTransactionPromise = waitForTransaction('nextjs-turbo', async transactionEvent => {
- return transactionEvent?.transaction === 'GET /route-handlers/[param]/error';
- });
-
- await request.get('/route-handlers/boop/error').catch(() => {});
-
- const routehandlerTransaction = await routehandlerTransactionPromise;
- const routehandlerError = await errorEventPromise;
-
- expect(routehandlerTransaction.contexts?.trace?.status).toBe('internal_error');
- expect(routehandlerTransaction.contexts?.trace?.op).toBe('http.server');
- expect(routehandlerTransaction.contexts?.trace?.origin).toContain('auto');
-
- expect(routehandlerError.exception?.values?.[0].value).toBe('Dynamic route handler error');
-
- expect(routehandlerError.request?.method).toBe('GET');
- expect(routehandlerError.request?.url).toContain('/route-handlers/boop/error');
-
- expect(routehandlerError.transaction).toBe('/route-handlers/[param]/error');
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/rsc-error.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/rsc-error.test.ts
deleted file mode 100644
index d9c94de2d2be..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/rsc-error.test.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForError } from '@sentry-internal/test-utils';
-
-test('Should capture errors from server components', async ({ page }) => {
- const errorEventPromise = waitForError('nextjs-turbo', errorEvent => {
- return !!errorEvent?.exception?.values?.some(value => value.value === 'page rsc render error');
- });
-
- await page.goto(`/123/rsc-page-error`);
-
- const errorEvent = await errorEventPromise;
-
- expect(errorEvent).toBeDefined();
- expect(errorEvent.exception?.values?.[0]?.mechanism).toEqual({
- handled: false,
- type: 'auto.function.nextjs.on_request_error',
- });
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/server-components.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/server-components.test.ts
deleted file mode 100644
index d3a6db69fcd5..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tests/app-router/server-components.test.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-test('Sends a transaction for a request to app router with URL', async ({ page }) => {
- const serverComponentTransactionPromise = waitForTransaction('nextjs-turbo', transactionEvent => {
- return (
- transactionEvent?.transaction === 'GET /parameterized/[one]/beep/[two]' &&
- transactionEvent.contexts?.trace?.data?.['http.target']?.startsWith('/parameterized/1337/beep/42')
- );
- });
-
- await page.goto('/parameterized/1337/beep/42');
-
- const transactionEvent = await serverComponentTransactionPromise;
-
- expect(transactionEvent.contexts?.trace).toEqual({
- data: expect.objectContaining({
- 'sentry.op': 'http.server',
- 'sentry.origin': 'auto',
- 'sentry.sample_rate': 1,
- 'sentry.source': 'route',
- 'http.method': 'GET',
- 'http.response.status_code': 200,
- 'http.route': '/parameterized/[one]/beep/[two]',
- 'http.status_code': 200,
- 'http.target': '/parameterized/1337/beep/42',
- 'otel.kind': 'SERVER',
- 'next.route': '/parameterized/[one]/beep/[two]',
- }),
- op: 'http.server',
- origin: 'auto',
- span_id: expect.stringMatching(/[a-f0-9]{16}/),
- status: 'ok',
- trace_id: expect.stringMatching(/[a-f0-9]{32}/),
- });
-
- expect(transactionEvent.request).toMatchObject({
- url: expect.stringContaining('/parameterized/1337/beep/42'),
- });
-
- // The transaction should not contain any spans with the same name as the transaction
- // e.g. "GET /parameterized/[one]/beep/[two]"
- expect(
- transactionEvent.spans?.filter(span => {
- return span.description === transactionEvent.transaction;
- }),
- ).toHaveLength(0);
-});
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tsconfig.json b/dev-packages/e2e-tests/test-applications/nextjs-turbo/tsconfig.json
deleted file mode 100644
index 1ed098ed9058..000000000000
--- a/dev-packages/e2e-tests/test-applications/nextjs-turbo/tsconfig.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "compilerOptions": {
- "allowImportingTsExtensions": true,
- "target": "es2018",
- "lib": ["dom", "dom.iterable", "esnext"],
- "allowJs": true,
- "skipLibCheck": true,
- "strict": true,
- "forceConsistentCasingInFileNames": true,
- "noEmit": true,
- "esModuleInterop": true,
- "module": "esnext",
- "moduleResolution": "node",
- "resolveJsonModule": true,
- "isolatedModules": true,
- "jsx": "preserve",
- "plugins": [
- {
- "name": "next"
- }
- ],
- "incremental": true
- },
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "next.config.js", ".next/types/**/*.ts"],
- "exclude": ["node_modules", "playwright.config.ts"]
-}