11import { expect , test } from '@playwright/test' ;
22import { waitForError , waitForTransaction } from '@sentry-internal/test-utils' ;
33import { type SpanJSON } from '@sentry/core' ;
4- import { APP_NAME , isNode } from './constants' ;
5-
6- // In Node, @sentry/node/preload eagerly activates the OTel HonoInstrumentation,
7- // which wraps all Hono instance methods at construction time via WrappedHono.
8- const MIDDLEWARE_ORIGIN = 'auto.middleware.hono' ;
9- const OTEL_ORIGIN = 'auto.http.otel.hono' ;
4+ import { APP_NAME } from './constants' ;
105
116const SCENARIOS = [
127 {
138 name : 'root app middleware' ,
149 prefix : '/test-middleware' ,
15- origin : MIDDLEWARE_ORIGIN ,
1610 } ,
1711 {
1812 name : 'sub-app middleware (route group)' ,
1913 prefix : '/test-subapp-middleware' ,
20- origin : isNode ? OTEL_ORIGIN : MIDDLEWARE_ORIGIN ,
2114 } ,
2215] as const ;
2316
24- for ( const { name, prefix, origin } of SCENARIOS ) {
17+ for ( const { name, prefix } of SCENARIOS ) {
2518 test . describe ( name , ( ) => {
2619 test ( 'creates a span for named middleware' , async ( { baseURL } ) => {
2720 const transactionPromise = waitForTransaction ( APP_NAME , event => {
@@ -43,7 +36,7 @@ for (const { name, prefix, origin } of SCENARIOS) {
4336 expect . objectContaining ( {
4437 description : 'middlewareA' ,
4538 op : 'middleware.hono' ,
46- origin,
39+ origin : 'auto.middleware.hono' ,
4740 status : 'ok' ,
4841 } ) ,
4942 ) ;
@@ -68,18 +61,13 @@ for (const { name, prefix, origin } of SCENARIOS) {
6861 expect . objectContaining ( {
6962 description : '<anonymous>' ,
7063 op : 'middleware.hono' ,
71- origin : MIDDLEWARE_ORIGIN ,
64+ origin : 'auto.middleware.hono' ,
7265 status : 'ok' ,
7366 } ) ,
7467 ) ;
7568 } ) ;
7669
7770 test ( 'multiple middleware are sibling spans under the same parent' , async ( { baseURL } ) => {
78- test . skip (
79- isNode ,
80- 'Node double-instruments middleware (too many spans) - TODO: fix this in the SDK and re-enable the test' ,
81- ) ;
82-
8371 const transactionPromise = waitForTransaction ( APP_NAME , event => {
8472 return event . contexts ?. trace ?. op === 'http.server' && event . transaction === `GET ${ prefix } /multi` ;
8573 } ) ;
@@ -90,7 +78,6 @@ for (const { name, prefix, origin } of SCENARIOS) {
9078 const transaction = await transactionPromise ;
9179 const spans = transaction . spans || [ ] ;
9280
93- // Sort spans because they are in a different order in Node/Bun (OTel-based)
9481 const middlewareSpans = spans . sort ( ( a , b ) => ( a . start_timestamp ?? 0 ) - ( b . start_timestamp ?? 0 ) ) ;
9582
9683 expect ( middlewareSpans ) . toHaveLength ( 2 ) ;
@@ -139,10 +126,6 @@ for (const { name, prefix, origin } of SCENARIOS) {
139126 const transaction = await transactionPromise ;
140127 const spans = transaction . spans || [ ] ;
141128
142- // On the /error path only one middleware (failingMiddleware) is registered,
143- // so we can find the error span by status alone. On Node for sub-apps, the
144- // OTel layer wraps before patchRoute, so the function name may be lost in
145- // the patchRoute span — but the error status is always set.
146129 const failingSpan = spans . find (
147130 ( span : SpanJSON ) => span . op === 'middleware.hono' && span . status === 'internal_error' ,
148131 ) ;
@@ -169,36 +152,8 @@ for (const { name, prefix, origin } of SCENARIOS) {
169152 } ) ;
170153}
171154
172- test . describe ( '.all() handler on sub-app (method ALL edge case)' , ( ) => {
173- test ( 'Node: OTel wraps .all() and produces a hono span' , async ( { baseURL } ) => {
174- test . skip ( ! isNode , 'Node-specific: OTel wraps .all() at construction time' ) ;
175-
176- const transactionPromise = waitForTransaction ( APP_NAME , event => {
177- return (
178- event . contexts ?. trace ?. op === 'http.server' && event . transaction === 'GET /test-subapp-middleware/all-handler'
179- ) ;
180- } ) ;
181-
182- const response = await fetch ( `${ baseURL } /test-subapp-middleware/all-handler` ) ;
183- expect ( response . status ) . toBe ( 200 ) ;
184-
185- const body = await response . json ( ) ;
186- expect ( body ) . toEqual ( { handler : 'all' } ) ;
187-
188- const transaction = await transactionPromise ;
189- const spans = transaction . spans || [ ] ;
190-
191- // On Node, OTel wraps .all() at construction time. Since the handler
192- // returns a Response, OTel classifies it as 'request_handler' (not
193- // middleware). patchRoute also wraps it but sees the anonymous OTel wrapper.
194- // Either way, the handler IS instrumented — verify any hono span exists.
195- const honoSpan = spans . find ( ( span : SpanJSON ) => span . op ?. endsWith ( '.hono' ) ) ;
196- expect ( honoSpan ) . toBeDefined ( ) ;
197- } ) ;
198-
199- test ( 'Bun/Cloudflare: patchRoute wraps .all() as middleware span' , async ( { baseURL } ) => {
200- test . skip ( isNode , 'Bun/Cloudflare-specific: patchRoute is the sole wrapper' ) ;
201-
155+ test . describe ( 'patchRoute wraps .all() as middleware span (in sub-app)' , ( ) => {
156+ test ( 'patchRoute wraps .all() as middleware span' , async ( { baseURL } ) => {
202157 const transactionPromise = waitForTransaction ( APP_NAME , event => {
203158 return (
204159 event . contexts ?. trace ?. op === 'http.server' && event . transaction === 'GET /test-subapp-middleware/all-handler'
@@ -225,7 +180,7 @@ test.describe('.all() handler on sub-app (method ALL edge case)', () => {
225180 expect . objectContaining ( {
226181 description : 'allCatchAll' ,
227182 op : 'middleware.hono' ,
228- origin : MIDDLEWARE_ORIGIN ,
183+ origin : 'auto.middleware.hono' ,
229184 status : 'ok' ,
230185 } ) ,
231186 ) ;
0 commit comments