Skip to content

Commit 3084371

Browse files
committed
Address review comments
1 parent e9cab06 commit 3084371

File tree

2 files changed

+58
-55
lines changed

2 files changed

+58
-55
lines changed

dev-packages/e2e-tests/test-applications/react-router-7-lazy-routes/tests/transactions.test.ts

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ test('Updates navigation transaction name correctly when span is cancelled early
504504
test('Creates separate transactions for rapid consecutive navigations', async ({ page }) => {
505505
await page.goto('/');
506506

507-
// First navigation: / -> /lazy/inner/:id/:anotherId/:someAnotherId
507+
// Set up transaction listeners
508508
const firstTransactionPromise = waitForTransaction('react-router-7-lazy-routes', async transactionEvent => {
509509
return (
510510
!!transactionEvent?.transaction &&
@@ -513,21 +513,6 @@ test('Creates separate transactions for rapid consecutive navigations', async ({
513513
);
514514
});
515515

516-
const navigationToInner = page.locator('id=navigation');
517-
await expect(navigationToInner).toBeVisible();
518-
await navigationToInner.click();
519-
520-
const firstEvent = await firstTransactionPromise;
521-
522-
// Verify first transaction
523-
expect(firstEvent.transaction).toBe('/lazy/inner/:id/:anotherId/:someAnotherId');
524-
expect(firstEvent.contexts?.trace?.op).toBe('navigation');
525-
expect(firstEvent.contexts?.trace?.status).toBe('ok');
526-
527-
const firstTraceId = firstEvent.contexts?.trace?.trace_id;
528-
const firstSpanId = firstEvent.contexts?.trace?.span_id;
529-
530-
// Second navigation: /lazy/inner -> /another-lazy/sub/:id/:subId
531516
const secondTransactionPromise = waitForTransaction('react-router-7-lazy-routes', async transactionEvent => {
532517
return (
533518
!!transactionEvent?.transaction &&
@@ -536,37 +521,49 @@ test('Creates separate transactions for rapid consecutive navigations', async ({
536521
);
537522
});
538523

539-
const navigationToAnother = page.locator('id=navigate-to-another-from-inner');
540-
await expect(navigationToAnother).toBeVisible();
541-
await navigationToAnother.click();
524+
// Third navigation promise - using counter to match second occurrence of same route
525+
let innerRouteMatchCount = 0;
526+
const thirdTransactionPromise = waitForTransaction('react-router-7-lazy-routes', async transactionEvent => {
527+
if (
528+
transactionEvent?.transaction &&
529+
transactionEvent.contexts?.trace?.op === 'navigation' &&
530+
transactionEvent.transaction === '/lazy/inner/:id/:anotherId/:someAnotherId'
531+
) {
532+
innerRouteMatchCount++;
533+
return innerRouteMatchCount === 2; // Match the second occurrence
534+
}
535+
return false;
536+
});
537+
538+
// Perform navigations
539+
// First navigation: / -> /lazy/inner/:id/:anotherId/:someAnotherId
540+
await page.locator('id=navigation').click();
541+
542+
const firstEvent = await firstTransactionPromise;
543+
544+
// Second navigation: /lazy/inner -> /another-lazy/sub/:id/:subId
545+
await page.locator('id=navigate-to-another-from-inner').click();
542546

543547
const secondEvent = await secondTransactionPromise;
544548

545-
// Verify second transaction
549+
// Third navigation: /another-lazy -> /lazy/inner/:id/:anotherId/:someAnotherId (back to same route as first)
550+
await page.locator('id=navigate-to-inner-from-deep').click();
551+
552+
const thirdEvent = await thirdTransactionPromise;
553+
554+
// Verify transactions
555+
expect(firstEvent.transaction).toBe('/lazy/inner/:id/:anotherId/:someAnotherId');
556+
expect(firstEvent.contexts?.trace?.op).toBe('navigation');
557+
const firstTraceId = firstEvent.contexts?.trace?.trace_id;
558+
const firstSpanId = firstEvent.contexts?.trace?.span_id;
559+
546560
expect(secondEvent.transaction).toBe('/another-lazy/sub/:id/:subId');
547561
expect(secondEvent.contexts?.trace?.op).toBe('navigation');
548562
expect(secondEvent.contexts?.trace?.status).toBe('ok');
549563

550564
const secondTraceId = secondEvent.contexts?.trace?.trace_id;
551565
const secondSpanId = secondEvent.contexts?.trace?.span_id;
552566

553-
// Third navigation: /another-lazy -> /lazy/inner/:id/:anotherId/:someAnotherId (back to same route as first)
554-
const thirdTransactionPromise = waitForTransaction('react-router-7-lazy-routes', async transactionEvent => {
555-
return (
556-
!!transactionEvent?.transaction &&
557-
transactionEvent.contexts?.trace?.op === 'navigation' &&
558-
transactionEvent.transaction === '/lazy/inner/:id/:anotherId/:someAnotherId' &&
559-
// Ensure we're not matching the first transaction again
560-
transactionEvent.contexts?.trace?.trace_id !== firstTraceId
561-
);
562-
});
563-
564-
const navigationBackToInner = page.locator('id=navigate-to-inner-from-deep');
565-
await expect(navigationBackToInner).toBeVisible();
566-
await navigationBackToInner.click();
567-
568-
const thirdEvent = await thirdTransactionPromise;
569-
570567
// Verify third transaction
571568
expect(thirdEvent.transaction).toBe('/lazy/inner/:id/:anotherId/:someAnotherId');
572569
expect(thirdEvent.contexts?.trace?.op).toBe('navigation');

packages/react/src/reactrouter-compat-utils/instrumentation.tsx

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,26 @@ export function addResolvedRoutesToParent(resolvedRoutes: RouteObject[], parentR
7676
}
7777
}
7878

79+
/**
80+
* Determines if a navigation should be handled based on router state.
81+
* Only handles:
82+
* - PUSH navigations (always)
83+
* - POP navigations (only after initial pageload is complete)
84+
* - When router state is 'idle' (not 'loading' or 'submitting')
85+
*
86+
* During 'loading' or 'submitting', state.location may still have the old pathname,
87+
* which would cause us to create a span for the wrong route.
88+
*/
89+
function shouldHandleNavigation(
90+
state: { historyAction: string; navigation: { state: string } },
91+
isInitialPageloadComplete: boolean,
92+
): boolean {
93+
return (
94+
(state.historyAction === 'PUSH' || (state.historyAction === 'POP' && isInitialPageloadComplete)) &&
95+
state.navigation.state === 'idle'
96+
);
97+
}
98+
7999
export interface ReactRouterOptions {
80100
useEffect: UseEffect;
81101
useLocation: UseLocation;
@@ -277,14 +297,7 @@ export function createV6CompatibleWrapCreateBrowserRouter<
277297
// If we haven't seen a pageload span yet, keep waiting (don't mark as complete)
278298
}
279299

280-
// Only handle navigation when it's complete (state is idle).
281-
// During 'loading' or 'submitting', state.location may still have the old pathname,
282-
// which would cause us to create a span for the wrong route.
283-
const shouldHandleNavigation =
284-
(state.historyAction === 'PUSH' || (state.historyAction === 'POP' && isInitialPageloadComplete)) &&
285-
state.navigation.state === 'idle';
286-
287-
if (shouldHandleNavigation) {
300+
if (shouldHandleNavigation(state, isInitialPageloadComplete)) {
288301
handleNavigation({
289302
location: state.location,
290303
routes,
@@ -401,14 +414,7 @@ export function createV6CompatibleWrapCreateMemoryRouter<
401414
// If we haven't seen a pageload span yet, keep waiting (don't mark as complete)
402415
}
403416

404-
// Only handle navigation when it's complete (state is idle).
405-
// During 'loading' or 'submitting', state.location may still have the old pathname,
406-
// which would cause us to create a span for the wrong route.
407-
const shouldHandleNavigation =
408-
(state.historyAction === 'PUSH' || (state.historyAction === 'POP' && isInitialPageloadComplete)) &&
409-
state.navigation.state === 'idle';
410-
411-
if (shouldHandleNavigation) {
417+
if (shouldHandleNavigation(state, isInitialPageloadComplete)) {
412418
handleNavigation({
413419
location: state.location,
414420
routes,
@@ -622,8 +628,8 @@ function tryUpdateSpanName(
622628
newName: string,
623629
newSource: string,
624630
): void {
625-
const isNewNameBetter = newName !== currentSpanName && newName.includes(':');
626-
if (isNewNameBetter) {
631+
const isNewNameParameterized = newName !== currentSpanName && newName.includes(':');
632+
if (isNewNameParameterized) {
627633
activeSpan.updateName(newName);
628634
activeSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, newSource as 'route' | 'url' | 'custom');
629635
}

0 commit comments

Comments
 (0)