Skip to content

Commit a1324bb

Browse files
fix: navigate() with href containing basepath (#6335)
Co-authored-by: Manuel Schiller <manuel.schiller@caligano.de>
1 parent e93a4c3 commit a1324bb

File tree

13 files changed

+271
-4
lines changed

13 files changed

+271
-4
lines changed

e2e/react-router/basepath-file-based/src/routes/index.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,27 @@ function App() {
3939
}
4040
>
4141
Navigate to /redirectReload
42+
</button>{' '}
43+
<button
44+
data-testid="to-about-href-with-basepath-btn"
45+
onClick={() =>
46+
navigate({
47+
href: '/app/about',
48+
})
49+
}
50+
>
51+
Navigate to /about using href with basepath
52+
</button>{' '}
53+
<button
54+
data-testid="to-about-href-with-basepath-reload-btn"
55+
onClick={() =>
56+
navigate({
57+
href: '/app/about',
58+
reloadDocument: true,
59+
})
60+
}
61+
>
62+
Navigate to /about using href with basepath (reloadDocument)
4263
</button>
4364
</div>
4465
)

e2e/react-router/basepath-file-based/tests/reload-document.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,27 @@ test('redirect respects basepath with reloadDocument = true on redirect', async
3838
await page.waitForURL('/app/about')
3939
await expect(page.getByTestId(`about-component`)).toBeInViewport()
4040
})
41+
42+
test('navigate() with href containing basepath', async ({ page }) => {
43+
await page.goto(`/app/`)
44+
await expect(page.getByTestId(`home-component`)).toBeInViewport()
45+
46+
const aboutBtn = page.getByTestId(`to-about-href-with-basepath-btn`)
47+
await aboutBtn.click()
48+
// Should navigate to /app/about, NOT /app/app/about
49+
await page.waitForURL('/app/about')
50+
await expect(page.getByTestId(`about-component`)).toBeInViewport()
51+
})
52+
53+
test('navigate() with href containing basepath and reloadDocument=true', async ({
54+
page,
55+
}) => {
56+
await page.goto(`/app/`)
57+
await expect(page.getByTestId(`home-component`)).toBeInViewport()
58+
59+
const aboutBtn = page.getByTestId(`to-about-href-with-basepath-reload-btn`)
60+
await aboutBtn.click()
61+
// Should navigate to /app/about, NOT stay on current page
62+
await page.waitForURL('/app/about')
63+
await expect(page.getByTestId(`about-component`)).toBeInViewport()
64+
})

