@@ -477,6 +477,176 @@ describeMatrix(
477477 listener . cleanup ( ) ;
478478 }
479479 } ) ;
480+
481+ it ( "traces routes from mounted nested app" , async ( ) => {
482+ const listener = createTracingListener ( ) ;
483+
484+ try {
485+ const nestedApp = new H3 ( {
486+ plugins : [ tracingPlugin ( ) ] ,
487+ } ) ;
488+ nestedApp . get ( "/nested" , ( ) => "nested response" ) ;
489+
490+ t . app . mount ( "/api" , nestedApp ) ;
491+
492+ const response = await t . fetch ( "/api/nested" ) ;
493+ expect ( response . status ) . toBe ( 200 ) ;
494+ expect ( await response . text ( ) ) . toBe ( "nested response" ) ;
495+
496+ // Wait for tracing events to be processed
497+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
498+
499+ const routeEvents = listener . events . filter (
500+ ( e ) => e . asyncStart ?. data . type === "route" ,
501+ ) ;
502+
503+ // Should have traced the nested app route
504+ expect ( routeEvents . length ) . toBeGreaterThan ( 0 ) ;
505+ const nestedRouteEvent = routeEvents . find (
506+ ( e ) => e . asyncStart ?. data . event . url . pathname === "/api/nested" ,
507+ ) ;
508+ expect ( nestedRouteEvent ) . toBeDefined ( ) ;
509+ } finally {
510+ listener . cleanup ( ) ;
511+ }
512+ } ) ;
513+
514+ it ( "traces middleware from mounted nested app" , async ( ) => {
515+ const listener = createTracingListener ( ) ;
516+
517+ try {
518+ const nestedApp = new H3 ( {
519+ plugins : [ tracingPlugin ( ) ] ,
520+ } ) ;
521+ nestedApp . use ( ( event ) => {
522+ event . context . nestedMiddleware = true ;
523+ } ) ;
524+ nestedApp . get ( "/nested" , ( event ) => ( {
525+ nestedMiddleware : event . context . nestedMiddleware ,
526+ } ) ) ;
527+
528+ t . app . mount ( "/api" , nestedApp ) ;
529+
530+ const response = await t . fetch ( "/api/nested" ) ;
531+ expect ( response . status ) . toBe ( 200 ) ;
532+ const body = await response . json ( ) ;
533+ expect ( body . nestedMiddleware ) . toBe ( true ) ;
534+
535+ // Wait for tracing events to be processed
536+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
537+
538+ const middlewareEvents = listener . events . filter (
539+ ( e ) => e . asyncStart ?. data . type === "middleware" ,
540+ ) ;
541+
542+ // Should have traced the nested app middleware
543+ expect ( middlewareEvents . length ) . toBeGreaterThan ( 0 ) ;
544+ } finally {
545+ listener . cleanup ( ) ;
546+ }
547+ } ) ;
548+
549+ it ( "traces both parent and nested app routes and middleware" , async ( ) => {
550+ const listener = createTracingListener ( ) ;
551+
552+ try {
553+ // Parent app route
554+ t . app . get ( "/parent" , ( ) => "parent response" ) ;
555+
556+ // Nested app with route and middleware
557+ const nestedApp = new H3 ( ) ;
558+ nestedApp . use ( ( event ) => {
559+ event . context . nested = true ;
560+ } ) ;
561+ nestedApp . get ( "/nested" , ( ) => "nested response" ) ;
562+
563+ t . app . mount ( "/api" , nestedApp ) ;
564+
565+ // Make requests to both
566+ const parentResponse = await t . fetch ( "/parent" ) ;
567+ expect ( parentResponse . status ) . toBe ( 200 ) ;
568+
569+ const nestedResponse = await t . fetch ( "/api/nested" ) ;
570+ expect ( nestedResponse . status ) . toBe ( 200 ) ;
571+
572+ // Wait for tracing events to be processed
573+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
574+
575+ const routeEvents = listener . events . filter (
576+ ( e ) => e . asyncStart ?. data . type === "route" ,
577+ ) ;
578+ const middlewareEvents = listener . events . filter (
579+ ( e ) => e . asyncStart ?. data . type === "middleware" ,
580+ ) ;
581+
582+ // Should have traced both parent and nested routes
583+ expect ( routeEvents . length ) . toBeGreaterThanOrEqual ( 2 ) ;
584+
585+ // Should have traced nested middleware
586+ expect ( middlewareEvents . length ) . toBeGreaterThan ( 0 ) ;
587+
588+ // Verify parent route was traced
589+ const parentRouteEvent = routeEvents . find (
590+ ( e ) => e . asyncStart ?. data . event . url . pathname === "/parent" ,
591+ ) ;
592+ expect ( parentRouteEvent ) . toBeDefined ( ) ;
593+
594+ // Verify nested route was traced
595+ const nestedRouteEvent = routeEvents . find (
596+ ( e ) => e . asyncStart ?. data . event . url . pathname === "/api/nested" ,
597+ ) ;
598+ expect ( nestedRouteEvent ) . toBeDefined ( ) ;
599+ } finally {
600+ listener . cleanup ( ) ;
601+ }
602+ } ) ;
603+
604+ it ( "traces deeply nested mounted apps" , async ( ) => {
605+ const listener = createTracingListener ( ) ;
606+
607+ try {
608+ // Create a deeply nested app structure
609+ const deepApp = new H3 ( ) ;
610+ deepApp . use ( ( event ) => {
611+ event . context . deep = true ;
612+ } ) ;
613+ deepApp . get ( "/deep" , ( ) => "deep response" ) ;
614+
615+ const midApp = new H3 ( ) ;
616+ midApp . use ( ( event ) => {
617+ event . context . mid = true ;
618+ } ) ;
619+ midApp . mount ( "/v1" , deepApp ) ;
620+
621+ t . app . mount ( "/api" , midApp ) ;
622+
623+ const response = await t . fetch ( "/api/v1/deep" ) ;
624+ expect ( response . status ) . toBe ( 200 ) ;
625+ expect ( await response . text ( ) ) . toBe ( "deep response" ) ;
626+
627+ // Wait for tracing events to be processed
628+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
629+
630+ const routeEvents = listener . events . filter (
631+ ( e ) => e . asyncStart ?. data . type === "route" ,
632+ ) ;
633+ const middlewareEvents = listener . events . filter (
634+ ( e ) => e . asyncStart ?. data . type === "middleware" ,
635+ ) ;
636+
637+ // Should have traced the deep route
638+ expect ( routeEvents . length ) . toBeGreaterThan ( 0 ) ;
639+ const deepRouteEvent = routeEvents . find (
640+ ( e ) => e . asyncStart ?. data . event . url . pathname === "/api/v1/deep" ,
641+ ) ;
642+ expect ( deepRouteEvent ) . toBeDefined ( ) ;
643+
644+ // Should have traced middleware from both mid and deep apps
645+ expect ( middlewareEvents . length ) . toBeGreaterThanOrEqual ( 2 ) ;
646+ } finally {
647+ listener . cleanup ( ) ;
648+ }
649+ } ) ;
480650 } ,
481651 testOpts ,
482652) ;
0 commit comments