From 93d6d0018b675a02a1f257f2e207b02e76403b77 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Wed, 29 Jul 2026 13:49:49 +0200 Subject: [PATCH 1/2] copy solidstart --- .../test-applications/solidstart-2/.gitignore | 46 +++++++ .../test-applications/solidstart-2/README.md | 45 +++++++ .../solidstart-2/app.config.ts | 8 ++ .../solidstart-2/package.json | 38 ++++++ .../solidstart-2/playwright.config.mjs | 8 ++ .../solidstart-2/public/favicon.ico | Bin 0 -> 664 bytes .../solidstart-2/src/app.tsx | 22 ++++ .../solidstart-2/src/entry-client.tsx | 19 +++ .../solidstart-2/src/entry-server.tsx | 21 ++++ .../solidstart-2/src/instrument.server.ts | 10 ++ .../solidstart-2/src/middleware.ts | 6 + .../src/routes/back-navigation.tsx | 9 ++ .../solidstart-2/src/routes/client-error.tsx | 15 +++ .../src/routes/error-boundary.tsx | 64 ++++++++++ .../solidstart-2/src/routes/index.tsx | 31 +++++ .../solidstart-2/src/routes/server-error.tsx | 17 +++ .../solidstart-2/src/routes/users/[id].tsx | 21 ++++ .../solidstart-2/start-event-proxy.mjs | 6 + .../solidstart-2/tests/errorboundary.test.ts | 90 +++++++++++++ .../solidstart-2/tests/errors.client.test.ts | 30 +++++ .../solidstart-2/tests/errors.server.test.ts | 30 +++++ .../tests/performance.client.test.ts | 119 ++++++++++++++++++ .../tests/performance.server.test.ts | 55 ++++++++ .../solidstart-2/tsconfig.json | 19 +++ .../solidstart-2/vitest.config.ts | 10 ++ 25 files changed, 739 insertions(+) create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/.gitignore create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/README.md create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/package.json create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/playwright.config.mjs create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/public/favicon.ico create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/app.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-client.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-server.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/instrument.server.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/middleware.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/back-navigation.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/client-error.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/error-boundary.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/index.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/server-error.tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/users/[id].tsx create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/vitest.config.ts diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/.gitignore b/dev-packages/e2e-tests/test-applications/solidstart-2/.gitignore new file mode 100644 index 000000000000..a51ed3c20c8d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/.gitignore @@ -0,0 +1,46 @@ + +dist +.solid +.output +.vercel +.netlify +.vinxi + +# Environment +.env +.env*.local + +# dependencies +/node_modules +/.pnp +.pnp.js + +# IDEs and editors +/.idea +.project +.classpath +*.launch +.settings/ + +# Temp +gitignore + +# testing +/coverage + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +/test-results/ +/playwright-report/ +/playwright/.cache/ + +!*.d.ts diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/README.md b/dev-packages/e2e-tests/test-applications/solidstart-2/README.md new file mode 100644 index 000000000000..9a141e9c2f0d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/README.md @@ -0,0 +1,45 @@ +# SolidStart + +Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com); + +## Creating a project + +```bash +# create a new project in the current directory +npm init solid@latest + +# create a new project in my-app +npm init solid@latest my-app +``` + +## Developing + +Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a +development server: + +```bash +npm run dev + +# or start the server and open the app in a new browser tab +npm run dev -- --open +``` + +## Building + +Solid apps are built with _presets_, which optimise your project for deployment to different environments. + +By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add +it to the `devDependencies` in `package.json` and specify in your `app.config.js`. + +## Testing + +Tests are written with `vitest`, `@solidjs/testing-library` and `@testing-library/jest-dom` to extend expect with some +helpful custom matchers. + +To run them, simply start: + +```sh +npm test +``` + +## This project was created with the [Solid CLI](https://solid-cli.netlify.app) diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts new file mode 100644 index 000000000000..71061cf25d96 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts @@ -0,0 +1,8 @@ +import { withSentry } from '@sentry/solidstart'; +import { defineConfig } from '@solidjs/start/config'; + +export default defineConfig( + withSentry({ + middleware: './src/middleware.ts', + }), +); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/package.json b/dev-packages/e2e-tests/test-applications/solidstart-2/package.json new file mode 100644 index 000000000000..7e382b6dc54b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/package.json @@ -0,0 +1,38 @@ +{ + "name": "solidstart-e2e-testapp", + "version": "0.0.0", + "scripts": { + "clean": "pnpx rimraf node_modules pnpm-lock.yaml .vinxi .output", + "build": "vinxi build", + "preview": "HOST=localhost PORT=3030 vinxi start", + "start:import": "HOST=localhost PORT=3030 node --import ./.output/server/instrument.server.mjs .output/server/index.mjs", + "test:prod": "TEST_ENV=production playwright test", + "test:build": "pnpm install && pnpm build", + "test:assert": "pnpm test:prod" + }, + "type": "module", + "dependencies": { + "@sentry/solidstart": "file:../../packed/sentry-solidstart-packed.tgz" + }, + "devDependencies": { + "@playwright/test": "~1.56.0", + "@sentry-internal/test-utils": "link:../../../test-utils", + "@solidjs/meta": "^0.29.4", + "@solidjs/router": "^0.15.0", + "@solidjs/start": "^1.0.2", + "@solidjs/testing-library": "^0.8.7", + "@testing-library/jest-dom": "^6.4.2", + "@testing-library/user-event": "^14.5.2", + "@vitest/ui": "^1.5.0", + "jsdom": "^24.0.0", + "solid-js": "1.9.5", + "typescript": "^5.4.5", + "vinxi": "^0.4.0", + "vite": "^5.4.11", + "vite-plugin-solid": "^2.11.6", + "vitest": "^1.5.0" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/solidstart-2/playwright.config.mjs new file mode 100644 index 000000000000..ee2ee42980b8 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm start:import', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/public/favicon.ico b/dev-packages/e2e-tests/test-applications/solidstart-2/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..fb282da0719ef6ab4c1732df93be6216b0d85520 GIT binary patch literal 664 zcmV;J0%!e+P)m9ebk1R zejT~~6f_`?;`cEd!+`7(hw@%%2;?RN8gX-L?z6cM( zKoG@&w+0}f@Pfvwc+deid)qgE!L$ENKYjViZC_Zcr>L(`2oXUT8f0mRQ(6-=HN_Ai zeBBEz3WP+1Cw`m!49Wf!MnZzp5bH8VkR~BcJ1s-j90TAS2Yo4j!J|KodxYR%3Numw zA?gq6e`5@!W~F$_De3yt&uspo&2yLb$(NwcPPI-4LGc!}HdY%jfq@AFs8LiZ4k(p} zZ!c9o+qbWYs-Mg zgdyTALzJX&7QXHdI_DPTFL33;w}88{e6Zk)MX0kN{3DX9uz#O_L58&XRH$Nvvu;fO zf&)7@?C~$z1K<>j0ga$$MIg+5xN;eQ?1-CA=`^Y169@Ab6!vcaNP=hxfKN%@Ly^R* zK1iv*s1Yl6_dVyz8>ZqYhz6J4|3fQ@2LQeX@^%W(B~8>=MoEmBEGGD1;gHXlpX>!W ym)!leA2L@`cpb^hy)P75=I!`pBYxP7<2VfQ3j76qLgzIA0000 ( + + SolidStart - with Vitest + {props.children} + + )} + > + + + ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-client.tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-client.tsx new file mode 100644 index 000000000000..d9900ed5689d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-client.tsx @@ -0,0 +1,19 @@ +// @refresh reload +import * as Sentry from '@sentry/solidstart'; +import { solidRouterBrowserTracingIntegration } from '@sentry/solidstart/solidrouter'; +import { StartClient, mount } from '@solidjs/start/client'; + +Sentry.init({ + traceLifecycle: 'static', + // We can't use env variables here, seems like they are stripped + // out in production builds. + dsn: 'https://public@dsn.ingest.sentry.io/1337', + environment: 'qa', // dynamic sampling bias to keep transactions + integrations: [solidRouterBrowserTracingIntegration()], + tunnel: 'http://localhost:3031/', // proxy server + // Performance Monitoring + tracesSampleRate: 1.0, // Capture 100% of the transactions + debug: !!import.meta.env.DEBUG, +}); + +mount(() => , document.getElementById('app')!); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-server.tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-server.tsx new file mode 100644 index 000000000000..276935366318 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/entry-server.tsx @@ -0,0 +1,21 @@ +// @refresh reload +import { StartServer, createHandler } from '@solidjs/start/server'; + +export default createHandler(() => ( + ( + + + + + + {assets} + + +
{children}
+ {scripts} + + + )} + /> +)); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/instrument.server.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/src/instrument.server.ts new file mode 100644 index 000000000000..d89f2566f8be --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/instrument.server.ts @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/solidstart'; + +Sentry.init({ + traceLifecycle: 'static', + dsn: process.env.E2E_TEST_DSN, + environment: 'qa', // dynamic sampling bias to keep transactions + tracesSampleRate: 1.0, // Capture 100% of the transactions + tunnel: 'http://localhost:3031/', // proxy server + debug: !!process.env.DEBUG, +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/middleware.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/src/middleware.ts new file mode 100644 index 000000000000..88123a035fb6 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/middleware.ts @@ -0,0 +1,6 @@ +import { sentryBeforeResponseMiddleware } from '@sentry/solidstart'; +import { createMiddleware } from '@solidjs/start/middleware'; + +export default createMiddleware({ + onBeforeResponse: [sentryBeforeResponseMiddleware()], +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/back-navigation.tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/back-navigation.tsx new file mode 100644 index 000000000000..ddd970944bf3 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/back-navigation.tsx @@ -0,0 +1,9 @@ +import { A } from '@solidjs/router'; + +export default function BackNavigation() { + return ( + + User 6 + + ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/client-error.tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/client-error.tsx new file mode 100644 index 000000000000..5e405e8c4e40 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/client-error.tsx @@ -0,0 +1,15 @@ +export default function ClientErrorPage() { + return ( +
+ +
+ ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/error-boundary.tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/error-boundary.tsx new file mode 100644 index 000000000000..b22607667e7e --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/error-boundary.tsx @@ -0,0 +1,64 @@ +import * as Sentry from '@sentry/solidstart'; +import type { ParentProps } from 'solid-js'; +import { ErrorBoundary, createSignal, onMount } from 'solid-js'; + +const SentryErrorBoundary = Sentry.withSentryErrorBoundary(ErrorBoundary); + +const [count, setCount] = createSignal(1); +const [caughtError, setCaughtError] = createSignal(false); + +export default function ErrorBoundaryTestPage() { + return ( + + {caughtError() && ( + + )} +
+
+ +
+
+
+ ); +} + +function Throw(props: { error: string }) { + onMount(() => { + throw new Error(props.error); + }); + return null; +} + +function SampleErrorBoundary(props: ParentProps) { + return ( + ( +
+

Error Boundary Fallback

+
+ {error.message} +
+ +
+ )} + > + {props.children} +
+ ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/index.tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/index.tsx new file mode 100644 index 000000000000..9a0b22cc38c6 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/index.tsx @@ -0,0 +1,31 @@ +import { A } from '@solidjs/router'; + +export default function Home() { + return ( + <> +

Welcome to Solid Start

+

+ Visit docs.solidjs.com/solid-start to read the documentation +

+ + + ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/server-error.tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/server-error.tsx new file mode 100644 index 000000000000..05dce5e10a56 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/server-error.tsx @@ -0,0 +1,17 @@ +import { withServerActionInstrumentation } from '@sentry/solidstart'; +import { createAsync } from '@solidjs/router'; + +const getPrefecture = async () => { + 'use server'; + return await withServerActionInstrumentation('getPrefecture', () => { + throw new Error('Error thrown from Solid Start E2E test app server route'); + + return { prefecture: 'Kanagawa' }; + }); +}; + +export default function ServerErrorPage() { + const data = createAsync(() => getPrefecture()); + + return
Prefecture: {data()?.prefecture}
; +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/users/[id].tsx b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/users/[id].tsx new file mode 100644 index 000000000000..22abd3ba8803 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/src/routes/users/[id].tsx @@ -0,0 +1,21 @@ +import { withServerActionInstrumentation } from '@sentry/solidstart'; +import { createAsync, useParams } from '@solidjs/router'; + +const getPrefecture = async () => { + 'use server'; + return await withServerActionInstrumentation('getPrefecture', () => { + return { prefecture: 'Ehime' }; + }); +}; +export default function User() { + const params = useParams(); + const userData = createAsync(() => getPrefecture()); + + return ( +
+ User ID: {params.id} +
+ Prefecture: {userData()?.prefecture} +
+ ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs new file mode 100644 index 000000000000..d45a7a013f36 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'solidstart', +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts new file mode 100644 index 000000000000..9b169d6abda4 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts @@ -0,0 +1,90 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('captures an exception', async ({ page }) => { + const errorEventPromise = waitForError('solidstart', errorEvent => { + return ( + !errorEvent.type && + errorEvent.exception?.values?.[0]?.value === + 'Error 1 thrown from Sentry ErrorBoundary in Solid Start E2E test app' + ); + }); + + await page.goto('/error-boundary'); + await page.locator('#caughtErrorBtn').click(); + const errorEvent = await errorEventPromise; + + expect(errorEvent).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Error 1 thrown from Sentry ErrorBoundary in Solid Start E2E test app', + mechanism: { + type: 'auto.function.solid.error_boundary', + handled: true, + }, + }, + ], + }, + transaction: '/error-boundary', + }); +}); + +test('captures a second exception after resetting the boundary', async ({ page }) => { + const firstErrorEventPromise = waitForError('solidstart', errorEvent => { + return ( + !errorEvent.type && + errorEvent.exception?.values?.[0]?.value === + 'Error 1 thrown from Sentry ErrorBoundary in Solid Start E2E test app' + ); + }); + + await page.goto('/error-boundary'); + await page.locator('#caughtErrorBtn').click(); + const firstErrorEvent = await firstErrorEventPromise; + + expect(firstErrorEvent).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Error 1 thrown from Sentry ErrorBoundary in Solid Start E2E test app', + mechanism: { + type: 'auto.function.solid.error_boundary', + handled: true, + }, + }, + ], + }, + transaction: '/error-boundary', + }); + + const secondErrorEventPromise = waitForError('solidstart', errorEvent => { + return ( + !errorEvent.type && + errorEvent.exception?.values?.[0]?.value === + 'Error 2 thrown from Sentry ErrorBoundary in Solid Start E2E test app' + ); + }); + + await page.locator('#errorBoundaryResetBtn').click(); + await page.locator('#caughtErrorBtn').click(); + const secondErrorEvent = await secondErrorEventPromise; + + expect(secondErrorEvent).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Error 2 thrown from Sentry ErrorBoundary in Solid Start E2E test app', + mechanism: { + type: 'auto.function.solid.error_boundary', + handled: true, + }, + }, + ], + }, + transaction: '/error-boundary', + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts new file mode 100644 index 000000000000..e2b00786f54c --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test.describe('client-side errors', () => { + test('captures error thrown on click', async ({ page }) => { + const errorPromise = waitForError('solidstart', async errorEvent => { + return errorEvent?.exception?.values?.[0]?.value === 'Uncaught error thrown from Solid Start E2E test app'; + }); + + await page.goto(`/client-error`); + await page.locator('#errorBtn').click(); + const error = await errorPromise; + + expect(error).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Uncaught error thrown from Solid Start E2E test app', + mechanism: { + handled: false, + }, + }, + ], + }, + transaction: '/client-error', + }); + expect(error.transaction).toEqual('/client-error'); + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts new file mode 100644 index 000000000000..7bf86b364da9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test.describe('server-side errors', () => { + test('captures server action error', async ({ page }) => { + const errorEventPromise = waitForError('solidstart', errorEvent => { + return errorEvent?.exception?.values?.[0]?.value === 'Error thrown from Solid Start E2E test app server route'; + }); + + await page.goto(`/server-error`); + + const error = await errorEventPromise; + + expect(error).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Error thrown from Solid Start E2E test app server route', + mechanism: { + type: 'auto.function.solidstart', + handled: false, + }, + }, + ], + }, + transaction: 'GET /server-error', + }); + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts new file mode 100644 index 000000000000..aec390512674 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts @@ -0,0 +1,119 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('sends a pageload transaction', async ({ page }) => { + const transactionPromise = waitForTransaction('solidstart', async transactionEvent => { + return transactionEvent?.transaction === '/' && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + await page.goto('/'); + const pageloadTransaction = await transactionPromise; + + expect(pageloadTransaction).toMatchObject({ + contexts: { + trace: { + op: 'pageload', + origin: 'auto.pageload.browser', + data: { + 'sentry.source': 'route', + 'url.template': '/', + 'url.path': '/', + 'url.full': expect.stringMatching(/^https?:\/\/localhost:\d+\/$/), + }, + }, + }, + transaction: '/', + transaction_info: { + source: 'route', + }, + }); +}); + +test('sends a navigation transaction with parametrized route', async ({ page }) => { + const transactionPromise = waitForTransaction('solidstart', async transactionEvent => { + return transactionEvent?.transaction === '/users/:id' && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + await page.goto(`/`); + await page.locator('#navLink').click(); + const navigationTransaction = await transactionPromise; + + expect(navigationTransaction).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.solidstart.solidrouter', + data: { + 'sentry.source': 'route', + 'url.template': '/users/:id', + 'url.path': '/users/5', + 'url.full': expect.stringMatching(/^https?:\/\/localhost:\d+\/users\/5$/), + }, + }, + }, + transaction: '/users/:id', + transaction_info: { + source: 'route', + }, + }); +}); + +test('updates the transaction when using the back button', async ({ page }) => { + // Solid Router sends a `-1` navigation when using the back button. + // The sentry solidRouterBrowserTracingIntegration tries to update such + // transactions with the proper name once the `useLocation` hook triggers. + const navigationTxnPromise = waitForTransaction('solidstart', async transactionEvent => { + return transactionEvent?.transaction === '/users/:id' && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + await page.goto(`/back-navigation`); + await page.locator('#navLink').click(); + const navigationTxn = await navigationTxnPromise; + + expect(navigationTxn).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.solidstart.solidrouter', + data: { + 'sentry.source': 'route', + 'url.template': '/users/:id', + 'url.path': '/users/6', + 'url.full': expect.stringMatching(/^https?:\/\/localhost:\d+\/users\/6$/), + }, + }, + }, + transaction: '/users/:id', + transaction_info: { + source: 'route', + }, + }); + + const backNavigationTxnPromise = waitForTransaction('solidstart', async transactionEvent => { + return ( + transactionEvent?.transaction === '/back-navigation' && transactionEvent.contexts?.trace?.op === 'navigation' + ); + }); + + await page.goBack(); + const backNavigationTxn = await backNavigationTxnPromise; + + expect(backNavigationTxn).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.solidstart.solidrouter', + data: { + 'sentry.source': 'route', + 'url.template': '/back-navigation', + 'url.path': '/back-navigation', + 'url.full': expect.stringMatching(/^https?:\/\/localhost:\d+\/back-navigation$/), + }, + }, + }, + transaction: '/back-navigation', + transaction_info: { + source: 'route', + }, + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts new file mode 100644 index 000000000000..a86f5b5af68c --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts @@ -0,0 +1,55 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; +import { + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, +} from '@sentry/solidstart'; + +test('sends a server action transaction on pageload', async ({ page }) => { + const transactionPromise = waitForTransaction('solidstart', transactionEvent => { + return transactionEvent?.transaction === 'GET /users/6'; + }); + + await page.goto('/users/6'); + + const transaction = await transactionPromise; + + expect(transaction.spans).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + description: 'getPrefecture', + data: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.server_action', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.solidstart', + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + }, + }), + ]), + ); +}); + +test('sends a server action transaction on client navigation', async ({ page }) => { + const transactionPromise = waitForTransaction('solidstart', transactionEvent => { + return transactionEvent?.transaction === 'POST getPrefecture'; + }); + + await page.goto('/'); + await page.locator('#navLink').click(); + await page.waitForURL('/users/5'); + + const transaction = await transactionPromise; + + expect(transaction.spans).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + description: 'getPrefecture', + data: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.server_action', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.solidstart', + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + }, + }), + ]), + ); +}); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json b/dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json new file mode 100644 index 000000000000..6f11292cc5d8 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "allowJs": true, + "strict": true, + "noEmit": true, + "types": ["vinxi/types/client", "vitest/globals", "@testing-library/jest-dom"], + "isolatedModules": true, + "paths": { + "~/*": ["./src/*"] + } + } +} diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/vitest.config.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/vitest.config.ts new file mode 100644 index 000000000000..6c2b639dc300 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/vitest.config.ts @@ -0,0 +1,10 @@ +import solid from 'vite-plugin-solid'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [solid()], + resolve: { + conditions: ['development', 'browser'], + }, + envPrefix: 'PUBLIC_', +}); From 6afbaaff000caf615469b11d63a2259f06d5d39d Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Wed, 29 Jul 2026 14:13:56 +0200 Subject: [PATCH 2/2] test(e2e): Add optional SolidStart 2 E2E test --- .../solidstart-2/app.config.ts | 8 ----- .../solidstart-2/package.json | 32 ++++++++++++------- .../solidstart-2/start-event-proxy.mjs | 2 +- .../solidstart-2/tests/errorboundary.test.ts | 6 ++-- .../solidstart-2/tests/errors.client.test.ts | 2 +- .../solidstart-2/tests/errors.server.test.ts | 2 +- .../tests/performance.client.test.ts | 8 ++--- .../tests/performance.server.test.ts | 4 +-- .../solidstart-2/tsconfig.json | 2 +- .../solidstart-2/vite.config.ts | 13 ++++++++ 10 files changed, 46 insertions(+), 33 deletions(-) delete mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/solidstart-2/vite.config.ts diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts deleted file mode 100644 index 71061cf25d96..000000000000 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/app.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { withSentry } from '@sentry/solidstart'; -import { defineConfig } from '@solidjs/start/config'; - -export default defineConfig( - withSentry({ - middleware: './src/middleware.ts', - }), -); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/package.json b/dev-packages/e2e-tests/test-applications/solidstart-2/package.json index 7e382b6dc54b..04c1fadeb65e 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/package.json +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/package.json @@ -1,10 +1,11 @@ { - "name": "solidstart-e2e-testapp", + "name": "solidstart-2", "version": "0.0.0", + "//": "In the build script, the instrument.server.ts file is copied to the .output/server dir. Ideally, this is done in the SDK.", "scripts": { - "clean": "pnpx rimraf node_modules pnpm-lock.yaml .vinxi .output", - "build": "vinxi build", - "preview": "HOST=localhost PORT=3030 vinxi start", + "clean": "pnpx rimraf node_modules pnpm-lock.yaml .nitro .output", + "build": "vite build && cp src/instrument.server.ts .output/server/instrument.server.mjs", + "preview": "HOST=localhost PORT=3030 vite preview", "start:import": "HOST=localhost PORT=3030 node --import ./.output/server/instrument.server.mjs .output/server/index.mjs", "test:prod": "TEST_ENV=production playwright test", "test:build": "pnpm install && pnpm build", @@ -12,27 +13,34 @@ }, "type": "module", "dependencies": { - "@sentry/solidstart": "file:../../packed/sentry-solidstart-packed.tgz" + "@sentry/solidstart": "file:../../packed/sentry-solidstart-packed.tgz", + "nitro": "3.0.260610-beta" }, "devDependencies": { "@playwright/test": "~1.56.0", "@sentry-internal/test-utils": "link:../../../test-utils", "@solidjs/meta": "^0.29.4", - "@solidjs/router": "^0.15.0", - "@solidjs/start": "^1.0.2", - "@solidjs/testing-library": "^0.8.7", + "@solidjs/router": "^1.0.0", + "@solidjs/start": "2.0.0-rc.6", + "@solidjs/testing-library": "^0.8.10", "@testing-library/jest-dom": "^6.4.2", "@testing-library/user-event": "^14.5.2", "@vitest/ui": "^1.5.0", "jsdom": "^24.0.0", - "solid-js": "1.9.5", + "solid-js": "1.9.14", "typescript": "^5.4.5", - "vinxi": "^0.4.0", - "vite": "^5.4.11", + "vite": "^8.1.5", "vite-plugin-solid": "^2.11.6", "vitest": "^1.5.0" }, "volta": { - "extends": "../../package.json" + "extends": "../../package.json", + "node": "24.15.0" + }, + "engines": { + "node": ">=24" + }, + "sentryTest": { + "optional": true } } diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs index d45a7a013f36..73a54a8041b6 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/start-event-proxy.mjs @@ -2,5 +2,5 @@ import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, - proxyServerName: 'solidstart', + proxyServerName: 'solidstart-2', }); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts index 9b169d6abda4..29a14c813eaf 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errorboundary.test.ts @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test'; import { waitForError } from '@sentry-internal/test-utils'; test('captures an exception', async ({ page }) => { - const errorEventPromise = waitForError('solidstart', errorEvent => { + const errorEventPromise = waitForError('solidstart-2', errorEvent => { return ( !errorEvent.type && errorEvent.exception?.values?.[0]?.value === @@ -32,7 +32,7 @@ test('captures an exception', async ({ page }) => { }); test('captures a second exception after resetting the boundary', async ({ page }) => { - const firstErrorEventPromise = waitForError('solidstart', errorEvent => { + const firstErrorEventPromise = waitForError('solidstart-2', errorEvent => { return ( !errorEvent.type && errorEvent.exception?.values?.[0]?.value === @@ -60,7 +60,7 @@ test('captures a second exception after resetting the boundary', async ({ page } transaction: '/error-boundary', }); - const secondErrorEventPromise = waitForError('solidstart', errorEvent => { + const secondErrorEventPromise = waitForError('solidstart-2', errorEvent => { return ( !errorEvent.type && errorEvent.exception?.values?.[0]?.value === diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts index e2b00786f54c..ddf0328daba9 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.client.test.ts @@ -3,7 +3,7 @@ import { waitForError } from '@sentry-internal/test-utils'; test.describe('client-side errors', () => { test('captures error thrown on click', async ({ page }) => { - const errorPromise = waitForError('solidstart', async errorEvent => { + const errorPromise = waitForError('solidstart-2', async errorEvent => { return errorEvent?.exception?.values?.[0]?.value === 'Uncaught error thrown from Solid Start E2E test app'; }); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts index 7bf86b364da9..e9ad17f9cb30 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/errors.server.test.ts @@ -3,7 +3,7 @@ import { waitForError } from '@sentry-internal/test-utils'; test.describe('server-side errors', () => { test('captures server action error', async ({ page }) => { - const errorEventPromise = waitForError('solidstart', errorEvent => { + const errorEventPromise = waitForError('solidstart-2', errorEvent => { return errorEvent?.exception?.values?.[0]?.value === 'Error thrown from Solid Start E2E test app server route'; }); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts index aec390512674..9052b6b1e179 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.client.test.ts @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test'; import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction', async ({ page }) => { - const transactionPromise = waitForTransaction('solidstart', async transactionEvent => { + const transactionPromise = waitForTransaction('solidstart-2', async transactionEvent => { return transactionEvent?.transaction === '/' && transactionEvent.contexts?.trace?.op === 'pageload'; }); @@ -30,7 +30,7 @@ test('sends a pageload transaction', async ({ page }) => { }); test('sends a navigation transaction with parametrized route', async ({ page }) => { - const transactionPromise = waitForTransaction('solidstart', async transactionEvent => { + const transactionPromise = waitForTransaction('solidstart-2', async transactionEvent => { return transactionEvent?.transaction === '/users/:id' && transactionEvent.contexts?.trace?.op === 'navigation'; }); @@ -62,7 +62,7 @@ test('updates the transaction when using the back button', async ({ page }) => { // Solid Router sends a `-1` navigation when using the back button. // The sentry solidRouterBrowserTracingIntegration tries to update such // transactions with the proper name once the `useLocation` hook triggers. - const navigationTxnPromise = waitForTransaction('solidstart', async transactionEvent => { + const navigationTxnPromise = waitForTransaction('solidstart-2', async transactionEvent => { return transactionEvent?.transaction === '/users/:id' && transactionEvent.contexts?.trace?.op === 'navigation'; }); @@ -89,7 +89,7 @@ test('updates the transaction when using the back button', async ({ page }) => { }, }); - const backNavigationTxnPromise = waitForTransaction('solidstart', async transactionEvent => { + const backNavigationTxnPromise = waitForTransaction('solidstart-2', async transactionEvent => { return ( transactionEvent?.transaction === '/back-navigation' && transactionEvent.contexts?.trace?.op === 'navigation' ); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts index a86f5b5af68c..1a4fd8c80e30 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tests/performance.server.test.ts @@ -7,7 +7,7 @@ import { } from '@sentry/solidstart'; test('sends a server action transaction on pageload', async ({ page }) => { - const transactionPromise = waitForTransaction('solidstart', transactionEvent => { + const transactionPromise = waitForTransaction('solidstart-2', transactionEvent => { return transactionEvent?.transaction === 'GET /users/6'; }); @@ -30,7 +30,7 @@ test('sends a server action transaction on pageload', async ({ page }) => { }); test('sends a server action transaction on client navigation', async ({ page }) => { - const transactionPromise = waitForTransaction('solidstart', transactionEvent => { + const transactionPromise = waitForTransaction('solidstart-2', transactionEvent => { return transactionEvent?.transaction === 'POST getPrefecture'; }); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json b/dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json index 6f11292cc5d8..950c6e08e1ac 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/tsconfig.json @@ -10,7 +10,7 @@ "allowJs": true, "strict": true, "noEmit": true, - "types": ["vinxi/types/client", "vitest/globals", "@testing-library/jest-dom"], + "types": ["@solidjs/start/env", "vitest/globals", "@testing-library/jest-dom"], "isolatedModules": true, "paths": { "~/*": ["./src/*"] diff --git a/dev-packages/e2e-tests/test-applications/solidstart-2/vite.config.ts b/dev-packages/e2e-tests/test-applications/solidstart-2/vite.config.ts new file mode 100644 index 000000000000..cd48af8a04db --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidstart-2/vite.config.ts @@ -0,0 +1,13 @@ +import { solidStart } from '@solidjs/start/config'; +import { nitro } from 'nitro/vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [ + solidStart({ + appRoot: './src', + middleware: './src/middleware.ts', + }), + nitro(), + ], +});