e2e/react-start/custom-basepath/src/routeTree.gen.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import { Route as rootRouteImport } from './routes/__root'
1212
import { Route as UsersRouteImport } from './routes/users'
1313
import { Route as PostsRouteImport } from './routes/posts'
14+
import { Route as NavigateTestRouteImport } from './routes/navigate-test'
1415
import { Route as LogoutRouteImport } from './routes/logout'
1516
import { Route as DeferredRouteImport } from './routes/deferred'
1617
import { Route as IndexRouteImport } from './routes/index'
@@ -34,6 +35,11 @@ const PostsRoute = PostsRouteImport.update({
3435
path: '/posts',
3536
getParentRoute: () => rootRouteImport,
3637
} as any)
38+
const NavigateTestRoute = NavigateTestRouteImport.update({
39+
id: '/navigate-test',
40+
path: '/navigate-test',
41+
getParentRoute: () => rootRouteImport,
42+
} as any)
3743
const LogoutRoute = LogoutRouteImport.update({
3844
id: '/logout',
3945
path: '/logout',
@@ -99,6 +105,7 @@ export interface FileRoutesByFullPath {
99105
'/': typeof IndexRoute
100106
'/deferred': typeof DeferredRoute
101107
'/logout': typeof LogoutRoute
108+
'/navigate-test': typeof NavigateTestRoute
102109
'/posts': typeof PostsRouteWithChildren
103110
'/users': typeof UsersRouteWithChildren
104111
'/api/users': typeof ApiUsersRouteWithChildren
@@ -115,6 +122,7 @@ export interface FileRoutesByTo {
115122
'/': typeof IndexRoute
116123
'/deferred': typeof DeferredRoute
117124
'/logout': typeof LogoutRoute
125+
'/navigate-test': typeof NavigateTestRoute
118126
'/api/users': typeof ApiUsersRouteWithChildren
119127
'/posts/$postId': typeof PostsPostIdRoute
120128
'/redirect/throw-it': typeof RedirectThrowItRoute
@@ -130,6 +138,7 @@ export interface FileRoutesById {
130138
'/': typeof IndexRoute
131139
'/deferred': typeof DeferredRoute
132140
'/logout': typeof LogoutRoute
141+
'/navigate-test': typeof NavigateTestRoute
133142
'/posts': typeof PostsRouteWithChildren
134143
'/users': typeof UsersRouteWithChildren
135144
'/api/users': typeof ApiUsersRouteWithChildren
@@ -148,6 +157,7 @@ export interface FileRouteTypes {
148157
| '/'
149158
| '/deferred'
150159
| '/logout'
160+
| '/navigate-test'
151161
| '/posts'
152162
| '/users'
153163
| '/api/users'
@@ -164,6 +174,7 @@ export interface FileRouteTypes {
164174
| '/'
165175
| '/deferred'
166176
| '/logout'
177+
| '/navigate-test'
167178
| '/api/users'
168179
| '/posts/$postId'
169180
| '/redirect/throw-it'
@@ -178,6 +189,7 @@ export interface FileRouteTypes {
178189
| '/'
179190
| '/deferred'
180191
| '/logout'
192+
| '/navigate-test'
181193
| '/posts'
182194
| '/users'
183195
| '/api/users'
@@ -195,6 +207,7 @@ export interface RootRouteChildren {
195207
IndexRoute: typeof IndexRoute
196208
DeferredRoute: typeof DeferredRoute
197209
LogoutRoute: typeof LogoutRoute
210+
NavigateTestRoute: typeof NavigateTestRoute
198211
PostsRoute: typeof PostsRouteWithChildren
199212
UsersRoute: typeof UsersRouteWithChildren
200213
ApiUsersRoute: typeof ApiUsersRouteWithChildren
@@ -219,6 +232,13 @@ declare module '@tanstack/react-router' {
219232
preLoaderRoute: typeof PostsRouteImport
220233
parentRoute: typeof rootRouteImport
221234
}
235+
'/navigate-test': {
236+
id: '/navigate-test'
237+
path: '/navigate-test'
238+
fullPath: '/navigate-test'
239+
preLoaderRoute: typeof NavigateTestRouteImport
240+
parentRoute: typeof rootRouteImport
241+
}
222242
'/logout': {
223243
id: '/logout'
224244
path: '/logout'
@@ -346,6 +366,7 @@ const rootRouteChildren: RootRouteChildren = {
346366
IndexRoute: IndexRoute,
347367
DeferredRoute: DeferredRoute,
348368
LogoutRoute: LogoutRoute,
369+
NavigateTestRoute: NavigateTestRoute,
349370
PostsRoute: PostsRouteWithChildren,
350371
UsersRoute: UsersRouteWithChildren,
351372
ApiUsersRoute: ApiUsersRouteWithChildren,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/navigate-test')({
4+
component: NavigateTest,
5+
})
6+
7+
function NavigateTest() {
8+
const navigate = Route.useNavigate()
9+
10+
return (
11+
<div className="p-2">
12+
<h3 data-testid="navigate-test-component">Navigate Test</h3>
13+
<button
14+
data-testid="to-posts-href-with-basepath-btn"
15+
onClick={() =>
16+
navigate({
17+
href: '/custom/basepath/posts',
18+
})
19+
}
20+
>
21+
Navigate to /posts using href with basepath
22+
</button>{' '}
23+
<button
24+
data-testid="to-posts-href-with-basepath-reload-btn"
25+
onClick={() =>
26+
navigate({
27+
href: '/custom/basepath/posts',
28+
reloadDocument: true,
29+
})
30+
}
31+
>
32+
Navigate to /posts using href with basepath (reloadDocument)
33+
</button>
34+
</div>
35+
)
36+
}

e2e/react-start/custom-basepath/src/routes/posts.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function PostsComponent() {
1818
const posts = Route.useLoaderData()
1919

2020
return (
21-
<div className="p-2 flex gap-2">
21+
<div className="p-2 flex gap-2" data-testid="posts-component">
2222
<ul className="list-disc pl-4">
2323
{[...posts, { id: 'i-do-not-exist', title: 'Non-existent Post' }].map(
2424
(post) => {

e2e/react-start/custom-basepath/tests/navigation.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,28 @@ test('server-side redirect', async ({ page, baseURL }) => {
7575
expect(headers.get('location')).toBe('/custom/basepath/posts/1')
7676
})
7777
})
78+
79+
test('navigate() with href containing basepath', async ({ page, baseURL }) => {
80+
await page.goto('/navigate-test')
81+
await expect(page.getByTestId('navigate-test-component')).toBeVisible()
82+
83+
const btn = page.getByTestId('to-posts-href-with-basepath-btn')
84+
await btn.click()
85+
// Should navigate to /custom/basepath/posts, NOT /custom/basepath/custom/basepath/posts
86+
await page.waitForURL(`${baseURL}/posts`)
87+
await expect(page.getByTestId('posts-component')).toBeVisible()
88+
})
89+
90+
test('navigate() with href containing basepath and reloadDocument=true', async ({
91+
page,
92+
baseURL,
93+
}) => {
94+
await page.goto('/navigate-test')
95+
await expect(page.getByTestId('navigate-test-component')).toBeVisible()
96+
97+
const btn = page.getByTestId('to-posts-href-with-basepath-reload-btn')
98+
await btn.click()
99+
// Should navigate to /custom/basepath/posts, NOT stay on current page
100+
await page.waitForURL(`${baseURL}/posts`)
101+
await expect(page.getByTestId('posts-component')).toBeVisible()
102+
})

e2e/solid-router/basepath-file-based/src/routes/index.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,27 @@ function App() {
1919
}
2020
>
2121
Navigate to /about with document reload
22+
</button>{' '}
23+
<button
24+
data-testid="to-about-href-with-basepath-btn"
25+
onClick={() =>
26+
navigate({
27+
href: '/app/about',
28+
})
29+
}
30+
>
31+
Navigate to /about using href with basepath
32+
</button>{' '}
33+
<button
34+
data-testid="to-about-href-with-basepath-reload-btn"
35+
onClick={() =>
36+
navigate({
37+
href: '/app/about',
38+
reloadDocument: true,
39+
})
40+
}
41+
>
42+
Navigate to /about using href with basepath (reloadDocument)
2243
</button>
2344
</div>
2445
)

e2e/solid-router/basepath-file-based/tests/reload-document.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,27 @@ test('navigate() respects basepath for when reloadDocument=true', async ({
1616
await page.waitForURL('/app/')
1717
await expect(page.getByTestId(`home-component`)).toBeInViewport()
1818
})
19+
20+
test('navigate() with href containing basepath', async ({ page }) => {
21+
await page.goto(`/app/`)
22+
await expect(page.getByTestId(`home-component`)).toBeInViewport()
23+
24+
const aboutBtn = page.getByTestId(`to-about-href-with-basepath-btn`)
25+
await aboutBtn.click()
26+
// Should navigate to /app/about, NOT /app/app/about
27+
await page.waitForURL('/app/about')
28+
await expect(page.getByTestId(`about-component`)).toBeInViewport()
29+
})
30+
31+
test('navigate() with href containing basepath and reloadDocument=true', async ({
32+
page,
33+
}) => {
34+
await page.goto(`/app/`)
35+
await expect(page.getByTestId(`home-component`)).toBeInViewport()
36+
37+
const aboutBtn = page.getByTestId(`to-about-href-with-basepath-reload-btn`)
38+
await aboutBtn.click()
39+
// Should navigate to /app/about, NOT stay on current page
40+
await page.waitForURL('/app/about')
41+
await expect(page.getByTestId(`about-component`)).toBeInViewport()
42+
})

e2e/solid-start/custom-basepath/src/routeTree.gen.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import { Route as rootRouteImport } from './routes/__root'
1212
import { Route as UsersRouteImport } from './routes/users'
1313
import { Route as PostsRouteImport } from './routes/posts'
14+
import { Route as NavigateTestRouteImport } from './routes/navigate-test'
1415
import { Route as LogoutRouteImport } from './routes/logout'
1516
import { Route as DeferredRouteImport } from './routes/deferred'
1617
import { Route as IndexRouteImport } from './routes/index'
@@ -34,6 +35,11 @@ const PostsRoute = PostsRouteImport.update({
3435
path: '/posts',
3536
getParentRoute: () => rootRouteImport,
3637
} as any)
38+
const NavigateTestRoute = NavigateTestRouteImport.update({
39+
id: '/navigate-test',
40+
path: '/navigate-test',
41+
getParentRoute: () => rootRouteImport,
42+
} as any)
3743
const LogoutRoute = LogoutRouteImport.update({
3844
id: '/logout',
3945
path: '/logout',
@@ -99,6 +105,7 @@ export interface FileRoutesByFullPath {
99105
'/': typeof IndexRoute
100106
'/deferred': typeof DeferredRoute
101107
'/logout': typeof LogoutRoute
108+
'/navigate-test': typeof NavigateTestRoute
102109
'/posts': typeof PostsRouteWithChildren
103110
'/users': typeof UsersRouteWithChildren
104111
'/api/users': typeof ApiUsersRouteWithChildren
@@ -115,6 +122,7 @@ export interface FileRoutesByTo {
115122
'/': typeof IndexRoute
116123
'/deferred': typeof DeferredRoute
117124
'/logout': typeof LogoutRoute
125+
'/navigate-test': typeof NavigateTestRoute
118126
'/api/users': typeof ApiUsersRouteWithChildren
119127
'/posts/$postId': typeof PostsPostIdRoute
120128
'/redirect/throw-it': typeof RedirectThrowItRoute
@@ -130,6 +138,7 @@ export interface FileRoutesById {
130138
'/': typeof IndexRoute
131139
'/deferred': typeof DeferredRoute
132140
'/logout': typeof LogoutRoute
141+
'/navigate-test': typeof NavigateTestRoute
133142
'/posts': typeof PostsRouteWithChildren
134143
'/users': typeof UsersRouteWithChildren
135144
'/api/users': typeof ApiUsersRouteWithChildren
@@ -148,6 +157,7 @@ export interface FileRouteTypes {
148157
| '/'
149158
| '/deferred'
150159
| '/logout'
160+
| '/navigate-test'
151161
| '/posts'
152162
| '/users'
153163
| '/api/users'
@@ -164,6 +174,7 @@ export interface FileRouteTypes {
164174
| '/'
165175
| '/deferred'
166176
| '/logout'
177+
| '/navigate-test'
167178
| '/api/users'
168179
| '/posts/$postId'
169180
| '/redirect/throw-it'
@@ -178,6 +189,7 @@ export interface FileRouteTypes {
178189
| '/'
179190
| '/deferred'
180191
| '/logout'
192+
| '/navigate-test'
181193
| '/posts'
182194
| '/users'
183195
| '/api/users'
@@ -195,6 +207,7 @@ export interface RootRouteChildren {
195207
IndexRoute: typeof IndexRoute
196208
DeferredRoute: typeof DeferredRoute
197209
LogoutRoute: typeof LogoutRoute
210+
NavigateTestRoute: typeof NavigateTestRoute
198211
PostsRoute: typeof PostsRouteWithChildren
199212
UsersRoute: typeof UsersRouteWithChildren
200213
ApiUsersRoute: typeof ApiUsersRouteWithChildren
@@ -219,6 +232,13 @@ declare module '@tanstack/solid-router' {
219232
preLoaderRoute: typeof PostsRouteImport
220233
parentRoute: typeof rootRouteImport
221234
}
235+
'/navigate-test': {
236+
id: '/navigate-test'
237+
path: '/navigate-test'
238+
fullPath: '/navigate-test'
239+
preLoaderRoute: typeof NavigateTestRouteImport
240+
parentRoute: typeof rootRouteImport
241+
}
222242
'/logout': {
223243
id: '/logout'
224244
path: '/logout'
@@ -346,6 +366,7 @@ const rootRouteChildren: RootRouteChildren = {
346366
IndexRoute: IndexRoute,
347367
DeferredRoute: DeferredRoute,
348368
LogoutRoute: LogoutRoute,
369+
NavigateTestRoute: NavigateTestRoute,
349370
PostsRoute: PostsRouteWithChildren,
350371
UsersRoute: UsersRouteWithChildren,
351372
ApiUsersRoute: ApiUsersRouteWithChildren,

0 commit comments

Comments
 (0)