Skip to content
Open
51 changes: 51 additions & 0 deletions e2e/react-start/basic/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { Route as LayoutRouteImport } from './routes/_layout'
import { Route as SpecialCharsRouteRouteImport } from './routes/specialChars/route'
import { Route as SearchParamsRouteRouteImport } from './routes/search-params/route'
import { Route as NotFoundRouteRouteImport } from './routes/not-found/route'
import { Route as CanonicalRouteRouteImport } from './routes/canonical/route'
import { Route as IndexRouteImport } from './routes/index'
import { Route as UsersIndexRouteImport } from './routes/users.index'
import { Route as SearchParamsIndexRouteImport } from './routes/search-params/index'
Expand Down Expand Up @@ -54,6 +55,7 @@ import { Route as MultiCookieRedirectTargetRouteImport } from './routes/multi-co
import { Route as ApiUsersRouteImport } from './routes/api.users'
import { Route as LayoutLayout2RouteImport } from './routes/_layout/_layout-2'
import { Route as SpecialCharsMalformedRouteRouteImport } from './routes/specialChars/malformed/route'
import { Route as CanonicalDeepRouteRouteImport } from './routes/canonical/deep/route'
import { Route as NotFoundParentBoundaryRouteRouteImport } from './routes/not-found/parent-boundary/route'
import { Route as NotFoundDeepRouteRouteImport } from './routes/not-found/deep/route'
import { Route as RedirectTargetIndexRouteImport } from './routes/redirect/$target/index'
Expand Down Expand Up @@ -152,6 +154,11 @@ const NotFoundRouteRoute = NotFoundRouteRouteImport.update({
path: '/not-found',
getParentRoute: () => rootRouteImport,
} as any)
const CanonicalRouteRoute = CanonicalRouteRouteImport.update({
id: '/canonical',
path: '/canonical',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
Expand Down Expand Up @@ -307,6 +314,11 @@ const SpecialCharsMalformedRouteRoute =
path: '/malformed',
getParentRoute: () => SpecialCharsRouteRoute,
} as any)
const CanonicalDeepRouteRoute = CanonicalDeepRouteRouteImport.update({
id: '/deep',
path: '/deep',
getParentRoute: () => CanonicalRouteRoute,
} as any)
const NotFoundParentBoundaryRouteRoute =
NotFoundParentBoundaryRouteRouteImport.update({
id: '/parent-boundary',
Expand Down Expand Up @@ -435,6 +447,7 @@ const NotFoundDeepBCDRoute = NotFoundDeepBCDRouteImport.update({

export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/canonical': typeof CanonicalRouteRouteWithChildren
'/not-found': typeof NotFoundRouteRouteWithChildren
'/search-params': typeof SearchParamsRouteRouteWithChildren
'/specialChars': typeof SpecialCharsRouteRouteWithChildren
Expand All @@ -449,6 +462,7 @@ export interface FileRoutesByFullPath {
'/stream': typeof StreamRoute
'/type-only-reexport': typeof TypeOnlyReexportRoute
'/users': typeof UsersRouteWithChildren
'/canonical/deep': typeof CanonicalDeepRouteRoute
'/not-found/deep': typeof NotFoundDeepRouteRouteWithChildren
'/not-found/parent-boundary': typeof NotFoundParentBoundaryRouteRouteWithChildren
'/specialChars/malformed': typeof SpecialCharsMalformedRouteRouteWithChildren
Expand Down Expand Up @@ -503,6 +517,7 @@ export interface FileRoutesByFullPath {
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/canonical': typeof CanonicalRouteRouteWithChildren
'/specialChars': typeof SpecialCharsRouteRouteWithChildren
'/async-scripts': typeof AsyncScriptsRoute
'/client-only': typeof ClientOnlyRoute
Expand All @@ -512,6 +527,7 @@ export interface FileRoutesByTo {
'/scripts': typeof ScriptsRoute
'/stream': typeof StreamRoute
'/type-only-reexport': typeof TypeOnlyReexportRoute
'/canonical/deep': typeof CanonicalDeepRouteRoute
'/specialChars/malformed': typeof SpecialCharsMalformedRouteRouteWithChildren
'/api/users': typeof ApiUsersRouteWithChildren
'/multi-cookie-redirect/target': typeof MultiCookieRedirectTargetRoute
Expand Down Expand Up @@ -563,6 +579,7 @@ export interface FileRoutesByTo {
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/canonical': typeof CanonicalRouteRouteWithChildren
'/not-found': typeof NotFoundRouteRouteWithChildren
'/search-params': typeof SearchParamsRouteRouteWithChildren
'/specialChars': typeof SpecialCharsRouteRouteWithChildren
Expand All @@ -578,6 +595,7 @@ export interface FileRoutesById {
'/stream': typeof StreamRoute
'/type-only-reexport': typeof TypeOnlyReexportRoute
'/users': typeof UsersRouteWithChildren
'/canonical/deep': typeof CanonicalDeepRouteRoute
'/not-found/deep': typeof NotFoundDeepRouteRouteWithChildren
'/not-found/parent-boundary': typeof NotFoundParentBoundaryRouteRouteWithChildren
'/specialChars/malformed': typeof SpecialCharsMalformedRouteRouteWithChildren
Expand Down Expand Up @@ -635,6 +653,7 @@ export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths:
| '/'
| '/canonical'
| '/not-found'
| '/search-params'
| '/specialChars'
Expand All @@ -649,6 +668,7 @@ export interface FileRouteTypes {
| '/stream'
| '/type-only-reexport'
| '/users'
| '/canonical/deep'
| '/not-found/deep'
| '/not-found/parent-boundary'
| '/specialChars/malformed'
Expand Down Expand Up @@ -703,6 +723,7 @@ export interface FileRouteTypes {
fileRoutesByTo: FileRoutesByTo
to:
| '/'
| '/canonical'
| '/specialChars'
| '/async-scripts'
| '/client-only'
Expand All @@ -712,6 +733,7 @@ export interface FileRouteTypes {
| '/scripts'
| '/stream'
| '/type-only-reexport'
| '/canonical/deep'
| '/specialChars/malformed'
| '/api/users'
| '/multi-cookie-redirect/target'
Expand Down Expand Up @@ -762,6 +784,7 @@ export interface FileRouteTypes {
id:
| '__root__'
| '/'
| '/canonical'
| '/not-found'
| '/search-params'
| '/specialChars'
Expand All @@ -777,6 +800,7 @@ export interface FileRouteTypes {
| '/stream'
| '/type-only-reexport'
| '/users'
| '/canonical/deep'
| '/not-found/deep'
| '/not-found/parent-boundary'
| '/specialChars/malformed'
Expand Down Expand Up @@ -833,6 +857,7 @@ export interface FileRouteTypes {
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
CanonicalRouteRoute: typeof CanonicalRouteRouteWithChildren
NotFoundRouteRoute: typeof NotFoundRouteRouteWithChildren
SearchParamsRouteRoute: typeof SearchParamsRouteRouteWithChildren
SpecialCharsRouteRoute: typeof SpecialCharsRouteRouteWithChildren
Expand Down Expand Up @@ -964,6 +989,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof NotFoundRouteRouteImport
parentRoute: typeof rootRouteImport
}
'/canonical': {
id: '/canonical'
path: '/canonical'
fullPath: '/canonical'
preLoaderRoute: typeof CanonicalRouteRouteImport
parentRoute: typeof rootRouteImport
}
'/': {
id: '/'
path: '/'
Expand Down Expand Up @@ -1174,6 +1206,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof SpecialCharsMalformedRouteRouteImport
parentRoute: typeof SpecialCharsRouteRoute
}
'/canonical/deep': {
id: '/canonical/deep'
path: '/deep'
fullPath: '/canonical/deep'
preLoaderRoute: typeof CanonicalDeepRouteRouteImport
parentRoute: typeof CanonicalRouteRoute
}
'/not-found/parent-boundary': {
id: '/not-found/parent-boundary'
path: '/parent-boundary'
Expand Down Expand Up @@ -1338,6 +1377,17 @@ declare module '@tanstack/react-router' {
}
}

interface CanonicalRouteRouteChildren {
CanonicalDeepRouteRoute: typeof CanonicalDeepRouteRoute
}

const CanonicalRouteRouteChildren: CanonicalRouteRouteChildren = {
CanonicalDeepRouteRoute: CanonicalDeepRouteRoute,
}

const CanonicalRouteRouteWithChildren = CanonicalRouteRoute._addFileChildren(
CanonicalRouteRouteChildren,
)
interface NotFoundDeepBCRouteRouteChildren {
NotFoundDeepBCDRoute: typeof NotFoundDeepBCDRoute
}
Expand Down Expand Up @@ -1589,6 +1639,7 @@ const FooBarQuxHereRouteWithChildren = FooBarQuxHereRoute._addFileChildren(

const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
CanonicalRouteRoute: CanonicalRouteRouteWithChildren,
NotFoundRouteRoute: NotFoundRouteRouteWithChildren,
SearchParamsRouteRoute: SearchParamsRouteRouteWithChildren,
SpecialCharsRouteRoute: SpecialCharsRouteRouteWithChildren,
Expand Down
12 changes: 12 additions & 0 deletions e2e/react-start/basic/src/routes/canonical/deep/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/canonical/deep')({
head: () => ({
links: [{ rel: 'canonical', href: 'https://example.com/canonical/deep' }],
}),
component: RouteComponent,
})

function RouteComponent() {
return <div>Hello "/canonical/deep"!</div>
}
12 changes: 12 additions & 0 deletions e2e/react-start/basic/src/routes/canonical/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/canonical')({
head: () => ({
links: [{ rel: 'canonical', href: 'https://example.com/canonical' }],
}),
component: RouteComponent,
})

function RouteComponent() {
return <div>Hello "/canonical"!</div>
}
18 changes: 18 additions & 0 deletions e2e/react-start/basic/tests/canonical.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { expect } from '@playwright/test'
import { test } from '@tanstack/router-e2e-utils'

test('Deduplicates child canonical links over parent', async ({ page }) => {
await page.goto('/canonical/deep')
await page.waitForURL('/canonical/deep')

await expect(page.locator('link[rel="canonical"]')).toHaveCount(1)

// Get all canonical links
const links = await page.locator('link[rel="canonical"]').all()
expect(links).toHaveLength(1)

await expect(page.locator('link[rel="canonical"]')).toHaveAttribute(
'href',
'https://example.com/canonical/deep',
)
})
Loading
Loading