Skip to content

Commit cf2346b

Browse files
authored
fix(router-core): Non-nested paths (#5169)
This PR continues on from #5165 and primarily adds additional tests to path resolution and matchByPath for non-nested paths in additiona to e2e test for both react and solid router to verify non-nesting functionality. One additional issue was picked up for handling of normal path segments. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - New Features - Added non-nested demo routes and navigation examples (including dynamic and edit paths) for React and Solid, with headings, links, and parameter displays. - Bug Fixes - Improved path parsing/decoding for non-nested segments to prevent unintended nesting and ensure correct parameter values. - Tests - Added broad unit tests for non-nested path parsing/matching/resolution (case-sensitive/insensitive, wildcards, optional/fuzzy). - Added e2e tests validating non-nested navigation and params; reduced e2e flakiness by awaiting network idle. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 3b69de0 commit cf2346b

File tree

16 files changed

+1647
-30
lines changed

16 files changed

+1647
-30
lines changed

e2e/react-router/basic-file-based/src/routeTree.gen.ts

Lines changed: 104 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/non-nested/baz/$bazid')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
const params = Route.useParams()
9+
10+
return (
11+
<>
12+
<div data-testid="non-nested-bazid-heading">
13+
Hello "/non-nested/baz/$bazid"!
14+
</div>
15+
<div>
16+
params:{' '}
17+
<span data-testid="non-nested-bazid-param">
18+
{JSON.stringify(params)}
19+
</span>
20+
</div>
21+
</>
22+
)
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Outlet, createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/non-nested/baz')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<>
10+
<div data-testid="non-nested-baz-heading">Hello "/non-nested/baz"!</div>
11+
<Outlet />
12+
</>
13+
)
14+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/non-nested/baz_/$bazid/edit')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
const params = Route.useParams()
9+
return (
10+
<>
11+
<div data-testid="non-nested-bazid-edit-heading">
12+
Hello "/non-nested/baz_/$bazid/edit"!
13+
</div>
14+
<div>
15+
params:{' '}
16+
<span data-testid="non-nested-bazid-edit-param">
17+
{JSON.stringify(params)}
18+
</span>
19+
</div>
20+
</>
21+
)
22+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Link, Outlet, createFileRoute } from '@tanstack/react-router'
2+
3+
export const Route = createFileRoute('/non-nested')({
4+
component: RouteComponent,
5+
})
6+
7+
function RouteComponent() {
8+
return (
9+
<div>
10+
<h3 className="pb-2" data-testid="non-nested-path-heading">
11+
Non-nested paths
12+
</h3>
13+
<ul className="grid mb-2">
14+
<li>
15+
<Link
16+
from={Route.fullPath}
17+
data-testid="l-to-non-nested-bazid"
18+
to="./baz/$bazid"
19+
params={{ bazid: '123' }}
20+
>
21+
/non-nested/baz/123
22+
</Link>
23+
</li>
24+
<li>
25+
<Link
26+
from={Route.fullPath}
27+
data-testid="l-to-non-nested-bazid-edit"
28+
to="./baz/$bazid/edit"
29+
params={{ bazid: '456' }}
30+
>
31+
/non-nested/baz/456/edit
32+
</Link>
33+
</li>
34+
</ul>
35+
<Outlet />
36+
</div>
37+
)
38+
}

e2e/react-router/basic-file-based/tests/app.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,38 @@ test('Should remount deps when remountDeps does change ', async ({ page }) => {
308308
'Page component mounts: 2',
309309
)
310310
})
311+
312+
test('Should not nest non-nested paths', async ({ page }) => {
313+
await page.goto('/non-nested')
314+
await page.waitForURL('/non-nested')
315+
const nonNestedPathHeading = page.getByTestId('non-nested-path-heading')
316+
const bazIdLink = page.getByTestId('l-to-non-nested-bazid')
317+
const bazIdEditLink = page.getByTestId('l-to-non-nested-bazid-edit')
318+
319+
await expect(nonNestedPathHeading).toBeInViewport()
320+
await expect(bazIdLink).toHaveAttribute('href', '/non-nested/baz/123')
321+
await expect(bazIdEditLink).toHaveAttribute(
322+
'href',
323+
'/non-nested/baz/456/edit',
324+
)
325+
326+
await bazIdLink.click()
327+
await page.waitForURL('/non-nested/baz/123')
328+
const bazHeading = page.getByTestId('non-nested-baz-heading')
329+
const bazIdHeading = page.getByTestId('non-nested-bazid-heading')
330+
const bazIdParam = page.getByTestId('non-nested-bazid-param')
331+
await expect(nonNestedPathHeading).toBeInViewport()
332+
await expect(bazHeading).toBeInViewport()
333+
await expect(bazIdHeading).toBeInViewport()
334+
await expect(bazIdParam).toContainText(JSON.stringify({ bazid: '123' }))
335+
336+
await bazIdEditLink.click()
337+
await page.waitForURL('/non-nested/baz/456/edit')
338+
const bazIdEditHeading = page.getByTestId('non-nested-bazid-edit-heading')
339+
const bazIdEditParam = page.getByTestId('non-nested-bazid-edit-param')
340+
await expect(nonNestedPathHeading).toBeInViewport()
341+
await expect(bazHeading).toBeHidden()
342+
await expect(bazIdHeading).toBeHidden()
343+
await expect(bazIdEditHeading).toBeInViewport()
344+
await expect(bazIdEditParam).toContainText(JSON.stringify({ bazid: '456' }))
345+
})

0 commit comments

Comments
 (0)