Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 81 additions & 23 deletions e2e/react-router/basic-file-based/src/routeTree.gen.ts

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions e2e/react-router/basic-file-based/src/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ function RootComponent() {
>
relative routing
</Link>{' '}
<Link
to="/대한민국"
activeProps={{
className: 'font-bold',
}}
>
unicode path
</Link>{' '}
<Link
// @ts-expect-error
to="/this-route-does-not-exist"
Expand Down
18 changes: 18 additions & 0 deletions e2e/react-router/basic-file-based/src/routes/params-ps/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ function RouteComponent() {
/params-ps/named/$foo
</Link>
</li>
<li>
<Link
data-testid="l-to-named-foo-special-characters"
to="/params-ps/named/$foo"
params={{ foo: 'foo%\\/🚀대' }}
>
/params-ps/named/$foo - with special characters
</Link>
</li>
<li>
<Link
data-testid="l-to-named-prefixfoo"
Expand Down Expand Up @@ -58,6 +67,15 @@ function RouteComponent() {
/params-ps/wildcard/$ with escaped params
</Link>
</li>
<li>
<Link
data-testid="l-to-wildcard-encoded"
to="/params-ps/wildcard/$"
params={{ _splat: '%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD' }}
>
/params-ps/wildcard/$ with encoded params
</Link>
</li>
<li>
<Link
data-testid="l-to-wildcard-prefixfoo"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ function RouteComponent() {
>
Bar2
</Link>
<Link
from={Route.fullPath}
to="./$bar"
params={{ bar: '🚀%2F/abc대' }}
data-testid="params-foo-links-bar-special-characters"
>
Bar with special characters
</Link>
<Outlet />
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ function RouteComponent() {
>
go to /search-params/default?default=d2
</Link>
<br />
<Link
data-testid="link-to-default-with-search-special-characters"
to="/search-params/default"
search={{ default: '🚀대한민국' }}
>
go to /search-params/default?default=🚀대한민국
</Link>
<br />
<Link
data-testid="link-to-default-with-search-encoded-characters"
to="/search-params/default"
search={{ default: '%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD' }}
>
go to
/search-params/default?default=%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD
</Link>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/search-params')({
beforeLoad: async () => {
await new Promise((resolve) => setTimeout(resolve, 1000))
await new Promise((resolve) => setTimeout(resolve, 100))
return { hello: 'world' as string }
},
})
9 changes: 0 additions & 9 deletions e2e/react-router/basic-file-based/src/routes/대한민국.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Link, Outlet, createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/대한민국')({
component: RouteComponent,
})

function RouteComponent() {
return (
<div>
<h3 className="pb-2" data-testid="unicode-heading">
Hello "/대한민국"!
</h3>
<ul className="grid mb-2">
<li>
<Link
data-testid="l-to-named-latin"
from={Route.fullPath}
to="./🚀/$id"
params={{ id: 'foo' }}
activeProps={{ className: 'font-bold' }}
>
link to latin id
</Link>
</li>
<li>
<Link
data-testid="l-to-named-unicode"
from={Route.fullPath}
to="./🚀/$id"
params={{ id: 'foo%\\/🚀대' }}
activeProps={{ className: 'font-bold' }}
>
link to unicode id
</Link>
</li>
<li>
<Link
data-testid="l-to-wildcard-latin"
from={Route.fullPath}
to="./wildcard/$"
params={{ _splat: 'foo/bar' }}
activeProps={{ className: 'font-bold' }}
>
link to foo/bar
</Link>
</li>
<li>
<Link
data-testid="l-to-wildcard-unicode"
from={Route.fullPath}
to="./wildcard/$"
params={{ _splat: 'foo%\\/🚀대' }}
activeProps={{ className: 'font-bold' }}
>
link to foo%\/🚀대
</Link>
</li>
</ul>
<hr />
<Outlet />
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/대한민국/wildcard/$')({
component: RouteComponent,
})

function RouteComponent() {
const params = Route.useParams()

return (
<div>
<h3 data-testid="unicode-wildcard-heading">Unicode Wildcard Params</h3>
<div>
Hello /대한민국/wildcard/
<span data-testid="unicode-wildcard-params">{params._splat}</span>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/대한민국/🚀/$id')({
component: RouteComponent,
})

function RouteComponent() {
const params = Route.useParams()

return (
<div>
<h3 data-testid="unicode-named-heading">Unicode Named Params</h3>
<div>
Hello /대한민국/🚀/
<span data-testid="unicode-named-params">{params.id}</span>
</div>
</div>
)
}
10 changes: 10 additions & 0 deletions e2e/react-router/basic-file-based/tests/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,13 @@ test('Should remount deps when remountDeps does change ', async ({ page }) => {
'Page component mounts: 3',
)
})

