Skip to content

Commit 3f3b5b9

Browse files
committed
add case if no pathname set
1 parent 00a791a commit 3f3b5b9

3 files changed

Lines changed: 40 additions & 5 deletions

File tree

dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export default function PerformancePage() {
88
<Link to="/performance/ssr">SSR Page</Link>
99
<Link to="/performance/with/sentry">With Param Page</Link>
1010
<Link to={{ pathname: '/performance/with/object-nav', search: '?foo=bar' }}>Object Navigate</Link>
11+
<Link to={{ search: '?query=test' }}>Search Only Navigate</Link>
1112
<Link to="/performance/server-loader">Server Loader</Link>
1213
</nav>
1314
</div>

dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/navigation.client.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,29 @@ test.describe('client - navigation performance', () => {
8181
});
8282
});
8383

84+
test('should create navigation transaction when navigating with search-only object `to` prop', async ({ page }) => {
85+
const txPromise = waitForTransaction(APP_NAME, async transactionEvent => {
86+
return transactionEvent.transaction === '/performance' && transactionEvent.contexts?.trace?.op === 'navigation';
87+
});
88+
89+
await page.goto(`/performance`); // pageload
90+
await page.waitForTimeout(1000); // give it a sec before navigation
91+
await page.getByRole('link', { name: 'Search Only Navigate' }).click(); // navigation with search-only object to
92+
93+
const transaction = await txPromise;
94+
95+
expect(transaction).toMatchObject({
96+
contexts: {
97+
trace: {
98+
op: 'navigation',
99+
origin: 'auto.navigation.react_router',
100+
},
101+
},
102+
transaction: '/performance',
103+
type: 'transaction',
104+
});
105+
});
106+
84107
test('should update navigation transaction for dynamic routes', async ({ page }) => {
85108
const txPromise = waitForTransaction(APP_NAME, async transactionEvent => {
86109
return transactionEvent.transaction === '/performance/with/:param';
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
/**
2-
* Resolves a navigate argument to a string path.
2+
* Resolves a navigate argument to a pathname string.
33
*
4-
* React Router's navigate() accepts a string, number, or To object ({ pathname, search, hash }).
4+
* React Router's navigate() accepts a string, number, or a To object ({ pathname, search, hash }).
5+
* All fields in the To object are optional (Partial<Path>), so we need to detect object args
6+
* to avoid "[object Object]" transaction names.
57
*/
68
export function resolveNavigateArg(target: unknown): string {
7-
if (typeof target === 'object' && target !== null && 'pathname' in target) {
8-
return (target as { pathname?: string }).pathname || '/';
9+
if (typeof target !== 'object' || target === null) {
10+
// string or number
11+
return String(target);
912
}
10-
return String(target);
13+
14+
// Object `to` with pathname
15+
const pathname = (target as Record<string, unknown>).pathname;
16+
if (typeof pathname === 'string') {
17+
return pathname || '/';
18+
}
19+
20+
// Object `to` without pathname - navigation stays on current path
21+
return (typeof window !== 'undefined' && window.location?.pathname) || '/';
1122
}

0 commit comments

Comments
 (0)