@@ -1157,3 +1157,80 @@ describe("tracing channels for H3Core instances", () => {
11571157 }
11581158 } ) ;
11591159} ) ;
1160+
1161+ describe ( "wrapHandlerWithTracing" , ( ) => {
1162+ it ( "wraps a handler so route traces are emitted" , async ( ) => {
1163+ const listener = createTracingListener ( ) ;
1164+ const { H3Core } = await import ( "../src/h3.ts" ) ;
1165+ const { wrapHandlerWithTracing } = await import ( "../src/tracing.ts" ) ;
1166+ const { H3Event } = await import ( "../src/event.ts" ) ;
1167+
1168+ try {
1169+ const app = new H3Core ( ) ;
1170+ const routeHandler = wrapHandlerWithTracing ( ( ) => "traced response" ) ;
1171+
1172+ app [ "~findRoute" ] = ( event : any ) => {
1173+ if ( event . url . pathname === "/test" && event . req . method === "GET" ) {
1174+ return { data : { method : "GET" , route : "/test" , handler : routeHandler } , params : { } } ;
1175+ }
1176+ return undefined ;
1177+ } ;
1178+
1179+ const request = new Request ( "http://localhost/test" , { method : "GET" } ) ;
1180+ const event = new H3Event ( request , undefined , app as any ) ;
1181+
1182+ await app . handler ( event ) ;
1183+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
1184+
1185+ const routeEvents = listener . events . filter ( ( e ) => e . asyncStart ?. data . type === "route" ) ;
1186+ expect ( routeEvents . some ( ( e ) => e . asyncStart ?. data . event . url . pathname === "/test" ) ) . toBe ( true ) ;
1187+ } finally {
1188+ listener . cleanup ( ) ;
1189+ }
1190+ } ) ;
1191+
1192+ it ( "is idempotent — wrapping twice returns the same wrapper" , async ( ) => {
1193+ const { wrapHandlerWithTracing } = await import ( "../src/tracing.ts" ) ;
1194+
1195+ const handler = ( ) => "ok" ;
1196+ const wrapped = wrapHandlerWithTracing ( handler ) ;
1197+ const doubleWrapped = wrapHandlerWithTracing ( wrapped ) ;
1198+
1199+ expect ( doubleWrapped ) . toBe ( wrapped ) ;
1200+ expect ( ( wrapped as any ) . __traced__ ) . toBe ( true ) ;
1201+ } ) ;
1202+
1203+ it ( "emits exactly one trace per request on a pre-wrapped handler" , async ( ) => {
1204+ const listener = createTracingListener ( ) ;
1205+ const { H3Core } = await import ( "../src/h3.ts" ) ;
1206+ const { wrapHandlerWithTracing } = await import ( "../src/tracing.ts" ) ;
1207+ const { H3Event } = await import ( "../src/event.ts" ) ;
1208+
1209+ try {
1210+ const app = new H3Core ( ) ;
1211+ const routeHandler = wrapHandlerWithTracing ( ( ) => "ok" ) ;
1212+
1213+ app [ "~findRoute" ] = ( ) => ( {
1214+ data : { method : "GET" as const , route : "/test" , handler : routeHandler } ,
1215+ params : { } ,
1216+ } ) ;
1217+
1218+ const run = async ( ) => {
1219+ const request = new Request ( "http://localhost/test" , { method : "GET" } ) ;
1220+ const event = new H3Event ( request , undefined , app as any ) ;
1221+ await app . handler ( event ) ;
1222+ } ;
1223+
1224+ await run ( ) ;
1225+ await run ( ) ;
1226+ await run ( ) ;
1227+
1228+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
1229+
1230+ const routeAsyncStarts = listener . events . filter ( ( e ) => e . asyncStart ?. data . type === "route" ) ;
1231+ expect ( routeAsyncStarts . length ) . toBe ( 3 ) ;
1232+ } finally {
1233+ listener . cleanup ( ) ;
1234+ }
1235+ } ) ;
1236+ } ) ;
0 commit comments