@@ -561,6 +561,48 @@ function testDomRouter(
561561 </div>"
562562 ` ) ;
563563 } ) ;
564+
565+ it ( "handles race conditions if router initialization completes prior to the layout effect router.subscribe() call" , async ( ) => {
566+ const sleep = ( ms : number ) =>
567+ new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
568+
569+ // Kick off some async data load _before_ any react stuff
570+ let suspensePromise = sleep ( 100 ) . then ( ( ) => "DATA" ) ;
571+
572+ // Create a router that will initialize shortly after the suspense boundary resolves
573+ let router = createTestRouter ( [
574+ {
575+ path : "/" ,
576+ // Only fails when this is around 200ms - passes if you bump it to ~500ms
577+ loader : ( ) => sleep ( 200 ) . then ( ( ) => "LOADER" ) ,
578+ Component : ( ) => < p > Data:{ useLoaderData ( ) } </ p > ,
579+ HydrateFallback : ( ) => "Hydrate Fallback" ,
580+ } ,
581+ ] ) ;
582+ expect ( router . state . initialized ) . toBe ( false ) ;
583+
584+ // Render a component that will suspend until `suspensePromise` resolves, then
585+ // renders RouterProvider which sets up listeners for the router state
586+ function App ( ) {
587+ // @ts -expect-error Needs React 19 types
588+ React . use ( suspensePromise ) ;
589+ return < RouterProvider router = { router } /> ;
590+ }
591+
592+ // Needs to be wrapped in `act()` for suspense to work properly
593+ // https://github.com/testing-library/react-testing-library/issues/1375
594+ await act ( async ( ) => {
595+ render (
596+ < React . Suspense fallback = "Suspense Fallback" >
597+ < App />
598+ </ React . Suspense > ,
599+ ) ;
600+ } ) ;
601+
602+ expect ( screen . getByText ( "Suspense Fallback" ) ) . toBeDefined ( ) ;
603+ await waitFor ( ( ) => screen . getByText ( "Data:LOADER" ) ) ;
604+ expect ( screen . queryByText ( "Suspense Fallback" ) ) . toBeNull ( ) ;
605+ } ) ;
564606 } ) ;
565607
566608 describe ( "navigations" , ( ) => {
0 commit comments