test.describe('Unicode route rendering', () => {
test('should render non-latin route correctly', async ({ page, baseURL }) => {
await page.goto('/대한민국')

await expect(page.locator('body')).toContainText('Hello "/대한민국"!')

expect(page.url()).toBe(`${baseURL}/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD`)
})
})
136 changes: 131 additions & 5 deletions e2e/react-router/basic-file-based/tests/params.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ test.describe('params operations + prefix/suffix', () => {
params: { foo: 'foo' },
destHeadingId: 'ParamsNamedFooSuffix',
},
{
id: 'l-to-named-foo-special-characters',
pathname: '/params-ps/named/foo%25%5C%2F%F0%9F%9A%80%EB%8C%80',
params: { foo: 'foo%\\/🚀대' },
destHeadingId: 'ParamsNamedFoo',
},
] satisfies Array<{
id: string
pathname: string
Expand Down Expand Up @@ -317,6 +323,16 @@ test.describe('params operations + prefix/suffix', () => {
},
destHeadingId: 'ParamsWildcardSplatSuffix',
},
{
id: 'l-to-wildcard-encoded',
pathname:
'/params-ps/wildcard/%25EB%258C%2580%25ED%2595%259C%25EB%25AF%25BC%25EA%25B5%25AD',
params: {
'*': '%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD',
_splat: '%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD',
},
destHeadingId: 'ParamsWildcardSplat',
},
] satisfies Array<{
id: string
pathname: string
Expand Down Expand Up @@ -368,12 +384,122 @@ test.describe('params operations + prefix/suffix', () => {
})
})

test.describe('Unicode route rendering', () => {
test('should render non-latin route correctly', async ({ page, baseURL }) => {
await page.goto('/대한민국')
test.describe('Unicode params', () => {
test('should render non-latin route correctly across multiple params', async ({
page,
baseURL,
}) => {
await page.goto('/params-ps')
await page.waitForURL('/params-ps')
const fooLink = page.getByTestId('l-to-named-foo-special-characters')

await fooLink.click()
await page.waitForURL('/params-ps/named/foo%25%5C%2F%F0%9F%9A%80%EB%8C%80')

expect(page.url()).toBe(
`${baseURL}/params-ps/named/foo%25%5C%2F%F0%9F%9A%80%EB%8C%80`,
)

const headingEl = page.getByRole('heading', { name: 'ParamsNamedFoo' })
await expect(headingEl).toBeVisible()
let paramsEl = page.getByTestId('params-output')
let paramsText = await paramsEl.innerText()
expect(paramsText).toEqual(JSON.stringify({ foo: 'foo%\\/🚀대' }))

const barLink = page.getByTestId('params-foo-links-bar-special-characters')

await barLink.click()

await page.waitForURL(
'/params-ps/named/foo%25%5C%2F%F0%9F%9A%80%EB%8C%80/%F0%9F%9A%80%252F%2Fabc%EB%8C%80',
)

expect(page.url()).toBe(
`${baseURL}/params-ps/named/foo%25%5C%2F%F0%9F%9A%80%EB%8C%80/%F0%9F%9A%80%252F%2Fabc%EB%8C%80`,
)

paramsEl = page.getByTestId('foo-bar-value')
paramsText = await paramsEl.innerText()
expect(paramsText).toEqual('🚀%2F/abc대')
})

test.describe('should handle routes with non-latin paths and params correctly', () => {
const testCases = [
{
name: 'named',
childPath: '🚀',
latinParams: 'foo',
unicodeParams: 'foo%\\/🚀대',
},
{
name: 'wildcard',
childPath: 'wildcard',
latinParams: 'foo/bar',
unicodeParams: 'foo%\\/🚀대',
},
]

testCases.forEach(({ name, childPath, latinParams, unicodeParams }) => {
test(`${name} params`, async ({ page, baseURL }) => {
const pascalCaseName = name.charAt(0).toUpperCase() + name.slice(1)
const routeParentPath = '/대한민국'
const encodedRouteParentPath = encodeURI(routeParentPath)
const childRoutePath = `${routeParentPath}/${childPath}`
const encodedChildRoutePath = encodeURI(childRoutePath)

await page.goto(routeParentPath)
await page.waitForURL(encodedRouteParentPath)

const headingRootEl = page.getByTestId('unicode-heading')

expect(await headingRootEl.innerText()).toBe('Hello "/대한민국"!')

const latinLink = page.getByTestId(`l-to-${name}-latin`)
const unicodeLink = page.getByTestId(`l-to-${name}-unicode`)

await expect(latinLink).not.toContainClass('font-bold')
await expect(unicodeLink).not.toContainClass('font-bold')

await latinLink.click()

await expect(page.locator('body')).toContainText('Hello "/대한민국"!')
await page.waitForURL(`${encodedChildRoutePath}/${latinParams}`)

expect(page.url()).toBe(`${baseURL}/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD`)
expect(page.url()).toBe(
`${baseURL}${encodedChildRoutePath}/${latinParams}`,
)

await expect(latinLink).toContainClass('font-bold')
await expect(unicodeLink).not.toContainClass('font-bold')

const headingEl = page.getByTestId(`unicode-${name}-heading`)
const paramsEl = page.getByTestId(`unicode-${name}-params`)

expect(await headingEl.innerText()).toBe(
`Unicode ${pascalCaseName} Params`,
)
expect(await paramsEl.innerText()).toBe(latinParams)

await unicodeLink.click()

const encodedParams =
name === 'wildcard'
? encodeURI(unicodeParams)
: encodeURIComponent(unicodeParams)

await page.waitForURL(`${encodedChildRoutePath}/${encodedParams}`)

expect(page.url()).toBe(
`${baseURL}${encodedChildRoutePath}/${encodedParams}`,
)

await expect(latinLink).not.toContainClass('font-bold')
await expect(unicodeLink).toContainClass('font-bold')

expect(await headingEl.innerText()).toBe(
`Unicode ${pascalCaseName} Params`,
)
expect(await paramsEl.innerText()).toBe(unicodeParams)
})
})
})
})
Loading
Loading