@@ -294,3 +294,86 @@ test('Does not send any duplicate navigation transaction names browsing between
294294 '/lazy/inner/:id/:anotherId' ,
295295 ] ) ;
296296} ) ;
297+
298+ test ( 'Does not create premature navigation transaction during long-running lazy route pageload' , async ( { page } ) => {
299+ const navigationPromise = waitForTransaction ( 'react-router-7-lazy-routes' , async transactionEvent => {
300+ return (
301+ ! ! transactionEvent ?. transaction &&
302+ transactionEvent . contexts ?. trace ?. op === 'navigation' &&
303+ transactionEvent . transaction . includes ( 'long-running' )
304+ ) ;
305+ } ) ;
306+
307+ const pageloadPromise = waitForTransaction ( 'react-router-7-lazy-routes' , async transactionEvent => {
308+ return (
309+ ! ! transactionEvent ?. transaction &&
310+ transactionEvent . contexts ?. trace ?. op === 'pageload' &&
311+ transactionEvent . transaction === '/long-running/slow/:id'
312+ ) ;
313+ } ) ;
314+
315+ await page . goto ( '/long-running/slow/12345' ) ;
316+
317+ const pageloadEvent = await pageloadPromise ;
318+
319+ expect ( pageloadEvent . transaction ) . toBe ( '/long-running/slow/:id' ) ;
320+ expect ( pageloadEvent . contexts ?. trace ?. op ) . toBe ( 'pageload' ) ;
321+
322+ const slowLoadingContent = page . locator ( 'id=slow-loading-content' ) ;
323+ await expect ( slowLoadingContent ) . toBeVisible ( { timeout : 5000 } ) ;
324+
325+ const result = await Promise . race ( [
326+ navigationPromise . then ( ( ) => 'navigation' ) ,
327+ new Promise < 'timeout' > ( resolve => setTimeout ( ( ) => resolve ( 'timeout' ) , 2000 ) ) ,
328+ ] ) ;
329+
330+ // Should timeout, meaning no unwanted navigation transaction was created
331+ expect ( result ) . toBe ( 'timeout' ) ;
332+ } ) ;
333+
334+ test ( 'Allows legitimate POP navigation (back/forward) after pageload completes' , async ( { page } ) => {
335+ await page . goto ( '/' ) ;
336+
337+ const navigationToLongRunning = page . locator ( 'id=navigation-to-long-running' ) ;
338+ await expect ( navigationToLongRunning ) . toBeVisible ( ) ;
339+
340+ const firstNavigationPromise = waitForTransaction ( 'react-router-7-lazy-routes' , async transactionEvent => {
341+ return (
342+ ! ! transactionEvent ?. transaction &&
343+ transactionEvent . contexts ?. trace ?. op === 'navigation' &&
344+ transactionEvent . transaction === '/long-running/slow/:id'
345+ ) ;
346+ } ) ;
347+
348+ await navigationToLongRunning . click ( ) ;
349+
350+ const slowLoadingContent = page . locator ( 'id=slow-loading-content' ) ;
351+ await expect ( slowLoadingContent ) . toBeVisible ( { timeout : 5000 } ) ;
352+
353+ const firstNavigationEvent = await firstNavigationPromise ;
354+
355+ expect ( firstNavigationEvent . transaction ) . toBe ( '/long-running/slow/:id' ) ;
356+ expect ( firstNavigationEvent . contexts ?. trace ?. op ) . toBe ( 'navigation' ) ;
357+
358+ // Now navigate back using browser back button (POP event)
359+ // This should create a navigation transaction since pageload is complete
360+ const backNavigationPromise = waitForTransaction ( 'react-router-7-lazy-routes' , async transactionEvent => {
361+ return (
362+ ! ! transactionEvent ?. transaction &&
363+ transactionEvent . contexts ?. trace ?. op === 'navigation' &&
364+ transactionEvent . transaction === '/'
365+ ) ;
366+ } ) ;
367+
368+ await page . goBack ( ) ;
369+
370+ // Verify we're back at home
371+ const homeLink = page . locator ( 'id=navigation' ) ;
372+ await expect ( homeLink ) . toBeVisible ( ) ;
373+
374+ const backNavigationEvent = await backNavigationPromise ;
375+
376+ // Validate that the back navigation (POP) was properly tracked
377+ expect ( backNavigationEvent . transaction ) . toBe ( '/' ) ;
378+ expect ( backNavigationEvent . contexts ?. trace ?. op ) . toBe ( 'navigation' ) ;
379+ } ) ;
0 commit comments