From 485877e5df7ce4e63d92fdbf700c4adc61a00f89 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:36:58 +0200 Subject: [PATCH 1/3] add minimal hono starter --- .../test-applications/hono-4-cf/.gitignore | 33 ++++++++++++++++ .../test-applications/hono-4-cf/package.json | 15 ++++++++ .../test-applications/hono-4-cf/src/index.ts | 9 +++++ .../test-applications/hono-4-cf/tsconfig.json | 12 ++++++ .../hono-4-cf/wrangler.jsonc | 38 +++++++++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/package.json create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore b/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore new file mode 100644 index 000000000000..e319e0635f90 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore @@ -0,0 +1,33 @@ +# prod +dist/ + +# dev +.yarn/ +!.yarn/releases +.vscode/* +!.vscode/launch.json +!.vscode/*.code-snippets +.idea/workspace.xml +.idea/usage.statistics.xml +.idea/shelf + +# deps +node_modules/ +.wrangler + +# env +.env +.env.production +.dev.vars + +# logs +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# misc +.DS_Store diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json b/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json new file mode 100644 index 000000000000..e6faf399daf7 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json @@ -0,0 +1,15 @@ +{ + "name": "hono-4-cf", + "type": "module", + "scripts": { + "dev": "wrangler dev", + "deploy": "wrangler deploy --minify", + "cf-typegen": "wrangler types --env-interface CloudflareBindings" + }, + "dependencies": { + "hono": "^4.12.14" + }, + "devDependencies": { + "wrangler": "^4.4.0" + } +} diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts b/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts new file mode 100644 index 000000000000..152196c64ccc --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts @@ -0,0 +1,9 @@ +import { Hono } from 'hono'; + +const app = new Hono(); + +app.get('/', c => { + return c.text('Hello Hono!'); +}); + +export default app; diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json b/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json new file mode 100644 index 000000000000..5e1f025cc70d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "skipLibCheck": true, + "lib": ["ESNext"], + "jsx": "react-jsx", + "jsxImportSource": "hono/jsx" + } +} diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc b/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc new file mode 100644 index 000000000000..92cc7c6a4ebb --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc @@ -0,0 +1,38 @@ +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "hono-4-cf", + "main": "src/index.ts", + "compatibility_date": "2026-04-20", + // "compatibility_flags": [ + // "nodejs_compat" + // ], + // "vars": { + // "MY_VAR": "my-variable" + // }, + // "kv_namespaces": [ + // { + // "binding": "MY_KV_NAMESPACE", + // "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + // } + // ], + // "r2_buckets": [ + // { + // "binding": "MY_BUCKET", + // "bucket_name": "my-bucket" + // } + // ], + // "d1_databases": [ + // { + // "binding": "MY_DB", + // "database_name": "my-database", + // "database_id": "" + // } + // ], + // "ai": { + // "binding": "AI" + // }, + // "observability": { + // "enabled": true, + // "head_sampling_rate": 1 + // } +} From 4450bb67df3593c340642df8bb74c9a6fae36732 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:56:07 +0200 Subject: [PATCH 2/3] test(hono): Add E2E test for Hono on Cloudflare --- .../test-applications/hono-4-cf/.gitignore | 3 ++ .../test-applications/hono-4-cf/.npmrc | 2 + .../test-applications/hono-4-cf/package.json | 19 +++++-- .../hono-4-cf/playwright.config.ts | 22 ++++++++ .../test-applications/hono-4-cf/src/index.ts | 28 +++++++++- .../hono-4-cf/start-event-proxy.mjs | 6 +++ .../hono-4-cf/tests/errors.test.ts | 52 +++++++++++++++++++ .../hono-4-cf/tests/tracing.test.ts | 39 ++++++++++++++ .../test-applications/hono-4-cf/tsconfig.json | 3 +- .../hono-4-cf/wrangler.jsonc | 33 +----------- 10 files changed, 170 insertions(+), 37 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/.npmrc create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/tests/errors.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/tests/tracing.test.ts diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore b/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore index e319e0635f90..534f51704346 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore @@ -29,5 +29,8 @@ yarn-error.log* pnpm-debug.log* lerna-debug.log* +# test +test-results + # misc .DS_Store diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/.npmrc b/dev-packages/e2e-tests/test-applications/hono-4-cf/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/.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/hono-4-cf/package.json b/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json index e6faf399daf7..415b93d32424 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json @@ -1,15 +1,28 @@ { "name": "hono-4-cf", "type": "module", + "version": "0.0.0", + "private": true, "scripts": { - "dev": "wrangler dev", + "dev": "wrangler dev --var \"E2E_TEST_DSN:$E2E_TEST_DSN\" --log-level=$(test $CI && echo 'none' || echo 'log')", + "build": "wrangler deploy --dry-run", "deploy": "wrangler deploy --minify", - "cf-typegen": "wrangler types --env-interface CloudflareBindings" + "cf-typegen": "wrangler types --env-interface CloudflareBindings", + "test:build": "pnpm install && pnpm build", + "test:assert": "TEST_ENV=production playwright test" }, "dependencies": { + "@sentry/hono": "latest || *", "hono": "^4.12.14" }, "devDependencies": { - "wrangler": "^4.4.0" + "@playwright/test": "~1.56.0", + "@cloudflare/workers-types": "^4.20240725.0", + "@sentry-internal/test-utils": "link:../../../test-utils", + "typescript": "^5.5.2", + "wrangler": "^4.61.0" + }, + "volta": { + "extends": "../../package.json" } } diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/playwright.config.ts b/dev-packages/e2e-tests/test-applications/hono-4-cf/playwright.config.ts new file mode 100644 index 000000000000..1cca1e0ee184 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/playwright.config.ts @@ -0,0 +1,22 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const testEnv = process.env.TEST_ENV; + +if (!testEnv) { + throw new Error('No test env defined'); +} + +const APP_PORT = 38787; + +const config = getPlaywrightConfig( + { + startCommand: `pnpm dev --port ${APP_PORT}`, + port: APP_PORT, + }, + { + workers: '100%', + retries: 0, + }, +); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts b/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts index 152196c64ccc..b8ebd909821a 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts @@ -1,9 +1,35 @@ import { Hono } from 'hono'; +import { HTTPException } from 'hono/http-exception'; +import { sentry } from '@sentry/hono/cloudflare'; -const app = new Hono(); +const app = new Hono<{ Bindings: { E2E_TEST_DSN: string } }>(); + +app.use( + sentry(app, env => ({ + dsn: env.E2E_TEST_DSN, + environment: 'qa', + tracesSampleRate: 1.0, + tunnel: 'http://localhost:3031/', // proxy server + })), +); app.get('/', c => { return c.text('Hello Hono!'); }); +app.get('/test-param/:paramId', c => { + return c.json({ paramId: c.req.param('paramId') }); +}); + +app.get('/error/:cause', c => { + throw new Error('This is a test error for Sentry!', { + cause: c.req.param('cause'), + }); +}); + +app.get('/http-exception/:code', c => { + const code = Number(c.req.param('code')) as Parameters[0]; + throw new HTTPException(code, { message: `HTTPException ${code}` }); +}); + export default app; diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/hono-4-cf/start-event-proxy.mjs new file mode 100644 index 000000000000..bccc9f3be95a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'hono-4-cf', +}); diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/errors.test.ts new file mode 100644 index 000000000000..56d7fb599045 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/errors.test.ts @@ -0,0 +1,52 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('captures error thrown in route handler', async ({ baseURL }) => { + const errorWaiter = waitForError('hono-4-cf', event => { + return event.exception?.values?.[0]?.value === 'This is a test error for Sentry!'; + }); + + const response = await fetch(`${baseURL}/error/test-cause`); + expect(response.status).toBe(500); + + const event = await errorWaiter; + expect(event.exception?.values?.[0]?.value).toBe('This is a test error for Sentry!'); +}); + +test('captures HTTPException with 502 status', async ({ baseURL }) => { + const errorWaiter = waitForError('hono-4-cf', event => { + return event.exception?.values?.[0]?.value === 'HTTPException 502'; + }); + + const response = await fetch(`${baseURL}/http-exception/502`); + expect(response.status).toBe(502); + + const event = await errorWaiter; + expect(event.exception?.values?.[0]?.value).toBe('HTTPException 502'); +}); + +// TODO: 401 and 404 HTTPExceptions should not be captured by Sentry by default, +// but currently they are. Fix the filtering and update these tests accordingly. +test('captures HTTPException with 401 status', async ({ baseURL }) => { + const errorWaiter = waitForError('hono-4-cf', event => { + return event.exception?.values?.[0]?.value === 'HTTPException 401'; + }); + + const response = await fetch(`${baseURL}/http-exception/401`); + expect(response.status).toBe(401); + + const event = await errorWaiter; + expect(event.exception?.values?.[0]?.value).toBe('HTTPException 401'); +}); + +test('captures HTTPException with 404 status', async ({ baseURL }) => { + const errorWaiter = waitForError('hono-4-cf', event => { + return event.exception?.values?.[0]?.value === 'HTTPException 404'; + }); + + const response = await fetch(`${baseURL}/http-exception/404`); + expect(response.status).toBe(404); + + const event = await errorWaiter; + expect(event.exception?.values?.[0]?.value).toBe('HTTPException 404'); +}); diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/tracing.test.ts b/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/tracing.test.ts new file mode 100644 index 000000000000..b2ac26c89d44 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/tracing.test.ts @@ -0,0 +1,39 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('sends a transaction for the index route', async ({ baseURL }) => { + const transactionWaiter = waitForTransaction('hono-4-cf', event => { + return event.transaction === 'GET /'; + }); + + const response = await fetch(`${baseURL}/`); + expect(response.status).toBe(200); + + const transaction = await transactionWaiter; + expect(transaction.contexts?.trace?.op).toBe('http.server'); +}); + +test('sends a transaction for a parameterized route', async ({ baseURL }) => { + const transactionWaiter = waitForTransaction('hono-4-cf', event => { + return event.transaction === 'GET /test-param/:paramId'; + }); + + const response = await fetch(`${baseURL}/test-param/123`); + expect(response.status).toBe(200); + + const transaction = await transactionWaiter; + expect(transaction.contexts?.trace?.op).toBe('http.server'); + expect(transaction.transaction).toBe('GET /test-param/:paramId'); +}); + +test('sends a transaction for a route that throws', async ({ baseURL }) => { + const transactionWaiter = waitForTransaction('hono-4-cf', event => { + return event.transaction === 'GET /error/:cause'; + }); + + await fetch(`${baseURL}/error/test-cause`); + + const transaction = await transactionWaiter; + expect(transaction.contexts?.trace?.op).toBe('http.server'); + expect(transaction.contexts?.trace?.status).toBe('internal_error'); +}); diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json b/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json index 5e1f025cc70d..3c4abeff44d6 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json @@ -7,6 +7,7 @@ "skipLibCheck": true, "lib": ["ESNext"], "jsx": "react-jsx", - "jsxImportSource": "hono/jsx" + "jsxImportSource": "hono/jsx", + "types": ["@cloudflare/workers-types"] } } diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc b/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc index 92cc7c6a4ebb..2ac330d50b1d 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc +++ b/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc @@ -3,36 +3,5 @@ "name": "hono-4-cf", "main": "src/index.ts", "compatibility_date": "2026-04-20", - // "compatibility_flags": [ - // "nodejs_compat" - // ], - // "vars": { - // "MY_VAR": "my-variable" - // }, - // "kv_namespaces": [ - // { - // "binding": "MY_KV_NAMESPACE", - // "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - // } - // ], - // "r2_buckets": [ - // { - // "binding": "MY_BUCKET", - // "bucket_name": "my-bucket" - // } - // ], - // "d1_databases": [ - // { - // "binding": "MY_DB", - // "database_name": "my-database", - // "database_id": "" - // } - // ], - // "ai": { - // "binding": "AI" - // }, - // "observability": { - // "enabled": true, - // "head_sampling_rate": 1 - // } + "compatibility_flags": ["nodejs_compat"], } From 02d982e4274c1f3231d91569c095f3a60327bead Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:30:39 +0200 Subject: [PATCH 3/3] add test variants (cf, node, bun) --- .github/workflows/build.yml | 4 +- .../test-applications/hono-4-cf/package.json | 28 ------------ .../test-applications/hono-4-cf/src/index.ts | 35 --------------- .../{hono-4-cf => hono-4}/.gitignore | 0 .../{hono-4-cf => hono-4}/.npmrc | 0 .../test-applications/hono-4/package.json | 43 +++++++++++++++++++ .../playwright.config.ts | 12 +++++- .../test-applications/hono-4/src/entry.bun.ts | 24 +++++++++++ .../hono-4/src/entry.cloudflare.ts | 18 ++++++++ .../hono-4/src/entry.node.ts | 24 +++++++++++ .../test-applications/hono-4/src/routes.ts | 24 +++++++++++ .../start-event-proxy.mjs | 2 +- .../tests/errors.test.ts | 10 +++-- .../tests/tracing.test.ts | 8 ++-- .../{hono-4-cf => hono-4}/tsconfig.json | 0 .../{hono-4-cf => hono-4}/wrangler.jsonc | 4 +- 16 files changed, 161 insertions(+), 75 deletions(-) delete mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/package.json delete mode 100644 dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/.gitignore (100%) rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/.npmrc (100%) create mode 100644 dev-packages/e2e-tests/test-applications/hono-4/package.json rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/playwright.config.ts (52%) create mode 100644 dev-packages/e2e-tests/test-applications/hono-4/src/entry.bun.ts create mode 100644 dev-packages/e2e-tests/test-applications/hono-4/src/entry.cloudflare.ts create mode 100644 dev-packages/e2e-tests/test-applications/hono-4/src/entry.node.ts create mode 100644 dev-packages/e2e-tests/test-applications/hono-4/src/routes.ts rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/start-event-proxy.mjs (77%) rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/tests/errors.test.ts (87%) rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/tests/tracing.test.ts (84%) rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/tsconfig.json (100%) rename dev-packages/e2e-tests/test-applications/{hono-4-cf => hono-4}/wrangler.jsonc (71%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 544bb7900008..d686f8293158 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -930,7 +930,9 @@ jobs: with: node-version-file: 'dev-packages/e2e-tests/test-applications/${{ matrix.test-application }}/package.json' - name: Set up Bun - if: contains(fromJSON('["node-exports-test-app","nextjs-16-bun", "elysia-bun"]'), matrix.test-application) + if: + contains(fromJSON('["node-exports-test-app","nextjs-16-bun", "elysia-bun", "hono-4"]'), + matrix.test-application) uses: oven-sh/setup-bun@v2 - name: Set up AWS SAM if: matrix.test-application == 'aws-serverless' diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json b/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json deleted file mode 100644 index 415b93d32424..000000000000 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "hono-4-cf", - "type": "module", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "wrangler dev --var \"E2E_TEST_DSN:$E2E_TEST_DSN\" --log-level=$(test $CI && echo 'none' || echo 'log')", - "build": "wrangler deploy --dry-run", - "deploy": "wrangler deploy --minify", - "cf-typegen": "wrangler types --env-interface CloudflareBindings", - "test:build": "pnpm install && pnpm build", - "test:assert": "TEST_ENV=production playwright test" - }, - "dependencies": { - "@sentry/hono": "latest || *", - "hono": "^4.12.14" - }, - "devDependencies": { - "@playwright/test": "~1.56.0", - "@cloudflare/workers-types": "^4.20240725.0", - "@sentry-internal/test-utils": "link:../../../test-utils", - "typescript": "^5.5.2", - "wrangler": "^4.61.0" - }, - "volta": { - "extends": "../../package.json" - } -} diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts b/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts deleted file mode 100644 index b8ebd909821a..000000000000 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/src/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Hono } from 'hono'; -import { HTTPException } from 'hono/http-exception'; -import { sentry } from '@sentry/hono/cloudflare'; - -const app = new Hono<{ Bindings: { E2E_TEST_DSN: string } }>(); - -app.use( - sentry(app, env => ({ - dsn: env.E2E_TEST_DSN, - environment: 'qa', - tracesSampleRate: 1.0, - tunnel: 'http://localhost:3031/', // proxy server - })), -); - -app.get('/', c => { - return c.text('Hello Hono!'); -}); - -app.get('/test-param/:paramId', c => { - return c.json({ paramId: c.req.param('paramId') }); -}); - -app.get('/error/:cause', c => { - throw new Error('This is a test error for Sentry!', { - cause: c.req.param('cause'), - }); -}); - -app.get('/http-exception/:code', c => { - const code = Number(c.req.param('code')) as Parameters[0]; - throw new HTTPException(code, { message: `HTTPException ${code}` }); -}); - -export default app; diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore b/dev-packages/e2e-tests/test-applications/hono-4/.gitignore similarity index 100% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/.gitignore rename to dev-packages/e2e-tests/test-applications/hono-4/.gitignore diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/.npmrc b/dev-packages/e2e-tests/test-applications/hono-4/.npmrc similarity index 100% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/.npmrc rename to dev-packages/e2e-tests/test-applications/hono-4/.npmrc diff --git a/dev-packages/e2e-tests/test-applications/hono-4/package.json b/dev-packages/e2e-tests/test-applications/hono-4/package.json new file mode 100644 index 000000000000..117555f7241f --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4/package.json @@ -0,0 +1,43 @@ +{ + "name": "hono-4", + "type": "module", + "version": "0.0.0", + "private": true, + "scripts": { + "dev:cf": "wrangler dev --var \"E2E_TEST_DSN:$E2E_TEST_DSN\" --log-level=$(test $CI && echo 'none' || echo 'log')", + "dev:node": "node --import tsx/esm --import @sentry/node/preload src/entry.node.ts", + "dev:bun": "bun src/entry.bun.ts", + "build": "wrangler deploy --dry-run", + "test:build": "pnpm install && pnpm build", + "test:assert": "TEST_ENV=production playwright test" + }, + "dependencies": { + "@sentry/hono": "latest || *", + "@sentry/node": "latest || *", + "@hono/node-server": "^1.19.10", + "hono": "^4.12.14" + }, + "devDependencies": { + "@playwright/test": "~1.56.0", + "@cloudflare/workers-types": "^4.20240725.0", + "@sentry-internal/test-utils": "link:../../../test-utils", + "tsx": "^4.20.3", + "typescript": "^5.5.2", + "wrangler": "^4.61.0" + }, + "volta": { + "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "assert-command": "RUNTIME=node pnpm test:assert", + "label": "hono-4 (node)" + }, + { + "assert-command": "RUNTIME=bun pnpm test:assert", + "label": "hono-4 (bun)" + } + ] + } +} diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/playwright.config.ts b/dev-packages/e2e-tests/test-applications/hono-4/playwright.config.ts similarity index 52% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/playwright.config.ts rename to dev-packages/e2e-tests/test-applications/hono-4/playwright.config.ts index 1cca1e0ee184..74a21e10a349 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/playwright.config.ts +++ b/dev-packages/e2e-tests/test-applications/hono-4/playwright.config.ts @@ -1,5 +1,9 @@ import { getPlaywrightConfig } from '@sentry-internal/test-utils'; +type Runtime = 'cloudflare' | 'node' | 'bun'; + +const RUNTIME = (process.env.RUNTIME || 'cloudflare') as Runtime; + const testEnv = process.env.TEST_ENV; if (!testEnv) { @@ -8,9 +12,15 @@ if (!testEnv) { const APP_PORT = 38787; +const startCommands: Record = { + cloudflare: `pnpm dev:cf --port ${APP_PORT}`, + node: `pnpm dev:node`, + bun: `pnpm dev:bun`, +}; + const config = getPlaywrightConfig( { - startCommand: `pnpm dev --port ${APP_PORT}`, + startCommand: startCommands[RUNTIME], port: APP_PORT, }, { diff --git a/dev-packages/e2e-tests/test-applications/hono-4/src/entry.bun.ts b/dev-packages/e2e-tests/test-applications/hono-4/src/entry.bun.ts new file mode 100644 index 000000000000..2a27d1adb8a9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4/src/entry.bun.ts @@ -0,0 +1,24 @@ +import { Hono } from 'hono'; +import { sentry } from '@sentry/hono/bun'; +import { addRoutes } from './routes'; + +const app = new Hono<{ Bindings: { E2E_TEST_DSN: string } }>(); + +app.use( + // @ts-expect-error - Env is not yet in type + sentry(app, { + dsn: process.env.E2E_TEST_DSN, + environment: 'qa', + tracesSampleRate: 1.0, + tunnel: 'http://localhost:3031/', + }), +); + +addRoutes(app); + +const port = Number(process.env.PORT || 38787); + +export default { + port, + fetch: app.fetch, +}; diff --git a/dev-packages/e2e-tests/test-applications/hono-4/src/entry.cloudflare.ts b/dev-packages/e2e-tests/test-applications/hono-4/src/entry.cloudflare.ts new file mode 100644 index 000000000000..e348dde56226 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4/src/entry.cloudflare.ts @@ -0,0 +1,18 @@ +import { Hono } from 'hono'; +import { sentry } from '@sentry/hono/cloudflare'; +import { addRoutes } from './routes'; + +const app = new Hono<{ Bindings: { E2E_TEST_DSN: string } }>(); + +app.use( + sentry(app, env => ({ + dsn: env.E2E_TEST_DSN, + environment: 'qa', + tracesSampleRate: 1.0, + tunnel: 'http://localhost:3031/', + })), +); + +addRoutes(app); + +export default app; diff --git a/dev-packages/e2e-tests/test-applications/hono-4/src/entry.node.ts b/dev-packages/e2e-tests/test-applications/hono-4/src/entry.node.ts new file mode 100644 index 000000000000..eb2c669c6806 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4/src/entry.node.ts @@ -0,0 +1,24 @@ +import { Hono } from 'hono'; +import { sentry } from '@sentry/hono/node'; +import { serve } from '@hono/node-server'; +import { addRoutes } from './routes'; + +const app = new Hono<{ Bindings: { E2E_TEST_DSN: string } }>(); + +app.use( + // @ts-expect-error - Env is not yet in type + sentry(app, { + dsn: process.env.E2E_TEST_DSN, + environment: 'qa', + tracesSampleRate: 1.0, + tunnel: 'http://localhost:3031/', + }), +); + +addRoutes(app); + +const port = Number(process.env.PORT || 38787); + +serve({ fetch: app.fetch, port }, () => { + console.log(`Hono (Node) listening on port ${port}`); +}); diff --git a/dev-packages/e2e-tests/test-applications/hono-4/src/routes.ts b/dev-packages/e2e-tests/test-applications/hono-4/src/routes.ts new file mode 100644 index 000000000000..fbb273c7c425 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/hono-4/src/routes.ts @@ -0,0 +1,24 @@ +import type { Hono } from 'hono'; +import { HTTPException } from 'hono/http-exception'; + +export function addRoutes(app: Hono<{ Bindings: { E2E_TEST_DSN: string } }>): void { + app.get('/', c => { + return c.text('Hello Hono!'); + }); + + app.get('/test-param/:paramId', c => { + return c.json({ paramId: c.req.param('paramId') }); + }); + + app.get('/error/:cause', c => { + throw new Error('This is a test error for Sentry!', { + cause: c.req.param('cause'), + }); + }); + + app.get('/http-exception/:code', c => { + // oxlint-disable-next-line typescript/no-explicit-any + const code = Number(c.req.param('code')) as any; + throw new HTTPException(code, { message: `HTTPException ${code}` }); + }); +} diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/hono-4/start-event-proxy.mjs similarity index 77% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/start-event-proxy.mjs rename to dev-packages/e2e-tests/test-applications/hono-4/start-event-proxy.mjs index bccc9f3be95a..cd6f91b3455d 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/hono-4/start-event-proxy.mjs @@ -2,5 +2,5 @@ import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, - proxyServerName: 'hono-4-cf', + proxyServerName: 'hono-4', }); diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/hono-4/tests/errors.test.ts similarity index 87% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/tests/errors.test.ts rename to dev-packages/e2e-tests/test-applications/hono-4/tests/errors.test.ts index 56d7fb599045..e85958e8328b 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/hono-4/tests/errors.test.ts @@ -1,8 +1,10 @@ import { expect, test } from '@playwright/test'; import { waitForError } from '@sentry-internal/test-utils'; +const APP_NAME = 'hono-4'; + test('captures error thrown in route handler', async ({ baseURL }) => { - const errorWaiter = waitForError('hono-4-cf', event => { + const errorWaiter = waitForError(APP_NAME, event => { return event.exception?.values?.[0]?.value === 'This is a test error for Sentry!'; }); @@ -14,7 +16,7 @@ test('captures error thrown in route handler', async ({ baseURL }) => { }); test('captures HTTPException with 502 status', async ({ baseURL }) => { - const errorWaiter = waitForError('hono-4-cf', event => { + const errorWaiter = waitForError(APP_NAME, event => { return event.exception?.values?.[0]?.value === 'HTTPException 502'; }); @@ -28,7 +30,7 @@ test('captures HTTPException with 502 status', async ({ baseURL }) => { // TODO: 401 and 404 HTTPExceptions should not be captured by Sentry by default, // but currently they are. Fix the filtering and update these tests accordingly. test('captures HTTPException with 401 status', async ({ baseURL }) => { - const errorWaiter = waitForError('hono-4-cf', event => { + const errorWaiter = waitForError(APP_NAME, event => { return event.exception?.values?.[0]?.value === 'HTTPException 401'; }); @@ -40,7 +42,7 @@ test('captures HTTPException with 401 status', async ({ baseURL }) => { }); test('captures HTTPException with 404 status', async ({ baseURL }) => { - const errorWaiter = waitForError('hono-4-cf', event => { + const errorWaiter = waitForError(APP_NAME, event => { return event.exception?.values?.[0]?.value === 'HTTPException 404'; }); diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/tracing.test.ts b/dev-packages/e2e-tests/test-applications/hono-4/tests/tracing.test.ts similarity index 84% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/tests/tracing.test.ts rename to dev-packages/e2e-tests/test-applications/hono-4/tests/tracing.test.ts index b2ac26c89d44..58c73c6a8369 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/tests/tracing.test.ts +++ b/dev-packages/e2e-tests/test-applications/hono-4/tests/tracing.test.ts @@ -1,8 +1,10 @@ import { expect, test } from '@playwright/test'; import { waitForTransaction } from '@sentry-internal/test-utils'; +const APP_NAME = 'hono-4'; + test('sends a transaction for the index route', async ({ baseURL }) => { - const transactionWaiter = waitForTransaction('hono-4-cf', event => { + const transactionWaiter = waitForTransaction(APP_NAME, event => { return event.transaction === 'GET /'; }); @@ -14,7 +16,7 @@ test('sends a transaction for the index route', async ({ baseURL }) => { }); test('sends a transaction for a parameterized route', async ({ baseURL }) => { - const transactionWaiter = waitForTransaction('hono-4-cf', event => { + const transactionWaiter = waitForTransaction(APP_NAME, event => { return event.transaction === 'GET /test-param/:paramId'; }); @@ -27,7 +29,7 @@ test('sends a transaction for a parameterized route', async ({ baseURL }) => { }); test('sends a transaction for a route that throws', async ({ baseURL }) => { - const transactionWaiter = waitForTransaction('hono-4-cf', event => { + const transactionWaiter = waitForTransaction(APP_NAME, event => { return event.transaction === 'GET /error/:cause'; }); diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json b/dev-packages/e2e-tests/test-applications/hono-4/tsconfig.json similarity index 100% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/tsconfig.json rename to dev-packages/e2e-tests/test-applications/hono-4/tsconfig.json diff --git a/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc b/dev-packages/e2e-tests/test-applications/hono-4/wrangler.jsonc similarity index 71% rename from dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc rename to dev-packages/e2e-tests/test-applications/hono-4/wrangler.jsonc index 2ac330d50b1d..d4344dfa198a 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4-cf/wrangler.jsonc +++ b/dev-packages/e2e-tests/test-applications/hono-4/wrangler.jsonc @@ -1,7 +1,7 @@ { "$schema": "node_modules/wrangler/config-schema.json", - "name": "hono-4-cf", - "main": "src/index.ts", + "name": "hono-4", + "main": "src/entry.cloudflare.ts", "compatibility_date": "2026-04-20", "compatibility_flags": ["nodejs_compat"], }