From cffb35776c2e2b0fe60dc982a088fc51216565b7 Mon Sep 17 00:00:00 2001 From: Nico Lynzaad Date: Thu, 28 Aug 2025 23:15:33 +0200 Subject: [PATCH 1/8] refactor to control path change reactivity separately in Link and useNavigate --- packages/react-router/src/link.tsx | 29 +++++++-- .../react-router/src/useActiveLocation.ts | 57 ----------------- packages/react-router/src/useNavigate.tsx | 21 +++++-- packages/solid-router/src/link.tsx | 29 +++++++-- .../solid-router/src/useActiveLocation.ts | 61 ------------------- packages/solid-router/src/useNavigate.tsx | 24 +++++--- 6 files changed, 83 insertions(+), 138 deletions(-) delete mode 100644 packages/react-router/src/useActiveLocation.ts delete mode 100644 packages/solid-router/src/useActiveLocation.ts diff --git a/packages/react-router/src/link.tsx b/packages/react-router/src/link.tsx index 6fea974ffe..6ce942135f 100644 --- a/packages/react-router/src/link.tsx +++ b/packages/react-router/src/link.tsx @@ -4,10 +4,12 @@ import { deepEqual, exactPathTest, functionalUpdate, + last, preloadWarning, removeTrailingSlash, } from '@tanstack/router-core' -import { useActiveLocation } from './useActiveLocation' +import { useMemo } from 'react' +import { useMatch } from './useMatch' import { useRouterState } from './useRouterState' import { useRouter } from './useRouter' @@ -99,15 +101,33 @@ export function useLinkProps< structuralSharing: true as any, }) - // subscribe to location here to re-build fromPath if it changes const routerLocation = useRouterState({ select: (s) => s.location, structuralSharing: true as any, }) - const { getFromPath } = useActiveLocation() + const matchIndex = useMatch({ + strict: false, + select: (match) => match.index, + }) - const from = getFromPath(options.from) + // subscribe to location here to re-build fromPath if it changes + const from = useMemo( + () => { + const activeLocationMatches = router.matchRoutes(routerLocation, { + _buildLocation: false, + }) + + const activeLocationMatch = last(activeLocationMatches) + + return ( + options.from ?? + activeLocationMatch?.fullPath ?? + router.state.matches[matchIndex]!.fullPath + ) + }, + [matchIndex, options.from, router, routerLocation], + ) const _options = React.useMemo( () => { @@ -116,7 +136,6 @@ export function useLinkProps< // eslint-disable-next-line react-hooks/exhaustive-deps [ router, - routerLocation, currentSearch, from, options._fromLocation, diff --git a/packages/react-router/src/useActiveLocation.ts b/packages/react-router/src/useActiveLocation.ts deleted file mode 100644 index c7220fdaca..0000000000 --- a/packages/react-router/src/useActiveLocation.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { last } from '@tanstack/router-core' -import { useCallback, useEffect, useState } from 'react' -import { useRouter } from './useRouter' -import { useMatch } from './useMatch' -import { useRouterState } from './useRouterState' -import type { ParsedLocation } from '@tanstack/router-core' - -export type UseActiveLocationResult = { - activeLocation: ParsedLocation - getFromPath: (from?: string) => string - setActiveLocation: (location?: ParsedLocation) => void -} - -export const useActiveLocation = ( - location?: ParsedLocation, -): UseActiveLocationResult => { - const router = useRouter() - const routerLocation = useRouterState({ select: (state) => state.location }) - const [activeLocation, setActiveLocation] = useState( - location ?? routerLocation, - ) - const [customActiveLocation, setCustomActiveLocation] = useState< - ParsedLocation | undefined - >(location) - - useEffect(() => { - setActiveLocation(customActiveLocation ?? routerLocation) - }, [routerLocation, customActiveLocation]) - - const matchIndex = useMatch({ - strict: false, - select: (match) => match.index, - }) - - const getFromPath = useCallback( - (from?: string) => { - const activeLocationMatches = router.matchRoutes(activeLocation, { - _buildLocation: false, - }) - - const activeLocationMatch = last(activeLocationMatches) - - return ( - from ?? - activeLocationMatch?.fullPath ?? - router.state.matches[matchIndex]!.fullPath - ) - }, - [activeLocation, matchIndex, router], - ) - - return { - activeLocation, - getFromPath, - setActiveLocation: setCustomActiveLocation, - } -} diff --git a/packages/react-router/src/useNavigate.tsx b/packages/react-router/src/useNavigate.tsx index c12cffb9c9..a7eea1864a 100644 --- a/packages/react-router/src/useNavigate.tsx +++ b/packages/react-router/src/useNavigate.tsx @@ -1,6 +1,7 @@ import * as React from 'react' +import { last } from '@tanstack/router-core' import { useRouter } from './useRouter' -import { useActiveLocation } from './useActiveLocation' +import { useMatch } from './useMatch' import type { AnyRouter, FromPathOption, @@ -17,11 +18,23 @@ export function useNavigate< }): UseNavigateResult { const router = useRouter() - const { getFromPath, activeLocation } = useActiveLocation() + const matchIndex = useMatch({ + strict: false, + select: (match) => match.index, + }) return React.useCallback( (options: NavigateOptions) => { - const from = getFromPath(options.from ?? _defaultOpts?.from) + const activeLocationMatches = router.matchRoutes(router.latestLocation, { + _buildLocation: false, + }) + + const activeLocationMatch = last(activeLocationMatches) + + const from = options.from ?? + _defaultOpts?.from ?? + activeLocationMatch?.fullPath ?? + router.state.matches[matchIndex]!.fullPath return router.navigate({ ...options, @@ -29,7 +42,7 @@ export function useNavigate< }) }, // eslint-disable-next-line react-hooks/exhaustive-deps - [_defaultOpts?.from, router, getFromPath, activeLocation], + [_defaultOpts?.from, router], ) as UseNavigateResult } diff --git a/packages/solid-router/src/link.tsx b/packages/solid-router/src/link.tsx index 00c0c10997..13b305c46a 100644 --- a/packages/solid-router/src/link.tsx +++ b/packages/solid-router/src/link.tsx @@ -6,16 +6,18 @@ import { deepEqual, exactPathTest, functionalUpdate, + last, preloadWarning, removeTrailingSlash, } from '@tanstack/router-core' import { Dynamic } from 'solid-js/web' +import { createMemo } from 'solid-js' +import { useMatch } from './useMatch' import { useRouterState } from './useRouterState' import { useRouter } from './useRouter' import { useIntersectionObserver } from './utils' -import { useActiveLocation } from './useActiveLocation' import type { AnyRouter, Constrain, @@ -133,9 +135,29 @@ export function useLinkProps< select: (s) => s.location.searchStr, }) - const { getFromPath, activeLocation } = useActiveLocation() + const routerLocation = useRouterState({ + select: (s) => s.location, + }) + + const matchIndex = useMatch({ + strict: false, + select: (match) => match.index, + }) - const from = getFromPath(options.from) + const from = createMemo(() => { + const activeLocationMatches = router.matchRoutes(routerLocation(), { + _buildLocation: false, + }, + ) + + const activeLocationMatch = last(activeLocationMatches) + + return ( + options.from ?? + activeLocationMatch?.fullPath ?? + router.state.matches[matchIndex()]!.fullPath + ) + }) const _options = () => { return { @@ -146,7 +168,6 @@ export function useLinkProps< const next = Solid.createMemo(() => { currentSearch() - activeLocation() return router.buildLocation(_options() as any) }) diff --git a/packages/solid-router/src/useActiveLocation.ts b/packages/solid-router/src/useActiveLocation.ts deleted file mode 100644 index 268af7296d..0000000000 --- a/packages/solid-router/src/useActiveLocation.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { last } from '@tanstack/router-core' -import { createEffect, createMemo, createSignal } from 'solid-js' -import { useMatch } from './useMatch' -import { useRouter } from './useRouter' -import { useRouterState } from './useRouterState' -import type { Accessor } from 'solid-js' -import type { ParsedLocation } from '@tanstack/router-core' - -export type UseLocationResult = { - activeLocation: Accessor - getFromPath: (from?: string) => Accessor - setActiveLocation: (location?: ParsedLocation) => void -} - -export function useActiveLocation( - location?: ParsedLocation, -): UseLocationResult { - const router = useRouter() - // we are not using a variable here for router state location since we need to only calculate that if the location is not passed in. It can result in unnecessary history actions if we do that. - const [activeLocation, setActiveLocation] = createSignal( - location ?? useRouterState({ select: (s) => s.location })(), - ) - const [customActiveLocation, setCustomActiveLocation] = createSignal< - ParsedLocation | undefined - >(location) - - createEffect(() => { - setActiveLocation( - customActiveLocation() ?? useRouterState({ select: (s) => s.location })(), - ) - }) - - const matchIndex = useMatch({ - strict: false, - select: (match) => match.index, - }) - - const getFromPath = (from?: string) => - createMemo(() => { - const activeLocationMatches = router.matchRoutes( - customActiveLocation() ?? activeLocation(), - { - _buildLocation: false, - }, - ) - - const activeLocationMatch = last(activeLocationMatches) - - return ( - from ?? - activeLocationMatch?.fullPath ?? - router.state.matches[matchIndex()]!.fullPath - ) - }) - - return { - activeLocation, - getFromPath, - setActiveLocation: setCustomActiveLocation, - } -} diff --git a/packages/solid-router/src/useNavigate.tsx b/packages/solid-router/src/useNavigate.tsx index 0a7f743753..9e6a1cd41a 100644 --- a/packages/solid-router/src/useNavigate.tsx +++ b/packages/solid-router/src/useNavigate.tsx @@ -1,6 +1,7 @@ import * as Solid from 'solid-js' +import { last } from '@tanstack/router-core' import { useRouter } from './useRouter' -import { useActiveLocation } from './useActiveLocation' +import { useMatch } from './useMatch' import type { AnyRouter, FromPathOption, @@ -17,17 +18,26 @@ export function useNavigate< }): UseNavigateResult { const router = useRouter() - const { getFromPath, setActiveLocation } = useActiveLocation( - router.latestLocation, - ) + const matchIndex = useMatch({ + strict: false, + select: (match) => match.index, + }) return ((options: NavigateOptions) => { - setActiveLocation(router.latestLocation) - const from = getFromPath(options.from ?? _defaultOpts?.from) + const activeLocationMatches = router.matchRoutes(router.latestLocation, { + _buildLocation: false, + }) + + const activeLocationMatch = last(activeLocationMatches) + + const from = options.from ?? + _defaultOpts?.from ?? + activeLocationMatch?.fullPath ?? + router.state.matches[matchIndex()]!.fullPath return router.navigate({ ...options, - from: from(), + from, }) }) as UseNavigateResult } From 3c8b5e9a54244494b90f349d583c239f8975c6ae Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 21:28:59 +0000 Subject: [PATCH 2/8] ci: apply automated fixes --- packages/react-router/src/link.tsx | 25 ++++++++++------------- packages/react-router/src/useNavigate.tsx | 3 ++- packages/solid-router/src/link.tsx | 3 +-- packages/solid-router/src/useNavigate.tsx | 3 ++- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/packages/react-router/src/link.tsx b/packages/react-router/src/link.tsx index 6ce942135f..97ad2722a8 100644 --- a/packages/react-router/src/link.tsx +++ b/packages/react-router/src/link.tsx @@ -112,22 +112,19 @@ export function useLinkProps< }) // subscribe to location here to re-build fromPath if it changes - const from = useMemo( - () => { - const activeLocationMatches = router.matchRoutes(routerLocation, { - _buildLocation: false, - }) + const from = useMemo(() => { + const activeLocationMatches = router.matchRoutes(routerLocation, { + _buildLocation: false, + }) - const activeLocationMatch = last(activeLocationMatches) + const activeLocationMatch = last(activeLocationMatches) - return ( - options.from ?? - activeLocationMatch?.fullPath ?? - router.state.matches[matchIndex]!.fullPath - ) - }, - [matchIndex, options.from, router, routerLocation], - ) + return ( + options.from ?? + activeLocationMatch?.fullPath ?? + router.state.matches[matchIndex]!.fullPath + ) + }, [matchIndex, options.from, router, routerLocation]) const _options = React.useMemo( () => { diff --git a/packages/react-router/src/useNavigate.tsx b/packages/react-router/src/useNavigate.tsx index a7eea1864a..3fa3243659 100644 --- a/packages/react-router/src/useNavigate.tsx +++ b/packages/react-router/src/useNavigate.tsx @@ -31,7 +31,8 @@ export function useNavigate< const activeLocationMatch = last(activeLocationMatches) - const from = options.from ?? + const from = + options.from ?? _defaultOpts?.from ?? activeLocationMatch?.fullPath ?? router.state.matches[matchIndex]!.fullPath diff --git a/packages/solid-router/src/link.tsx b/packages/solid-router/src/link.tsx index 13b305c46a..293aeed3f1 100644 --- a/packages/solid-router/src/link.tsx +++ b/packages/solid-router/src/link.tsx @@ -147,8 +147,7 @@ export function useLinkProps< const from = createMemo(() => { const activeLocationMatches = router.matchRoutes(routerLocation(), { _buildLocation: false, - }, - ) + }) const activeLocationMatch = last(activeLocationMatches) diff --git a/packages/solid-router/src/useNavigate.tsx b/packages/solid-router/src/useNavigate.tsx index 9e6a1cd41a..de7ab1f9ff 100644 --- a/packages/solid-router/src/useNavigate.tsx +++ b/packages/solid-router/src/useNavigate.tsx @@ -30,7 +30,8 @@ export function useNavigate< const activeLocationMatch = last(activeLocationMatches) - const from = options.from ?? + const from = + options.from ?? _defaultOpts?.from ?? activeLocationMatch?.fullPath ?? router.state.matches[matchIndex()]!.fullPath From 24139725c42c672c39bd0276fe827e8dae05d666 Mon Sep 17 00:00:00 2001 From: Nico Lynzaad Date: Fri, 29 Aug 2025 10:07:13 +0200 Subject: [PATCH 3/8] simplify --- packages/react-router/src/link.tsx | 27 +--------------------- packages/react-router/src/useNavigate.tsx | 26 +++------------------ packages/solid-router/src/link.tsx | 28 ++--------------------- packages/solid-router/src/useNavigate.tsx | 23 +++---------------- 4 files changed, 9 insertions(+), 95 deletions(-) diff --git a/packages/react-router/src/link.tsx b/packages/react-router/src/link.tsx index 97ad2722a8..a05cf29f81 100644 --- a/packages/react-router/src/link.tsx +++ b/packages/react-router/src/link.tsx @@ -4,12 +4,9 @@ import { deepEqual, exactPathTest, functionalUpdate, - last, preloadWarning, removeTrailingSlash, } from '@tanstack/router-core' -import { useMemo } from 'react' -import { useMatch } from './useMatch' import { useRouterState } from './useRouterState' import { useRouter } from './useRouter' @@ -101,30 +98,8 @@ export function useLinkProps< structuralSharing: true as any, }) - const routerLocation = useRouterState({ - select: (s) => s.location, - structuralSharing: true as any, - }) - - const matchIndex = useMatch({ - strict: false, - select: (match) => match.index, - }) - // subscribe to location here to re-build fromPath if it changes - const from = useMemo(() => { - const activeLocationMatches = router.matchRoutes(routerLocation, { - _buildLocation: false, - }) - - const activeLocationMatch = last(activeLocationMatches) - - return ( - options.from ?? - activeLocationMatch?.fullPath ?? - router.state.matches[matchIndex]!.fullPath - ) - }, [matchIndex, options.from, router, routerLocation]) + const from = options.from const _options = React.useMemo( () => { diff --git a/packages/react-router/src/useNavigate.tsx b/packages/react-router/src/useNavigate.tsx index 3fa3243659..cf8c857f2e 100644 --- a/packages/react-router/src/useNavigate.tsx +++ b/packages/react-router/src/useNavigate.tsx @@ -1,7 +1,5 @@ import * as React from 'react' -import { last } from '@tanstack/router-core' import { useRouter } from './useRouter' -import { useMatch } from './useMatch' import type { AnyRouter, FromPathOption, @@ -18,32 +16,14 @@ export function useNavigate< }): UseNavigateResult { const router = useRouter() - const matchIndex = useMatch({ - strict: false, - select: (match) => match.index, - }) - return React.useCallback( (options: NavigateOptions) => { - const activeLocationMatches = router.matchRoutes(router.latestLocation, { - _buildLocation: false, - }) - - const activeLocationMatch = last(activeLocationMatches) - - const from = - options.from ?? - _defaultOpts?.from ?? - activeLocationMatch?.fullPath ?? - router.state.matches[matchIndex]!.fullPath - return router.navigate({ ...options, - from, + from: options.from ?? + _defaultOpts?.from, }) - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [_defaultOpts?.from, router], + }, [_defaultOpts?.from, router], ) as UseNavigateResult } diff --git a/packages/solid-router/src/link.tsx b/packages/solid-router/src/link.tsx index 293aeed3f1..3029c6020d 100644 --- a/packages/solid-router/src/link.tsx +++ b/packages/solid-router/src/link.tsx @@ -6,13 +6,10 @@ import { deepEqual, exactPathTest, functionalUpdate, - last, preloadWarning, removeTrailingSlash, } from '@tanstack/router-core' import { Dynamic } from 'solid-js/web' -import { createMemo } from 'solid-js' -import { useMatch } from './useMatch' import { useRouterState } from './useRouterState' import { useRouter } from './useRouter' @@ -135,33 +132,12 @@ export function useLinkProps< select: (s) => s.location.searchStr, }) - const routerLocation = useRouterState({ - select: (s) => s.location, - }) - - const matchIndex = useMatch({ - strict: false, - select: (match) => match.index, - }) - - const from = createMemo(() => { - const activeLocationMatches = router.matchRoutes(routerLocation(), { - _buildLocation: false, - }) - - const activeLocationMatch = last(activeLocationMatches) - - return ( - options.from ?? - activeLocationMatch?.fullPath ?? - router.state.matches[matchIndex()]!.fullPath - ) - }) + const from = options.from const _options = () => { return { ...options, - from: from(), + from, } } diff --git a/packages/solid-router/src/useNavigate.tsx b/packages/solid-router/src/useNavigate.tsx index de7ab1f9ff..0ca56fca47 100644 --- a/packages/solid-router/src/useNavigate.tsx +++ b/packages/solid-router/src/useNavigate.tsx @@ -1,7 +1,6 @@ import * as Solid from 'solid-js' import { last } from '@tanstack/router-core' import { useRouter } from './useRouter' -import { useMatch } from './useMatch' import type { AnyRouter, FromPathOption, @@ -18,27 +17,11 @@ export function useNavigate< }): UseNavigateResult { const router = useRouter() - const matchIndex = useMatch({ - strict: false, - select: (match) => match.index, - }) - return ((options: NavigateOptions) => { - const activeLocationMatches = router.matchRoutes(router.latestLocation, { - _buildLocation: false, - }) - - const activeLocationMatch = last(activeLocationMatches) - - const from = - options.from ?? - _defaultOpts?.from ?? - activeLocationMatch?.fullPath ?? - router.state.matches[matchIndex()]!.fullPath - - return router.navigate({ + return router.navigate({ ...options, - from, + from: options.from ?? + _defaultOpts?.from, }) }) as UseNavigateResult } From 9f6cb3fe25839787cd147874e24aac34e3bfb0f6 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 08:08:13 +0000 Subject: [PATCH 4/8] ci: apply automated fixes --- packages/react-router/src/useNavigate.tsx | 6 +++--- packages/solid-router/src/useNavigate.tsx | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/react-router/src/useNavigate.tsx b/packages/react-router/src/useNavigate.tsx index cf8c857f2e..2671aa7e4e 100644 --- a/packages/react-router/src/useNavigate.tsx +++ b/packages/react-router/src/useNavigate.tsx @@ -20,10 +20,10 @@ export function useNavigate< (options: NavigateOptions) => { return router.navigate({ ...options, - from: options.from ?? - _defaultOpts?.from, + from: options.from ?? _defaultOpts?.from, }) - }, [_defaultOpts?.from, router], + }, + [_defaultOpts?.from, router], ) as UseNavigateResult } diff --git a/packages/solid-router/src/useNavigate.tsx b/packages/solid-router/src/useNavigate.tsx index 0ca56fca47..98f791b053 100644 --- a/packages/solid-router/src/useNavigate.tsx +++ b/packages/solid-router/src/useNavigate.tsx @@ -18,10 +18,9 @@ export function useNavigate< const router = useRouter() return ((options: NavigateOptions) => { - return router.navigate({ + return router.navigate({ ...options, - from: options.from ?? - _defaultOpts?.from, + from: options.from ?? _defaultOpts?.from, }) }) as UseNavigateResult } From bb24db33a9b71bafee3e9dcf34d67ea6ff5623c8 Mon Sep 17 00:00:00 2001 From: Nico Lynzaad Date: Fri, 29 Aug 2025 10:13:38 +0200 Subject: [PATCH 5/8] cleanup --- packages/react-router/src/link.tsx | 1 - packages/solid-router/src/useNavigate.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/react-router/src/link.tsx b/packages/react-router/src/link.tsx index a05cf29f81..b64b47f129 100644 --- a/packages/react-router/src/link.tsx +++ b/packages/react-router/src/link.tsx @@ -98,7 +98,6 @@ export function useLinkProps< structuralSharing: true as any, }) - // subscribe to location here to re-build fromPath if it changes const from = options.from const _options = React.useMemo( diff --git a/packages/solid-router/src/useNavigate.tsx b/packages/solid-router/src/useNavigate.tsx index 0ca56fca47..804c789203 100644 --- a/packages/solid-router/src/useNavigate.tsx +++ b/packages/solid-router/src/useNavigate.tsx @@ -1,5 +1,4 @@ import * as Solid from 'solid-js' -import { last } from '@tanstack/router-core' import { useRouter } from './useRouter' import type { AnyRouter, From fee00262e6c6e9477d36213897f0791dacd92fce Mon Sep 17 00:00:00 2001 From: Nico Lynzaad Date: Sun, 31 Aug 2025 13:22:59 +0200 Subject: [PATCH 6/8] e2e tests for relative routing --- .../basic-file-based/src/routeTree.gen.ts | 396 ++++++++++++++++++ .../basic-file-based/src/routes/__root.tsx | 8 + .../src/routes/relative/index.tsx | 22 + .../relative/link/nested/deep/index.tsx | 13 + .../src/routes/relative/link/nested/index.tsx | 13 + .../routes/relative/link/path/$path/index.tsx | 31 ++ .../src/routes/relative/link/path/index.tsx | 18 + .../routes/relative/link/relative-link-a.tsx | 13 + .../routes/relative/link/relative-link-b.tsx | 13 + .../src/routes/relative/link/route.tsx | 103 +++++ .../relative/link/with-search/index.tsx | 28 ++ .../useNavigate/nested/deep/index.tsx | 13 + .../relative/useNavigate/nested/index.tsx | 13 + .../relative/useNavigate/path/$path/index.tsx | 40 ++ .../relative/useNavigate/path/index.tsx | 18 + .../useNavigate/relative-useNavigate-a.tsx | 15 + .../useNavigate/relative-useNavigate-b.tsx | 13 + .../src/routes/relative/useNavigate/route.tsx | 134 ++++++ .../useNavigate/with-search/index.tsx | 34 ++ .../basic-file-based/tests/relative.spec.ts | 273 ++++++++++++ 20 files changed, 1211 insertions(+) create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/nested/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/path/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/route.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/link/with-search/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/route.tsx create mode 100644 e2e/react-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx create mode 100644 e2e/react-router/basic-file-based/tests/relative.spec.ts diff --git a/e2e/react-router/basic-file-based/src/routeTree.gen.ts b/e2e/react-router/basic-file-based/src/routeTree.gen.ts index e44ac41896..62af050d6e 100644 --- a/e2e/react-router/basic-file-based/src/routeTree.gen.ts +++ b/e2e/react-router/basic-file-based/src/routeTree.gen.ts @@ -23,6 +23,7 @@ import { Route as LayoutRouteImport } from './routes/_layout' import { Route as SearchParamsRouteRouteImport } from './routes/search-params/route' import { Route as IndexRouteImport } from './routes/index' import { Route as SearchParamsIndexRouteImport } from './routes/search-params/index' +import { Route as RelativeIndexRouteImport } from './routes/relative/index' import { Route as RedirectIndexRouteImport } from './routes/redirect/index' import { Route as PostsIndexRouteImport } from './routes/posts.index' import { Route as ParamsPsIndexRouteImport } from './routes/params-ps/index' @@ -35,9 +36,15 @@ import { Route as groupLazyinsideRouteImport } from './routes/(group)/lazyinside import { Route as groupInsideRouteImport } from './routes/(group)/inside' import { Route as groupLayoutRouteImport } from './routes/(group)/_layout' import { Route as anotherGroupOnlyrouteinsideRouteImport } from './routes/(another-group)/onlyrouteinside' +import { Route as RelativeUseNavigateRouteRouteImport } from './routes/relative/useNavigate/route' +import { Route as RelativeLinkRouteRouteImport } from './routes/relative/link/route' import { Route as RedirectTargetIndexRouteImport } from './routes/redirect/$target/index' import { Route as ParamsPsWildcardIndexRouteImport } from './routes/params-ps/wildcard/index' import { Route as ParamsPsNamedIndexRouteImport } from './routes/params-ps/named/index' +import { Route as RelativeUseNavigateRelativeUseNavigateBRouteImport } from './routes/relative/useNavigate/relative-useNavigate-b' +import { Route as RelativeUseNavigateRelativeUseNavigateARouteImport } from './routes/relative/useNavigate/relative-useNavigate-a' +import { Route as RelativeLinkRelativeLinkBRouteImport } from './routes/relative/link/relative-link-b' +import { Route as RelativeLinkRelativeLinkARouteImport } from './routes/relative/link/relative-link-a' import { Route as RedirectPreloadThirdRouteImport } from './routes/redirect/preload/third' import { Route as RedirectPreloadSecondRouteImport } from './routes/redirect/preload/second' import { Route as RedirectPreloadFirstRouteImport } from './routes/redirect/preload/first' @@ -55,6 +62,16 @@ import { Route as LayoutLayout2LayoutBRouteImport } from './routes/_layout/_layo import { Route as LayoutLayout2LayoutARouteImport } from './routes/_layout/_layout-2/layout-a' import { Route as groupSubfolderInsideRouteImport } from './routes/(group)/subfolder/inside' import { Route as groupLayoutInsidelayoutRouteImport } from './routes/(group)/_layout.insidelayout' +import { Route as RelativeUseNavigateWithSearchIndexRouteImport } from './routes/relative/useNavigate/with-search/index' +import { Route as RelativeUseNavigatePathIndexRouteImport } from './routes/relative/useNavigate/path/index' +import { Route as RelativeUseNavigateNestedIndexRouteImport } from './routes/relative/useNavigate/nested/index' +import { Route as RelativeLinkWithSearchIndexRouteImport } from './routes/relative/link/with-search/index' +import { Route as RelativeLinkPathIndexRouteImport } from './routes/relative/link/path/index' +import { Route as RelativeLinkNestedIndexRouteImport } from './routes/relative/link/nested/index' +import { Route as RelativeUseNavigatePathPathIndexRouteImport } from './routes/relative/useNavigate/path/$path/index' +import { Route as RelativeUseNavigateNestedDeepIndexRouteImport } from './routes/relative/useNavigate/nested/deep/index' +import { Route as RelativeLinkPathPathIndexRouteImport } from './routes/relative/link/path/$path/index' +import { Route as RelativeLinkNestedDeepIndexRouteImport } from './routes/relative/link/nested/deep/index' const groupRouteImport = createFileRoute('/(group)')() @@ -122,6 +139,11 @@ const SearchParamsIndexRoute = SearchParamsIndexRouteImport.update({ path: '/', getParentRoute: () => SearchParamsRouteRoute, } as any) +const RelativeIndexRoute = RelativeIndexRouteImport.update({ + id: '/relative/', + path: '/relative/', + getParentRoute: () => rootRouteImport, +} as any) const RedirectIndexRoute = RedirectIndexRouteImport.update({ id: '/redirect/', path: '/redirect/', @@ -184,6 +206,17 @@ const anotherGroupOnlyrouteinsideRoute = path: '/onlyrouteinside', getParentRoute: () => rootRouteImport, } as any) +const RelativeUseNavigateRouteRoute = + RelativeUseNavigateRouteRouteImport.update({ + id: '/relative/useNavigate', + path: '/relative/useNavigate', + getParentRoute: () => rootRouteImport, + } as any) +const RelativeLinkRouteRoute = RelativeLinkRouteRouteImport.update({ + id: '/relative/link', + path: '/relative/link', + getParentRoute: () => rootRouteImport, +} as any) const RedirectTargetIndexRoute = RedirectTargetIndexRouteImport.update({ id: '/', path: '/', @@ -199,6 +232,30 @@ const ParamsPsNamedIndexRoute = ParamsPsNamedIndexRouteImport.update({ path: '/params-ps/named/', getParentRoute: () => rootRouteImport, } as any) +const RelativeUseNavigateRelativeUseNavigateBRoute = + RelativeUseNavigateRelativeUseNavigateBRouteImport.update({ + id: '/relative-useNavigate-b', + path: '/relative-useNavigate-b', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigateRelativeUseNavigateARoute = + RelativeUseNavigateRelativeUseNavigateARouteImport.update({ + id: '/relative-useNavigate-a', + path: '/relative-useNavigate-a', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeLinkRelativeLinkBRoute = + RelativeLinkRelativeLinkBRouteImport.update({ + id: '/relative-link-b', + path: '/relative-link-b', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) +const RelativeLinkRelativeLinkARoute = + RelativeLinkRelativeLinkARouteImport.update({ + id: '/relative-link-a', + path: '/relative-link-a', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) const RedirectPreloadThirdRoute = RedirectPreloadThirdRouteImport.update({ id: '/redirect/preload/third', path: '/redirect/preload/third', @@ -289,6 +346,64 @@ const groupLayoutInsidelayoutRoute = groupLayoutInsidelayoutRouteImport.update({ path: '/insidelayout', getParentRoute: () => groupLayoutRoute, } as any) +const RelativeUseNavigateWithSearchIndexRoute = + RelativeUseNavigateWithSearchIndexRouteImport.update({ + id: '/with-search/', + path: '/with-search/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigatePathIndexRoute = + RelativeUseNavigatePathIndexRouteImport.update({ + id: '/path/', + path: '/path/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigateNestedIndexRoute = + RelativeUseNavigateNestedIndexRouteImport.update({ + id: '/nested/', + path: '/nested/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeLinkWithSearchIndexRoute = + RelativeLinkWithSearchIndexRouteImport.update({ + id: '/with-search/', + path: '/with-search/', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) +const RelativeLinkPathIndexRoute = RelativeLinkPathIndexRouteImport.update({ + id: '/path/', + path: '/path/', + getParentRoute: () => RelativeLinkRouteRoute, +} as any) +const RelativeLinkNestedIndexRoute = RelativeLinkNestedIndexRouteImport.update({ + id: '/nested/', + path: '/nested/', + getParentRoute: () => RelativeLinkRouteRoute, +} as any) +const RelativeUseNavigatePathPathIndexRoute = + RelativeUseNavigatePathPathIndexRouteImport.update({ + id: '/path/$path/', + path: '/path/$path/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigateNestedDeepIndexRoute = + RelativeUseNavigateNestedDeepIndexRouteImport.update({ + id: '/nested/deep/', + path: '/nested/deep/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeLinkPathPathIndexRoute = + RelativeLinkPathPathIndexRouteImport.update({ + id: '/path/$path/', + path: '/path/$path/', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) +const RelativeLinkNestedDeepIndexRoute = + RelativeLinkNestedDeepIndexRouteImport.update({ + id: '/nested/deep/', + path: '/nested/deep/', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) export interface FileRoutesByFullPath { '/': typeof groupLayoutRouteWithChildren @@ -301,6 +416,8 @@ export interface FileRoutesByFullPath { '/posts': typeof PostsRouteWithChildren '/remountDeps': typeof RemountDepsRoute '/대한민국': typeof Char45824Char54620Char48124Char44397Route + '/relative/link': typeof RelativeLinkRouteRouteWithChildren + '/relative/useNavigate': typeof RelativeUseNavigateRouteRouteWithChildren '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute '/inside': typeof groupInsideRoute '/lazyinside': typeof groupLazyinsideRoute @@ -311,6 +428,7 @@ export interface FileRoutesByFullPath { '/params-ps': typeof ParamsPsIndexRoute '/posts/': typeof PostsIndexRoute '/redirect': typeof RedirectIndexRoute + '/relative': typeof RelativeIndexRoute '/search-params/': typeof SearchParamsIndexRoute '/insidelayout': typeof groupLayoutInsidelayoutRoute '/subfolder/inside': typeof groupSubfolderInsideRoute @@ -329,9 +447,23 @@ export interface FileRoutesByFullPath { '/redirect/preload/first': typeof RedirectPreloadFirstRoute '/redirect/preload/second': typeof RedirectPreloadSecondRoute '/redirect/preload/third': typeof RedirectPreloadThirdRoute + '/relative/link/relative-link-a': typeof RelativeLinkRelativeLinkARoute + '/relative/link/relative-link-b': typeof RelativeLinkRelativeLinkBRoute + '/relative/useNavigate/relative-useNavigate-a': typeof RelativeUseNavigateRelativeUseNavigateARoute + '/relative/useNavigate/relative-useNavigate-b': typeof RelativeUseNavigateRelativeUseNavigateBRoute '/params-ps/named': typeof ParamsPsNamedIndexRoute '/params-ps/wildcard': typeof ParamsPsWildcardIndexRoute '/redirect/$target/': typeof RedirectTargetIndexRoute + '/relative/link/nested': typeof RelativeLinkNestedIndexRoute + '/relative/link/path': typeof RelativeLinkPathIndexRoute + '/relative/link/with-search': typeof RelativeLinkWithSearchIndexRoute + '/relative/useNavigate/nested': typeof RelativeUseNavigateNestedIndexRoute + '/relative/useNavigate/path': typeof RelativeUseNavigatePathIndexRoute + '/relative/useNavigate/with-search': typeof RelativeUseNavigateWithSearchIndexRoute + '/relative/link/nested/deep': typeof RelativeLinkNestedDeepIndexRoute + '/relative/link/path/$path': typeof RelativeLinkPathPathIndexRoute + '/relative/useNavigate/nested/deep': typeof RelativeUseNavigateNestedDeepIndexRoute + '/relative/useNavigate/path/$path': typeof RelativeUseNavigatePathPathIndexRoute } export interface FileRoutesByTo { '/': typeof groupLayoutRouteWithChildren @@ -342,6 +474,8 @@ export interface FileRoutesByTo { '/notRemountDeps': typeof NotRemountDepsRoute '/remountDeps': typeof RemountDepsRoute '/대한민국': typeof Char45824Char54620Char48124Char44397Route + '/relative/link': typeof RelativeLinkRouteRouteWithChildren + '/relative/useNavigate': typeof RelativeUseNavigateRouteRouteWithChildren '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute '/inside': typeof groupInsideRoute '/lazyinside': typeof groupLazyinsideRoute @@ -351,6 +485,7 @@ export interface FileRoutesByTo { '/params-ps': typeof ParamsPsIndexRoute '/posts': typeof PostsIndexRoute '/redirect': typeof RedirectIndexRoute + '/relative': typeof RelativeIndexRoute '/search-params': typeof SearchParamsIndexRoute '/insidelayout': typeof groupLayoutInsidelayoutRoute '/subfolder/inside': typeof groupSubfolderInsideRoute @@ -369,9 +504,23 @@ export interface FileRoutesByTo { '/redirect/preload/first': typeof RedirectPreloadFirstRoute '/redirect/preload/second': typeof RedirectPreloadSecondRoute '/redirect/preload/third': typeof RedirectPreloadThirdRoute + '/relative/link/relative-link-a': typeof RelativeLinkRelativeLinkARoute + '/relative/link/relative-link-b': typeof RelativeLinkRelativeLinkBRoute + '/relative/useNavigate/relative-useNavigate-a': typeof RelativeUseNavigateRelativeUseNavigateARoute + '/relative/useNavigate/relative-useNavigate-b': typeof RelativeUseNavigateRelativeUseNavigateBRoute '/params-ps/named': typeof ParamsPsNamedIndexRoute '/params-ps/wildcard': typeof ParamsPsWildcardIndexRoute '/redirect/$target': typeof RedirectTargetIndexRoute + '/relative/link/nested': typeof RelativeLinkNestedIndexRoute + '/relative/link/path': typeof RelativeLinkPathIndexRoute + '/relative/link/with-search': typeof RelativeLinkWithSearchIndexRoute + '/relative/useNavigate/nested': typeof RelativeUseNavigateNestedIndexRoute + '/relative/useNavigate/path': typeof RelativeUseNavigatePathIndexRoute + '/relative/useNavigate/with-search': typeof RelativeUseNavigateWithSearchIndexRoute + '/relative/link/nested/deep': typeof RelativeLinkNestedDeepIndexRoute + '/relative/link/path/$path': typeof RelativeLinkPathPathIndexRoute + '/relative/useNavigate/nested/deep': typeof RelativeUseNavigateNestedDeepIndexRoute + '/relative/useNavigate/path/$path': typeof RelativeUseNavigatePathPathIndexRoute } export interface FileRoutesById { __root__: typeof rootRouteImport @@ -386,6 +535,8 @@ export interface FileRoutesById { '/posts': typeof PostsRouteWithChildren '/remountDeps': typeof RemountDepsRoute '/대한민국': typeof Char45824Char54620Char48124Char44397Route + '/relative/link': typeof RelativeLinkRouteRouteWithChildren + '/relative/useNavigate': typeof RelativeUseNavigateRouteRouteWithChildren '/(another-group)/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute '/(group)': typeof groupRouteWithChildren '/(group)/_layout': typeof groupLayoutRouteWithChildren @@ -399,6 +550,7 @@ export interface FileRoutesById { '/params-ps/': typeof ParamsPsIndexRoute '/posts/': typeof PostsIndexRoute '/redirect/': typeof RedirectIndexRoute + '/relative/': typeof RelativeIndexRoute '/search-params/': typeof SearchParamsIndexRoute '/(group)/_layout/insidelayout': typeof groupLayoutInsidelayoutRoute '/(group)/subfolder/inside': typeof groupSubfolderInsideRoute @@ -417,9 +569,23 @@ export interface FileRoutesById { '/redirect/preload/first': typeof RedirectPreloadFirstRoute '/redirect/preload/second': typeof RedirectPreloadSecondRoute '/redirect/preload/third': typeof RedirectPreloadThirdRoute + '/relative/link/relative-link-a': typeof RelativeLinkRelativeLinkARoute + '/relative/link/relative-link-b': typeof RelativeLinkRelativeLinkBRoute + '/relative/useNavigate/relative-useNavigate-a': typeof RelativeUseNavigateRelativeUseNavigateARoute + '/relative/useNavigate/relative-useNavigate-b': typeof RelativeUseNavigateRelativeUseNavigateBRoute '/params-ps/named/': typeof ParamsPsNamedIndexRoute '/params-ps/wildcard/': typeof ParamsPsWildcardIndexRoute '/redirect/$target/': typeof RedirectTargetIndexRoute + '/relative/link/nested/': typeof RelativeLinkNestedIndexRoute + '/relative/link/path/': typeof RelativeLinkPathIndexRoute + '/relative/link/with-search/': typeof RelativeLinkWithSearchIndexRoute + '/relative/useNavigate/nested/': typeof RelativeUseNavigateNestedIndexRoute + '/relative/useNavigate/path/': typeof RelativeUseNavigatePathIndexRoute + '/relative/useNavigate/with-search/': typeof RelativeUseNavigateWithSearchIndexRoute + '/relative/link/nested/deep/': typeof RelativeLinkNestedDeepIndexRoute + '/relative/link/path/$path/': typeof RelativeLinkPathPathIndexRoute + '/relative/useNavigate/nested/deep/': typeof RelativeUseNavigateNestedDeepIndexRoute + '/relative/useNavigate/path/$path/': typeof RelativeUseNavigatePathPathIndexRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath @@ -434,6 +600,8 @@ export interface FileRouteTypes { | '/posts' | '/remountDeps' | '/대한민국' + | '/relative/link' + | '/relative/useNavigate' | '/onlyrouteinside' | '/inside' | '/lazyinside' @@ -444,6 +612,7 @@ export interface FileRouteTypes { | '/params-ps' | '/posts/' | '/redirect' + | '/relative' | '/search-params/' | '/insidelayout' | '/subfolder/inside' @@ -462,9 +631,23 @@ export interface FileRouteTypes { | '/redirect/preload/first' | '/redirect/preload/second' | '/redirect/preload/third' + | '/relative/link/relative-link-a' + | '/relative/link/relative-link-b' + | '/relative/useNavigate/relative-useNavigate-a' + | '/relative/useNavigate/relative-useNavigate-b' | '/params-ps/named' | '/params-ps/wildcard' | '/redirect/$target/' + | '/relative/link/nested' + | '/relative/link/path' + | '/relative/link/with-search' + | '/relative/useNavigate/nested' + | '/relative/useNavigate/path' + | '/relative/useNavigate/with-search' + | '/relative/link/nested/deep' + | '/relative/link/path/$path' + | '/relative/useNavigate/nested/deep' + | '/relative/useNavigate/path/$path' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -475,6 +658,8 @@ export interface FileRouteTypes { | '/notRemountDeps' | '/remountDeps' | '/대한민국' + | '/relative/link' + | '/relative/useNavigate' | '/onlyrouteinside' | '/inside' | '/lazyinside' @@ -484,6 +669,7 @@ export interface FileRouteTypes { | '/params-ps' | '/posts' | '/redirect' + | '/relative' | '/search-params' | '/insidelayout' | '/subfolder/inside' @@ -502,9 +688,23 @@ export interface FileRouteTypes { | '/redirect/preload/first' | '/redirect/preload/second' | '/redirect/preload/third' + | '/relative/link/relative-link-a' + | '/relative/link/relative-link-b' + | '/relative/useNavigate/relative-useNavigate-a' + | '/relative/useNavigate/relative-useNavigate-b' | '/params-ps/named' | '/params-ps/wildcard' | '/redirect/$target' + | '/relative/link/nested' + | '/relative/link/path' + | '/relative/link/with-search' + | '/relative/useNavigate/nested' + | '/relative/useNavigate/path' + | '/relative/useNavigate/with-search' + | '/relative/link/nested/deep' + | '/relative/link/path/$path' + | '/relative/useNavigate/nested/deep' + | '/relative/useNavigate/path/$path' id: | '__root__' | '/' @@ -518,6 +718,8 @@ export interface FileRouteTypes { | '/posts' | '/remountDeps' | '/대한민국' + | '/relative/link' + | '/relative/useNavigate' | '/(another-group)/onlyrouteinside' | '/(group)' | '/(group)/_layout' @@ -531,6 +733,7 @@ export interface FileRouteTypes { | '/params-ps/' | '/posts/' | '/redirect/' + | '/relative/' | '/search-params/' | '/(group)/_layout/insidelayout' | '/(group)/subfolder/inside' @@ -549,9 +752,23 @@ export interface FileRouteTypes { | '/redirect/preload/first' | '/redirect/preload/second' | '/redirect/preload/third' + | '/relative/link/relative-link-a' + | '/relative/link/relative-link-b' + | '/relative/useNavigate/relative-useNavigate-a' + | '/relative/useNavigate/relative-useNavigate-b' | '/params-ps/named/' | '/params-ps/wildcard/' | '/redirect/$target/' + | '/relative/link/nested/' + | '/relative/link/path/' + | '/relative/link/with-search/' + | '/relative/useNavigate/nested/' + | '/relative/useNavigate/path/' + | '/relative/useNavigate/with-search/' + | '/relative/link/nested/deep/' + | '/relative/link/path/$path/' + | '/relative/useNavigate/nested/deep/' + | '/relative/useNavigate/path/$path/' fileRoutesById: FileRoutesById } export interface RootRouteChildren { @@ -566,12 +783,15 @@ export interface RootRouteChildren { PostsRoute: typeof PostsRouteWithChildren RemountDepsRoute: typeof RemountDepsRoute Char45824Char54620Char48124Char44397Route: typeof Char45824Char54620Char48124Char44397Route + RelativeLinkRouteRoute: typeof RelativeLinkRouteRouteWithChildren + RelativeUseNavigateRouteRoute: typeof RelativeUseNavigateRouteRouteWithChildren anotherGroupOnlyrouteinsideRoute: typeof anotherGroupOnlyrouteinsideRoute groupRoute: typeof groupRouteWithChildren RedirectTargetRoute: typeof RedirectTargetRouteWithChildren StructuralSharingEnabledRoute: typeof StructuralSharingEnabledRoute ParamsPsIndexRoute: typeof ParamsPsIndexRoute RedirectIndexRoute: typeof RedirectIndexRoute + RelativeIndexRoute: typeof RelativeIndexRoute ParamsPsNamedFooRoute: typeof ParamsPsNamedFooRoute ParamsPsNamedPrefixChar123fooChar125Route: typeof ParamsPsNamedPrefixChar123fooChar125Route ParamsPsNamedChar123fooChar125suffixRoute: typeof ParamsPsNamedChar123fooChar125suffixRoute @@ -680,6 +900,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SearchParamsIndexRouteImport parentRoute: typeof SearchParamsRouteRoute } + '/relative/': { + id: '/relative/' + path: '/relative' + fullPath: '/relative' + preLoaderRoute: typeof RelativeIndexRouteImport + parentRoute: typeof rootRouteImport + } '/redirect/': { id: '/redirect/' path: '/redirect' @@ -764,6 +991,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof anotherGroupOnlyrouteinsideRouteImport parentRoute: typeof rootRouteImport } + '/relative/useNavigate': { + id: '/relative/useNavigate' + path: '/relative/useNavigate' + fullPath: '/relative/useNavigate' + preLoaderRoute: typeof RelativeUseNavigateRouteRouteImport + parentRoute: typeof rootRouteImport + } + '/relative/link': { + id: '/relative/link' + path: '/relative/link' + fullPath: '/relative/link' + preLoaderRoute: typeof RelativeLinkRouteRouteImport + parentRoute: typeof rootRouteImport + } '/redirect/$target/': { id: '/redirect/$target/' path: '/' @@ -785,6 +1026,34 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ParamsPsNamedIndexRouteImport parentRoute: typeof rootRouteImport } + '/relative/useNavigate/relative-useNavigate-b': { + id: '/relative/useNavigate/relative-useNavigate-b' + path: '/relative-useNavigate-b' + fullPath: '/relative/useNavigate/relative-useNavigate-b' + preLoaderRoute: typeof RelativeUseNavigateRelativeUseNavigateBRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/relative-useNavigate-a': { + id: '/relative/useNavigate/relative-useNavigate-a' + path: '/relative-useNavigate-a' + fullPath: '/relative/useNavigate/relative-useNavigate-a' + preLoaderRoute: typeof RelativeUseNavigateRelativeUseNavigateARouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/link/relative-link-b': { + id: '/relative/link/relative-link-b' + path: '/relative-link-b' + fullPath: '/relative/link/relative-link-b' + preLoaderRoute: typeof RelativeLinkRelativeLinkBRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/relative-link-a': { + id: '/relative/link/relative-link-a' + path: '/relative-link-a' + fullPath: '/relative/link/relative-link-a' + preLoaderRoute: typeof RelativeLinkRelativeLinkARouteImport + parentRoute: typeof RelativeLinkRouteRoute + } '/redirect/preload/third': { id: '/redirect/preload/third' path: '/redirect/preload/third' @@ -904,6 +1173,76 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof groupLayoutInsidelayoutRouteImport parentRoute: typeof groupLayoutRoute } + '/relative/useNavigate/with-search/': { + id: '/relative/useNavigate/with-search/' + path: '/with-search' + fullPath: '/relative/useNavigate/with-search' + preLoaderRoute: typeof RelativeUseNavigateWithSearchIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/path/': { + id: '/relative/useNavigate/path/' + path: '/path' + fullPath: '/relative/useNavigate/path' + preLoaderRoute: typeof RelativeUseNavigatePathIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/nested/': { + id: '/relative/useNavigate/nested/' + path: '/nested' + fullPath: '/relative/useNavigate/nested' + preLoaderRoute: typeof RelativeUseNavigateNestedIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/link/with-search/': { + id: '/relative/link/with-search/' + path: '/with-search' + fullPath: '/relative/link/with-search' + preLoaderRoute: typeof RelativeLinkWithSearchIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/path/': { + id: '/relative/link/path/' + path: '/path' + fullPath: '/relative/link/path' + preLoaderRoute: typeof RelativeLinkPathIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/nested/': { + id: '/relative/link/nested/' + path: '/nested' + fullPath: '/relative/link/nested' + preLoaderRoute: typeof RelativeLinkNestedIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/useNavigate/path/$path/': { + id: '/relative/useNavigate/path/$path/' + path: '/path/$path' + fullPath: '/relative/useNavigate/path/$path' + preLoaderRoute: typeof RelativeUseNavigatePathPathIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/nested/deep/': { + id: '/relative/useNavigate/nested/deep/' + path: '/nested/deep' + fullPath: '/relative/useNavigate/nested/deep' + preLoaderRoute: typeof RelativeUseNavigateNestedDeepIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/link/path/$path/': { + id: '/relative/link/path/$path/' + path: '/path/$path' + fullPath: '/relative/link/path/$path' + preLoaderRoute: typeof RelativeLinkPathPathIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/nested/deep/': { + id: '/relative/link/nested/deep/' + path: '/nested/deep' + fullPath: '/relative/link/nested/deep' + preLoaderRoute: typeof RelativeLinkNestedDeepIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } } } @@ -957,6 +1296,60 @@ const PostsRouteChildren: PostsRouteChildren = { const PostsRouteWithChildren = PostsRoute._addFileChildren(PostsRouteChildren) +interface RelativeLinkRouteRouteChildren { + RelativeLinkRelativeLinkARoute: typeof RelativeLinkRelativeLinkARoute + RelativeLinkRelativeLinkBRoute: typeof RelativeLinkRelativeLinkBRoute + RelativeLinkNestedIndexRoute: typeof RelativeLinkNestedIndexRoute + RelativeLinkPathIndexRoute: typeof RelativeLinkPathIndexRoute + RelativeLinkWithSearchIndexRoute: typeof RelativeLinkWithSearchIndexRoute + RelativeLinkNestedDeepIndexRoute: typeof RelativeLinkNestedDeepIndexRoute + RelativeLinkPathPathIndexRoute: typeof RelativeLinkPathPathIndexRoute +} + +const RelativeLinkRouteRouteChildren: RelativeLinkRouteRouteChildren = { + RelativeLinkRelativeLinkARoute: RelativeLinkRelativeLinkARoute, + RelativeLinkRelativeLinkBRoute: RelativeLinkRelativeLinkBRoute, + RelativeLinkNestedIndexRoute: RelativeLinkNestedIndexRoute, + RelativeLinkPathIndexRoute: RelativeLinkPathIndexRoute, + RelativeLinkWithSearchIndexRoute: RelativeLinkWithSearchIndexRoute, + RelativeLinkNestedDeepIndexRoute: RelativeLinkNestedDeepIndexRoute, + RelativeLinkPathPathIndexRoute: RelativeLinkPathPathIndexRoute, +} + +const RelativeLinkRouteRouteWithChildren = + RelativeLinkRouteRoute._addFileChildren(RelativeLinkRouteRouteChildren) + +interface RelativeUseNavigateRouteRouteChildren { + RelativeUseNavigateRelativeUseNavigateARoute: typeof RelativeUseNavigateRelativeUseNavigateARoute + RelativeUseNavigateRelativeUseNavigateBRoute: typeof RelativeUseNavigateRelativeUseNavigateBRoute + RelativeUseNavigateNestedIndexRoute: typeof RelativeUseNavigateNestedIndexRoute + RelativeUseNavigatePathIndexRoute: typeof RelativeUseNavigatePathIndexRoute + RelativeUseNavigateWithSearchIndexRoute: typeof RelativeUseNavigateWithSearchIndexRoute + RelativeUseNavigateNestedDeepIndexRoute: typeof RelativeUseNavigateNestedDeepIndexRoute + RelativeUseNavigatePathPathIndexRoute: typeof RelativeUseNavigatePathPathIndexRoute +} + +const RelativeUseNavigateRouteRouteChildren: RelativeUseNavigateRouteRouteChildren = + { + RelativeUseNavigateRelativeUseNavigateARoute: + RelativeUseNavigateRelativeUseNavigateARoute, + RelativeUseNavigateRelativeUseNavigateBRoute: + RelativeUseNavigateRelativeUseNavigateBRoute, + RelativeUseNavigateNestedIndexRoute: RelativeUseNavigateNestedIndexRoute, + RelativeUseNavigatePathIndexRoute: RelativeUseNavigatePathIndexRoute, + RelativeUseNavigateWithSearchIndexRoute: + RelativeUseNavigateWithSearchIndexRoute, + RelativeUseNavigateNestedDeepIndexRoute: + RelativeUseNavigateNestedDeepIndexRoute, + RelativeUseNavigatePathPathIndexRoute: + RelativeUseNavigatePathPathIndexRoute, + } + +const RelativeUseNavigateRouteRouteWithChildren = + RelativeUseNavigateRouteRoute._addFileChildren( + RelativeUseNavigateRouteRouteChildren, + ) + interface groupLayoutRouteChildren { groupLayoutInsidelayoutRoute: typeof groupLayoutInsidelayoutRoute } @@ -1014,12 +1407,15 @@ const rootRouteChildren: RootRouteChildren = { RemountDepsRoute: RemountDepsRoute, Char45824Char54620Char48124Char44397Route: Char45824Char54620Char48124Char44397Route, + RelativeLinkRouteRoute: RelativeLinkRouteRouteWithChildren, + RelativeUseNavigateRouteRoute: RelativeUseNavigateRouteRouteWithChildren, anotherGroupOnlyrouteinsideRoute: anotherGroupOnlyrouteinsideRoute, groupRoute: groupRouteWithChildren, RedirectTargetRoute: RedirectTargetRouteWithChildren, StructuralSharingEnabledRoute: StructuralSharingEnabledRoute, ParamsPsIndexRoute: ParamsPsIndexRoute, RedirectIndexRoute: RedirectIndexRoute, + RelativeIndexRoute: RelativeIndexRoute, ParamsPsNamedFooRoute: ParamsPsNamedFooRoute, ParamsPsNamedPrefixChar123fooChar125Route: ParamsPsNamedPrefixChar123fooChar125Route, diff --git a/e2e/react-router/basic-file-based/src/routes/__root.tsx b/e2e/react-router/basic-file-based/src/routes/__root.tsx index 4062165c86..06734a3b95 100644 --- a/e2e/react-router/basic-file-based/src/routes/__root.tsx +++ b/e2e/react-router/basic-file-based/src/routes/__root.tsx @@ -122,6 +122,14 @@ function RootComponent() { > redirect {' '} + + relative routing + {' '} +
+ Relative Routing Tests - Home +
+
+ Using Links + Using useNavigate +
+
+ +
+ + ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx new file mode 100644 index 0000000000..5cc4b4e58a --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/link/nested/deep/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/nested/deep/"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/nested/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/nested/index.tsx new file mode 100644 index 0000000000..afca201e02 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/nested/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/link/nested/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/nested/"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx new file mode 100644 index 0000000000..30b13cb09d --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx @@ -0,0 +1,31 @@ +import { Link, createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/link/path/$path/')({ + component: RouteComponent, + loader: ({ params }) => { + return params + }, +}) + +function RouteComponent() { + const { path } = Route.useParams() + + return ( +
+
+ Hello from "/relative/links/path/{path}"! +
+
+ + To {path === 'a' ? 'b' : 'a'} + +
+
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/path/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/path/index.tsx new file mode 100644 index 0000000000..be1c7b7a47 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/path/index.tsx @@ -0,0 +1,18 @@ +import { Outlet, createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/link/path/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+
+ Relative Routing Tests - Path Params +
+
+ +
+
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx new file mode 100644 index 0000000000..72a1ee20ec --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/link/relative-link-a')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/relative-link-a"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx new file mode 100644 index 0000000000..e751331b3f --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/link/relative-link-b')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/relative-link-b"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/route.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/route.tsx new file mode 100644 index 0000000000..ae3193613f --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/route.tsx @@ -0,0 +1,103 @@ +import { + Link, + Outlet, + createFileRoute, + useNavigate, +} from '@tanstack/react-router' +import { useEffect } from 'react' + +export const Route = createFileRoute('/relative/link')({ + component: RouteComponent, +}) + +function RouteComponent() { + const navigate = useNavigate() + + useEffect(() => { + console.log('navigate') + }, [navigate]) + + return ( +
+
+ Relative Routing - Links - Index +
+
+ + Return To Home + + + Return To Index + + + Reload + + + Back + + + To Relative Link A + + + To Relative Link B + + + To Deeply Nested + + + To Path Param A + + + To With Search Params + +
+
+ +
+
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/link/with-search/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/link/with-search/index.tsx new file mode 100644 index 0000000000..fd7515ac11 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/link/with-search/index.tsx @@ -0,0 +1,28 @@ +import { createFileRoute, Link } from '@tanstack/react-router' +import { z } from 'zod' + +export const Route = createFileRoute('/relative/link/with-search/')({ + component: RouteComponent, + validateSearch: z.object({ + searchParam: z.string().default('1'), + }), +}) + +function RouteComponent() { + const { searchParam } = Route.useSearch() + return ( + <> +
+ Hello "/relative/link/with-search/" searchParam: {searchParam}! +
+
+ + Update Search + + + ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx new file mode 100644 index 0000000000..453a088d63 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/useNavigate/nested/deep/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/nested/deep/"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx new file mode 100644 index 0000000000..ace502df18 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/useNavigate/nested/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/nested/"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx new file mode 100644 index 0000000000..2e6d4c59de --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx @@ -0,0 +1,40 @@ +import { createFileRoute, useNavigate } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/useNavigate/path/$path/')({ + component: RouteComponent, + loader: ({ params }) => { + return params + }, +}) + +function RouteComponent() { + const navigate = useNavigate() + + const { path } = Route.useParams() + + return ( +
+
+ Hello from "/relative/useNavigate/path/{path}"! +
+
+ +
+
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx new file mode 100644 index 0000000000..18abb4af18 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx @@ -0,0 +1,18 @@ +import { Outlet, createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/useNavigate/path/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+
+ Relative Routing Tests - Path Params +
+
+ +
+
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx new file mode 100644 index 0000000000..e236d80f63 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx @@ -0,0 +1,15 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute( + '/relative/useNavigate/relative-useNavigate-a', +)({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/relative-useNavigate-a"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx new file mode 100644 index 0000000000..d5b2a4e798 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/relative/useNavigate/relative-useNavigate-b')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/relative-useNavigate-b"! +
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/route.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/route.tsx new file mode 100644 index 0000000000..567df92e8b --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/route.tsx @@ -0,0 +1,134 @@ +import { Outlet, createFileRoute, useNavigate } from '@tanstack/react-router' +import { useEffect } from 'react' + +export const Route = createFileRoute('/relative/useNavigate')({ + component: RouteComponent, +}) + +function RouteComponent() { + const navigate = useNavigate() + + useEffect(() => { + console.log('navigate') + }, [navigate]) + + return ( +
+
+ Relative Routing - Links - Index +
+
+ + + + + + + + + +
+
+ +
+
+ ) +} diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx new file mode 100644 index 0000000000..7342202e1d --- /dev/null +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx @@ -0,0 +1,34 @@ +import { createFileRoute, useNavigate } from '@tanstack/react-router' +import { z } from 'zod' + +export const Route = createFileRoute('/relative/useNavigate/with-search/')({ + component: RouteComponent, + validateSearch: z.object({ + searchParam: z.string().default('1'), + }), +}) + +function RouteComponent() { + const navigate = useNavigate() + const { searchParam } = Route.useSearch() + + return ( + <> +
+ Hello "/relative/useNavigate/with-search/" searchParam: {searchParam}! +
+
+ + + ) +} diff --git a/e2e/react-router/basic-file-based/tests/relative.spec.ts b/e2e/react-router/basic-file-based/tests/relative.spec.ts new file mode 100644 index 0000000000..4850d3630d --- /dev/null +++ b/e2e/react-router/basic-file-based/tests/relative.spec.ts @@ -0,0 +1,273 @@ +import { expect, test } from '@playwright/test' +import combinateImport from 'combinate' +import { getTestServerPort } from '@tanstack/router-e2e-utils' +import packageJson from '../package.json' with { type: 'json' } + +// somehow playwright does not correctly import default exports +const combinate = (combinateImport as any).default as typeof combinateImport + +const PORT = await getTestServerPort(packageJson.name) + +test.describe('relative_routing', () => { + const internalNavigationTestMatrix = combinate({ + navigation: ['link', 'useNavigate'] as const, + }) + + internalNavigationTestMatrix.forEach(({ navigation }) => { + test(`simple relative navigation. navigation: ${navigation}`, async ({ + page, + }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const indexLink = page.getByTestId(`relative-${navigation}-index`) + const backLink = page.getByTestId(`relative-${navigation}-back`) + const relativeRouteA = page.getByTestId(`relative-${navigation}-a`) + const relativeRouteB = page.getByTestId(`relative-${navigation}-b`) + + await relativeRouteA.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/relative-${navigation}-a`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-a-header`), + ).toBeInViewport() + + await relativeRouteB.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/relative-${navigation}-b`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-b-header`), + ).toBeInViewport() + + await indexLink.click() + + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-b-header`), + ).not.toBeInViewport() + + await backLink.click() + + await page.waitForURL(`http://localhost:${PORT}/relative`) + + await expect(page.getByTestId(`relative-routing-home`)).toBeInViewport() + }) + + test(`nested chilren. navigation: ${navigation}`, async ({ page }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const backLink = page.getByTestId(`relative-${navigation}-back`) + + const deeplyNestedChildRoute = page.getByTestId( + `relative-${navigation}-deeply-nested`, + ) + + await deeplyNestedChildRoute.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/nested/deep`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-nested-deep-header`), + ).toBeInViewport() + + await backLink.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/nested`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-nested-header`), + ).toBeInViewport() + }) + + test(`with path params. navigation: ${navigation}`, async ({ page }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const pathParamRoute = page.getByTestId(`relative-${navigation}-path`) + + await pathParamRoute.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/path/a`, + ) + + expect(page.url().endsWith('/path/a')).toBe(true) + + await expect( + page.getByTestId(`relative-${navigation}-path-param-header`), + ).toBeInViewport() + + const switchParamLink = page.getByTestId( + `relative-${navigation}-path-param-switchAB`, + ) + + await switchParamLink.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/path/b`, + ) + + expect(page.url().endsWith('/path/b')).toBe(true) + + await expect( + page.getByTestId(`relative-${navigation}-path-param-header`), + ).toBeInViewport() + }) + + test(`with search params. navigation: ${navigation}`, async ({ page }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const searchParamRoute = page.getByTestId( + `relative-${navigation}-withSearch`, + ) + + await searchParamRoute.click() + + let expectedUrl = new URL( + `http://localhost:${PORT}/relative/${navigation}/with-search?searchParam="1"`, + ) + + await page.waitForLoadState('domcontentloaded') + + expect(page.url().toString()).toBe(expectedUrl.toString()) + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toContainText('searchParam: 1') + + const updateSearchLink = page.getByTestId( + `relative-${navigation}-withSearch-update-param`, + ) + + await updateSearchLink.click() + + await page.waitForLoadState('domcontentloaded') + + expectedUrl = new URL( + `http://localhost:${PORT}/relative/${navigation}/with-search?searchParam="2"`, + ) + + expect(page.url().toString()).toBe(expectedUrl.toString()) + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toContainText('searchParam: 2') + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toBeInViewport() + }) + + test(`shouldn't cause excessive rendering. navigation: ${navigation}`, async ({ + page, + }) => { + let navigateMsgs = 0 + + page.on('console', (msg) => { + if (msg.text() === 'navigate') { + navigateMsgs++ + } + }) + + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + expect(navigateMsgs).toBe(1) + const indexLink = page.getByTestId(`relative-${navigation}-index`) + const backLink = page.getByTestId(`relative-${navigation}-back`) + const relativeRouteA = page.getByTestId(`relative-${navigation}-a`) + const relativeRouteB = page.getByTestId(`relative-${navigation}-b`) + const deeplyNestedChildRoute = page.getByTestId( + `relative-${navigation}-deeply-nested`, + ) + const pathParamRoute = page.getByTestId(`relative-${navigation}-path`) + const searchParamRoute = page.getByTestId( + `relative-${navigation}-withSearch`, + ) + + await relativeRouteA.click() + await page.waitForLoadState('domcontentloaded') + await relativeRouteB.click() + await page.waitForLoadState('domcontentloaded') + await deeplyNestedChildRoute.click() + await page.waitForLoadState('domcontentloaded') + await backLink.click() + await page.waitForLoadState('domcontentloaded') + await pathParamRoute.click() + await page.waitForLoadState('domcontentloaded') + const switchParamLink = page.getByTestId( + `relative-${navigation}-path-param-switchAB`, + ) + await switchParamLink.click() + await page.waitForLoadState('domcontentloaded') + await searchParamRoute.click() + await page.waitForLoadState('domcontentloaded') + + const updateSearchLink = page.getByTestId( + `relative-${navigation}-withSearch-update-param`, + ) + + await updateSearchLink.click() + await page.waitForLoadState('domcontentloaded') + + await indexLink.click() + await page.waitForLoadState('domcontentloaded') + + expect(navigateMsgs).toBe(1) + }) + }) +}) From cbec3c908d7d01c27b219535f0b0a12b50be24cd Mon Sep 17 00:00:00 2001 From: Nico Lynzaad Date: Sun, 31 Aug 2025 13:38:44 +0200 Subject: [PATCH 7/8] e2e tests for relative routing on solid --- .../basic-file-based/src/routeTree.gen.ts | 396 ++++++++++++++++++ .../basic-file-based/src/routes/__root.tsx | 8 + .../src/routes/relative/index.tsx | 22 + .../relative/link/nested/deep/index.tsx | 13 + .../src/routes/relative/link/nested/index.tsx | 13 + .../routes/relative/link/path/$path/index.tsx | 31 ++ .../src/routes/relative/link/path/index.tsx | 18 + .../routes/relative/link/relative-link-a.tsx | 13 + .../routes/relative/link/relative-link-b.tsx | 13 + .../src/routes/relative/link/route.tsx | 95 +++++ .../relative/link/with-search/index.tsx | 29 ++ .../useNavigate/nested/deep/index.tsx | 13 + .../relative/useNavigate/nested/index.tsx | 13 + .../relative/useNavigate/path/$path/index.tsx | 40 ++ .../relative/useNavigate/path/index.tsx | 18 + .../useNavigate/relative-useNavigate-a.tsx | 15 + .../useNavigate/relative-useNavigate-b.tsx | 15 + .../src/routes/relative/useNavigate/route.tsx | 134 ++++++ .../useNavigate/with-search/index.tsx | 35 ++ .../basic-file-based/tests/relative.spec.ts | 273 ++++++++++++ 20 files changed, 1207 insertions(+) create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/nested/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/path/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/route.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/link/with-search/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/route.tsx create mode 100644 e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx create mode 100644 e2e/solid-router/basic-file-based/tests/relative.spec.ts diff --git a/e2e/solid-router/basic-file-based/src/routeTree.gen.ts b/e2e/solid-router/basic-file-based/src/routeTree.gen.ts index 08d8fb4978..b81fbe69d5 100644 --- a/e2e/solid-router/basic-file-based/src/routeTree.gen.ts +++ b/e2e/solid-router/basic-file-based/src/routeTree.gen.ts @@ -22,6 +22,7 @@ import { Route as LayoutRouteImport } from './routes/_layout' import { Route as SearchParamsRouteRouteImport } from './routes/search-params/route' import { Route as IndexRouteImport } from './routes/index' import { Route as SearchParamsIndexRouteImport } from './routes/search-params/index' +import { Route as RelativeIndexRouteImport } from './routes/relative/index' import { Route as RedirectIndexRouteImport } from './routes/redirect/index' import { Route as PostsIndexRouteImport } from './routes/posts.index' import { Route as SearchParamsDefaultRouteImport } from './routes/search-params/default' @@ -32,7 +33,13 @@ import { Route as groupLazyinsideRouteImport } from './routes/(group)/lazyinside import { Route as groupInsideRouteImport } from './routes/(group)/inside' import { Route as groupLayoutRouteImport } from './routes/(group)/_layout' import { Route as anotherGroupOnlyrouteinsideRouteImport } from './routes/(another-group)/onlyrouteinside' +import { Route as RelativeUseNavigateRouteRouteImport } from './routes/relative/useNavigate/route' +import { Route as RelativeLinkRouteRouteImport } from './routes/relative/link/route' import { Route as RedirectTargetIndexRouteImport } from './routes/redirect/$target/index' +import { Route as RelativeUseNavigateRelativeUseNavigateBRouteImport } from './routes/relative/useNavigate/relative-useNavigate-b' +import { Route as RelativeUseNavigateRelativeUseNavigateARouteImport } from './routes/relative/useNavigate/relative-useNavigate-a' +import { Route as RelativeLinkRelativeLinkBRouteImport } from './routes/relative/link/relative-link-b' +import { Route as RelativeLinkRelativeLinkARouteImport } from './routes/relative/link/relative-link-a' import { Route as RedirectPreloadThirdRouteImport } from './routes/redirect/preload/third' import { Route as RedirectPreloadSecondRouteImport } from './routes/redirect/preload/second' import { Route as RedirectPreloadFirstRouteImport } from './routes/redirect/preload/first' @@ -44,6 +51,16 @@ import { Route as LayoutLayout2LayoutBRouteImport } from './routes/_layout/_layo import { Route as LayoutLayout2LayoutARouteImport } from './routes/_layout/_layout-2/layout-a' import { Route as groupSubfolderInsideRouteImport } from './routes/(group)/subfolder/inside' import { Route as groupLayoutInsidelayoutRouteImport } from './routes/(group)/_layout.insidelayout' +import { Route as RelativeUseNavigateWithSearchIndexRouteImport } from './routes/relative/useNavigate/with-search/index' +import { Route as RelativeUseNavigatePathIndexRouteImport } from './routes/relative/useNavigate/path/index' +import { Route as RelativeUseNavigateNestedIndexRouteImport } from './routes/relative/useNavigate/nested/index' +import { Route as RelativeLinkWithSearchIndexRouteImport } from './routes/relative/link/with-search/index' +import { Route as RelativeLinkPathIndexRouteImport } from './routes/relative/link/path/index' +import { Route as RelativeLinkNestedIndexRouteImport } from './routes/relative/link/nested/index' +import { Route as RelativeUseNavigatePathPathIndexRouteImport } from './routes/relative/useNavigate/path/$path/index' +import { Route as RelativeUseNavigateNestedDeepIndexRouteImport } from './routes/relative/useNavigate/nested/deep/index' +import { Route as RelativeLinkPathPathIndexRouteImport } from './routes/relative/link/path/$path/index' +import { Route as RelativeLinkNestedDeepIndexRouteImport } from './routes/relative/link/nested/deep/index' const groupRouteImport = createFileRoute('/(group)')() @@ -105,6 +122,11 @@ const SearchParamsIndexRoute = SearchParamsIndexRouteImport.update({ path: '/', getParentRoute: () => SearchParamsRouteRoute, } as any) +const RelativeIndexRoute = RelativeIndexRouteImport.update({ + id: '/relative/', + path: '/relative/', + getParentRoute: () => rootRouteImport, +} as any) const RedirectIndexRoute = RedirectIndexRouteImport.update({ id: '/redirect/', path: '/redirect/', @@ -156,11 +178,46 @@ const anotherGroupOnlyrouteinsideRoute = path: '/onlyrouteinside', getParentRoute: () => rootRouteImport, } as any) +const RelativeUseNavigateRouteRoute = + RelativeUseNavigateRouteRouteImport.update({ + id: '/relative/useNavigate', + path: '/relative/useNavigate', + getParentRoute: () => rootRouteImport, + } as any) +const RelativeLinkRouteRoute = RelativeLinkRouteRouteImport.update({ + id: '/relative/link', + path: '/relative/link', + getParentRoute: () => rootRouteImport, +} as any) const RedirectTargetIndexRoute = RedirectTargetIndexRouteImport.update({ id: '/', path: '/', getParentRoute: () => RedirectTargetRoute, } as any) +const RelativeUseNavigateRelativeUseNavigateBRoute = + RelativeUseNavigateRelativeUseNavigateBRouteImport.update({ + id: '/relative-useNavigate-b', + path: '/relative-useNavigate-b', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigateRelativeUseNavigateARoute = + RelativeUseNavigateRelativeUseNavigateARouteImport.update({ + id: '/relative-useNavigate-a', + path: '/relative-useNavigate-a', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeLinkRelativeLinkBRoute = + RelativeLinkRelativeLinkBRouteImport.update({ + id: '/relative-link-b', + path: '/relative-link-b', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) +const RelativeLinkRelativeLinkARoute = + RelativeLinkRelativeLinkARouteImport.update({ + id: '/relative-link-a', + path: '/relative-link-a', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) const RedirectPreloadThirdRoute = RedirectPreloadThirdRouteImport.update({ id: '/redirect/preload/third', path: '/redirect/preload/third', @@ -217,6 +274,64 @@ const groupLayoutInsidelayoutRoute = groupLayoutInsidelayoutRouteImport.update({ path: '/insidelayout', getParentRoute: () => groupLayoutRoute, } as any) +const RelativeUseNavigateWithSearchIndexRoute = + RelativeUseNavigateWithSearchIndexRouteImport.update({ + id: '/with-search/', + path: '/with-search/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigatePathIndexRoute = + RelativeUseNavigatePathIndexRouteImport.update({ + id: '/path/', + path: '/path/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigateNestedIndexRoute = + RelativeUseNavigateNestedIndexRouteImport.update({ + id: '/nested/', + path: '/nested/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeLinkWithSearchIndexRoute = + RelativeLinkWithSearchIndexRouteImport.update({ + id: '/with-search/', + path: '/with-search/', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) +const RelativeLinkPathIndexRoute = RelativeLinkPathIndexRouteImport.update({ + id: '/path/', + path: '/path/', + getParentRoute: () => RelativeLinkRouteRoute, +} as any) +const RelativeLinkNestedIndexRoute = RelativeLinkNestedIndexRouteImport.update({ + id: '/nested/', + path: '/nested/', + getParentRoute: () => RelativeLinkRouteRoute, +} as any) +const RelativeUseNavigatePathPathIndexRoute = + RelativeUseNavigatePathPathIndexRouteImport.update({ + id: '/path/$path/', + path: '/path/$path/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeUseNavigateNestedDeepIndexRoute = + RelativeUseNavigateNestedDeepIndexRouteImport.update({ + id: '/nested/deep/', + path: '/nested/deep/', + getParentRoute: () => RelativeUseNavigateRouteRoute, + } as any) +const RelativeLinkPathPathIndexRoute = + RelativeLinkPathPathIndexRouteImport.update({ + id: '/path/$path/', + path: '/path/$path/', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) +const RelativeLinkNestedDeepIndexRoute = + RelativeLinkNestedDeepIndexRouteImport.update({ + id: '/nested/deep/', + path: '/nested/deep/', + getParentRoute: () => RelativeLinkRouteRoute, + } as any) export interface FileRoutesByFullPath { '/': typeof groupLayoutRouteWithChildren @@ -228,6 +343,8 @@ export interface FileRoutesByFullPath { '/notRemountDeps': typeof NotRemountDepsRoute '/posts': typeof PostsRouteWithChildren '/remountDeps': typeof RemountDepsRoute + '/relative/link': typeof RelativeLinkRouteRouteWithChildren + '/relative/useNavigate': typeof RelativeUseNavigateRouteRouteWithChildren '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute '/inside': typeof groupInsideRoute '/lazyinside': typeof groupLazyinsideRoute @@ -236,6 +353,7 @@ export interface FileRoutesByFullPath { '/search-params/default': typeof SearchParamsDefaultRoute '/posts/': typeof PostsIndexRoute '/redirect': typeof RedirectIndexRoute + '/relative': typeof RelativeIndexRoute '/search-params/': typeof SearchParamsIndexRoute '/insidelayout': typeof groupLayoutInsidelayoutRoute '/subfolder/inside': typeof groupSubfolderInsideRoute @@ -248,7 +366,21 @@ export interface FileRoutesByFullPath { '/redirect/preload/first': typeof RedirectPreloadFirstRoute '/redirect/preload/second': typeof RedirectPreloadSecondRoute '/redirect/preload/third': typeof RedirectPreloadThirdRoute + '/relative/link/relative-link-a': typeof RelativeLinkRelativeLinkARoute + '/relative/link/relative-link-b': typeof RelativeLinkRelativeLinkBRoute + '/relative/useNavigate/relative-useNavigate-a': typeof RelativeUseNavigateRelativeUseNavigateARoute + '/relative/useNavigate/relative-useNavigate-b': typeof RelativeUseNavigateRelativeUseNavigateBRoute '/redirect/$target/': typeof RedirectTargetIndexRoute + '/relative/link/nested': typeof RelativeLinkNestedIndexRoute + '/relative/link/path': typeof RelativeLinkPathIndexRoute + '/relative/link/with-search': typeof RelativeLinkWithSearchIndexRoute + '/relative/useNavigate/nested': typeof RelativeUseNavigateNestedIndexRoute + '/relative/useNavigate/path': typeof RelativeUseNavigatePathIndexRoute + '/relative/useNavigate/with-search': typeof RelativeUseNavigateWithSearchIndexRoute + '/relative/link/nested/deep': typeof RelativeLinkNestedDeepIndexRoute + '/relative/link/path/$path': typeof RelativeLinkPathPathIndexRoute + '/relative/useNavigate/nested/deep': typeof RelativeUseNavigateNestedDeepIndexRoute + '/relative/useNavigate/path/$path': typeof RelativeUseNavigatePathPathIndexRoute } export interface FileRoutesByTo { '/': typeof groupLayoutRouteWithChildren @@ -258,6 +390,8 @@ export interface FileRoutesByTo { '/editing-b': typeof EditingBRoute '/notRemountDeps': typeof NotRemountDepsRoute '/remountDeps': typeof RemountDepsRoute + '/relative/link': typeof RelativeLinkRouteRouteWithChildren + '/relative/useNavigate': typeof RelativeUseNavigateRouteRouteWithChildren '/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute '/inside': typeof groupInsideRoute '/lazyinside': typeof groupLazyinsideRoute @@ -265,6 +399,7 @@ export interface FileRoutesByTo { '/search-params/default': typeof SearchParamsDefaultRoute '/posts': typeof PostsIndexRoute '/redirect': typeof RedirectIndexRoute + '/relative': typeof RelativeIndexRoute '/search-params': typeof SearchParamsIndexRoute '/insidelayout': typeof groupLayoutInsidelayoutRoute '/subfolder/inside': typeof groupSubfolderInsideRoute @@ -277,7 +412,21 @@ export interface FileRoutesByTo { '/redirect/preload/first': typeof RedirectPreloadFirstRoute '/redirect/preload/second': typeof RedirectPreloadSecondRoute '/redirect/preload/third': typeof RedirectPreloadThirdRoute + '/relative/link/relative-link-a': typeof RelativeLinkRelativeLinkARoute + '/relative/link/relative-link-b': typeof RelativeLinkRelativeLinkBRoute + '/relative/useNavigate/relative-useNavigate-a': typeof RelativeUseNavigateRelativeUseNavigateARoute + '/relative/useNavigate/relative-useNavigate-b': typeof RelativeUseNavigateRelativeUseNavigateBRoute '/redirect/$target': typeof RedirectTargetIndexRoute + '/relative/link/nested': typeof RelativeLinkNestedIndexRoute + '/relative/link/path': typeof RelativeLinkPathIndexRoute + '/relative/link/with-search': typeof RelativeLinkWithSearchIndexRoute + '/relative/useNavigate/nested': typeof RelativeUseNavigateNestedIndexRoute + '/relative/useNavigate/path': typeof RelativeUseNavigatePathIndexRoute + '/relative/useNavigate/with-search': typeof RelativeUseNavigateWithSearchIndexRoute + '/relative/link/nested/deep': typeof RelativeLinkNestedDeepIndexRoute + '/relative/link/path/$path': typeof RelativeLinkPathPathIndexRoute + '/relative/useNavigate/nested/deep': typeof RelativeUseNavigateNestedDeepIndexRoute + '/relative/useNavigate/path/$path': typeof RelativeUseNavigatePathPathIndexRoute } export interface FileRoutesById { __root__: typeof rootRouteImport @@ -291,6 +440,8 @@ export interface FileRoutesById { '/notRemountDeps': typeof NotRemountDepsRoute '/posts': typeof PostsRouteWithChildren '/remountDeps': typeof RemountDepsRoute + '/relative/link': typeof RelativeLinkRouteRouteWithChildren + '/relative/useNavigate': typeof RelativeUseNavigateRouteRouteWithChildren '/(another-group)/onlyrouteinside': typeof anotherGroupOnlyrouteinsideRoute '/(group)': typeof groupRouteWithChildren '/(group)/_layout': typeof groupLayoutRouteWithChildren @@ -302,6 +453,7 @@ export interface FileRoutesById { '/search-params/default': typeof SearchParamsDefaultRoute '/posts/': typeof PostsIndexRoute '/redirect/': typeof RedirectIndexRoute + '/relative/': typeof RelativeIndexRoute '/search-params/': typeof SearchParamsIndexRoute '/(group)/_layout/insidelayout': typeof groupLayoutInsidelayoutRoute '/(group)/subfolder/inside': typeof groupSubfolderInsideRoute @@ -314,7 +466,21 @@ export interface FileRoutesById { '/redirect/preload/first': typeof RedirectPreloadFirstRoute '/redirect/preload/second': typeof RedirectPreloadSecondRoute '/redirect/preload/third': typeof RedirectPreloadThirdRoute + '/relative/link/relative-link-a': typeof RelativeLinkRelativeLinkARoute + '/relative/link/relative-link-b': typeof RelativeLinkRelativeLinkBRoute + '/relative/useNavigate/relative-useNavigate-a': typeof RelativeUseNavigateRelativeUseNavigateARoute + '/relative/useNavigate/relative-useNavigate-b': typeof RelativeUseNavigateRelativeUseNavigateBRoute '/redirect/$target/': typeof RedirectTargetIndexRoute + '/relative/link/nested/': typeof RelativeLinkNestedIndexRoute + '/relative/link/path/': typeof RelativeLinkPathIndexRoute + '/relative/link/with-search/': typeof RelativeLinkWithSearchIndexRoute + '/relative/useNavigate/nested/': typeof RelativeUseNavigateNestedIndexRoute + '/relative/useNavigate/path/': typeof RelativeUseNavigatePathIndexRoute + '/relative/useNavigate/with-search/': typeof RelativeUseNavigateWithSearchIndexRoute + '/relative/link/nested/deep/': typeof RelativeLinkNestedDeepIndexRoute + '/relative/link/path/$path/': typeof RelativeLinkPathPathIndexRoute + '/relative/useNavigate/nested/deep/': typeof RelativeUseNavigateNestedDeepIndexRoute + '/relative/useNavigate/path/$path/': typeof RelativeUseNavigatePathPathIndexRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath @@ -328,6 +494,8 @@ export interface FileRouteTypes { | '/notRemountDeps' | '/posts' | '/remountDeps' + | '/relative/link' + | '/relative/useNavigate' | '/onlyrouteinside' | '/inside' | '/lazyinside' @@ -336,6 +504,7 @@ export interface FileRouteTypes { | '/search-params/default' | '/posts/' | '/redirect' + | '/relative' | '/search-params/' | '/insidelayout' | '/subfolder/inside' @@ -348,7 +517,21 @@ export interface FileRouteTypes { | '/redirect/preload/first' | '/redirect/preload/second' | '/redirect/preload/third' + | '/relative/link/relative-link-a' + | '/relative/link/relative-link-b' + | '/relative/useNavigate/relative-useNavigate-a' + | '/relative/useNavigate/relative-useNavigate-b' | '/redirect/$target/' + | '/relative/link/nested' + | '/relative/link/path' + | '/relative/link/with-search' + | '/relative/useNavigate/nested' + | '/relative/useNavigate/path' + | '/relative/useNavigate/with-search' + | '/relative/link/nested/deep' + | '/relative/link/path/$path' + | '/relative/useNavigate/nested/deep' + | '/relative/useNavigate/path/$path' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -358,6 +541,8 @@ export interface FileRouteTypes { | '/editing-b' | '/notRemountDeps' | '/remountDeps' + | '/relative/link' + | '/relative/useNavigate' | '/onlyrouteinside' | '/inside' | '/lazyinside' @@ -365,6 +550,7 @@ export interface FileRouteTypes { | '/search-params/default' | '/posts' | '/redirect' + | '/relative' | '/search-params' | '/insidelayout' | '/subfolder/inside' @@ -377,7 +563,21 @@ export interface FileRouteTypes { | '/redirect/preload/first' | '/redirect/preload/second' | '/redirect/preload/third' + | '/relative/link/relative-link-a' + | '/relative/link/relative-link-b' + | '/relative/useNavigate/relative-useNavigate-a' + | '/relative/useNavigate/relative-useNavigate-b' | '/redirect/$target' + | '/relative/link/nested' + | '/relative/link/path' + | '/relative/link/with-search' + | '/relative/useNavigate/nested' + | '/relative/useNavigate/path' + | '/relative/useNavigate/with-search' + | '/relative/link/nested/deep' + | '/relative/link/path/$path' + | '/relative/useNavigate/nested/deep' + | '/relative/useNavigate/path/$path' id: | '__root__' | '/' @@ -390,6 +590,8 @@ export interface FileRouteTypes { | '/notRemountDeps' | '/posts' | '/remountDeps' + | '/relative/link' + | '/relative/useNavigate' | '/(another-group)/onlyrouteinside' | '/(group)' | '/(group)/_layout' @@ -401,6 +603,7 @@ export interface FileRouteTypes { | '/search-params/default' | '/posts/' | '/redirect/' + | '/relative/' | '/search-params/' | '/(group)/_layout/insidelayout' | '/(group)/subfolder/inside' @@ -413,7 +616,21 @@ export interface FileRouteTypes { | '/redirect/preload/first' | '/redirect/preload/second' | '/redirect/preload/third' + | '/relative/link/relative-link-a' + | '/relative/link/relative-link-b' + | '/relative/useNavigate/relative-useNavigate-a' + | '/relative/useNavigate/relative-useNavigate-b' | '/redirect/$target/' + | '/relative/link/nested/' + | '/relative/link/path/' + | '/relative/link/with-search/' + | '/relative/useNavigate/nested/' + | '/relative/useNavigate/path/' + | '/relative/useNavigate/with-search/' + | '/relative/link/nested/deep/' + | '/relative/link/path/$path/' + | '/relative/useNavigate/nested/deep/' + | '/relative/useNavigate/path/$path/' fileRoutesById: FileRoutesById } export interface RootRouteChildren { @@ -427,10 +644,13 @@ export interface RootRouteChildren { NotRemountDepsRoute: typeof NotRemountDepsRoute PostsRoute: typeof PostsRouteWithChildren RemountDepsRoute: typeof RemountDepsRoute + RelativeLinkRouteRoute: typeof RelativeLinkRouteRouteWithChildren + RelativeUseNavigateRouteRoute: typeof RelativeUseNavigateRouteRouteWithChildren anotherGroupOnlyrouteinsideRoute: typeof anotherGroupOnlyrouteinsideRoute groupRoute: typeof groupRouteWithChildren RedirectTargetRoute: typeof RedirectTargetRouteWithChildren RedirectIndexRoute: typeof RedirectIndexRoute + RelativeIndexRoute: typeof RelativeIndexRoute ParamsSingleValueRoute: typeof ParamsSingleValueRoute PostsPostIdEditRoute: typeof PostsPostIdEditRoute RedirectPreloadFirstRoute: typeof RedirectPreloadFirstRoute @@ -524,6 +744,13 @@ declare module '@tanstack/solid-router' { preLoaderRoute: typeof SearchParamsIndexRouteImport parentRoute: typeof SearchParamsRouteRoute } + '/relative/': { + id: '/relative/' + path: '/relative' + fullPath: '/relative' + preLoaderRoute: typeof RelativeIndexRouteImport + parentRoute: typeof rootRouteImport + } '/redirect/': { id: '/redirect/' path: '/redirect' @@ -594,6 +821,20 @@ declare module '@tanstack/solid-router' { preLoaderRoute: typeof anotherGroupOnlyrouteinsideRouteImport parentRoute: typeof rootRouteImport } + '/relative/useNavigate': { + id: '/relative/useNavigate' + path: '/relative/useNavigate' + fullPath: '/relative/useNavigate' + preLoaderRoute: typeof RelativeUseNavigateRouteRouteImport + parentRoute: typeof rootRouteImport + } + '/relative/link': { + id: '/relative/link' + path: '/relative/link' + fullPath: '/relative/link' + preLoaderRoute: typeof RelativeLinkRouteRouteImport + parentRoute: typeof rootRouteImport + } '/redirect/$target/': { id: '/redirect/$target/' path: '/' @@ -601,6 +842,34 @@ declare module '@tanstack/solid-router' { preLoaderRoute: typeof RedirectTargetIndexRouteImport parentRoute: typeof RedirectTargetRoute } + '/relative/useNavigate/relative-useNavigate-b': { + id: '/relative/useNavigate/relative-useNavigate-b' + path: '/relative-useNavigate-b' + fullPath: '/relative/useNavigate/relative-useNavigate-b' + preLoaderRoute: typeof RelativeUseNavigateRelativeUseNavigateBRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/relative-useNavigate-a': { + id: '/relative/useNavigate/relative-useNavigate-a' + path: '/relative-useNavigate-a' + fullPath: '/relative/useNavigate/relative-useNavigate-a' + preLoaderRoute: typeof RelativeUseNavigateRelativeUseNavigateARouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/link/relative-link-b': { + id: '/relative/link/relative-link-b' + path: '/relative-link-b' + fullPath: '/relative/link/relative-link-b' + preLoaderRoute: typeof RelativeLinkRelativeLinkBRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/relative-link-a': { + id: '/relative/link/relative-link-a' + path: '/relative-link-a' + fullPath: '/relative/link/relative-link-a' + preLoaderRoute: typeof RelativeLinkRelativeLinkARouteImport + parentRoute: typeof RelativeLinkRouteRoute + } '/redirect/preload/third': { id: '/redirect/preload/third' path: '/redirect/preload/third' @@ -678,6 +947,76 @@ declare module '@tanstack/solid-router' { preLoaderRoute: typeof groupLayoutInsidelayoutRouteImport parentRoute: typeof groupLayoutRoute } + '/relative/useNavigate/with-search/': { + id: '/relative/useNavigate/with-search/' + path: '/with-search' + fullPath: '/relative/useNavigate/with-search' + preLoaderRoute: typeof RelativeUseNavigateWithSearchIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/path/': { + id: '/relative/useNavigate/path/' + path: '/path' + fullPath: '/relative/useNavigate/path' + preLoaderRoute: typeof RelativeUseNavigatePathIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/nested/': { + id: '/relative/useNavigate/nested/' + path: '/nested' + fullPath: '/relative/useNavigate/nested' + preLoaderRoute: typeof RelativeUseNavigateNestedIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/link/with-search/': { + id: '/relative/link/with-search/' + path: '/with-search' + fullPath: '/relative/link/with-search' + preLoaderRoute: typeof RelativeLinkWithSearchIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/path/': { + id: '/relative/link/path/' + path: '/path' + fullPath: '/relative/link/path' + preLoaderRoute: typeof RelativeLinkPathIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/nested/': { + id: '/relative/link/nested/' + path: '/nested' + fullPath: '/relative/link/nested' + preLoaderRoute: typeof RelativeLinkNestedIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/useNavigate/path/$path/': { + id: '/relative/useNavigate/path/$path/' + path: '/path/$path' + fullPath: '/relative/useNavigate/path/$path' + preLoaderRoute: typeof RelativeUseNavigatePathPathIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/useNavigate/nested/deep/': { + id: '/relative/useNavigate/nested/deep/' + path: '/nested/deep' + fullPath: '/relative/useNavigate/nested/deep' + preLoaderRoute: typeof RelativeUseNavigateNestedDeepIndexRouteImport + parentRoute: typeof RelativeUseNavigateRouteRoute + } + '/relative/link/path/$path/': { + id: '/relative/link/path/$path/' + path: '/path/$path' + fullPath: '/relative/link/path/$path' + preLoaderRoute: typeof RelativeLinkPathPathIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } + '/relative/link/nested/deep/': { + id: '/relative/link/nested/deep/' + path: '/nested/deep' + fullPath: '/relative/link/nested/deep' + preLoaderRoute: typeof RelativeLinkNestedDeepIndexRouteImport + parentRoute: typeof RelativeLinkRouteRoute + } } } @@ -731,6 +1070,60 @@ const PostsRouteChildren: PostsRouteChildren = { const PostsRouteWithChildren = PostsRoute._addFileChildren(PostsRouteChildren) +interface RelativeLinkRouteRouteChildren { + RelativeLinkRelativeLinkARoute: typeof RelativeLinkRelativeLinkARoute + RelativeLinkRelativeLinkBRoute: typeof RelativeLinkRelativeLinkBRoute + RelativeLinkNestedIndexRoute: typeof RelativeLinkNestedIndexRoute + RelativeLinkPathIndexRoute: typeof RelativeLinkPathIndexRoute + RelativeLinkWithSearchIndexRoute: typeof RelativeLinkWithSearchIndexRoute + RelativeLinkNestedDeepIndexRoute: typeof RelativeLinkNestedDeepIndexRoute + RelativeLinkPathPathIndexRoute: typeof RelativeLinkPathPathIndexRoute +} + +const RelativeLinkRouteRouteChildren: RelativeLinkRouteRouteChildren = { + RelativeLinkRelativeLinkARoute: RelativeLinkRelativeLinkARoute, + RelativeLinkRelativeLinkBRoute: RelativeLinkRelativeLinkBRoute, + RelativeLinkNestedIndexRoute: RelativeLinkNestedIndexRoute, + RelativeLinkPathIndexRoute: RelativeLinkPathIndexRoute, + RelativeLinkWithSearchIndexRoute: RelativeLinkWithSearchIndexRoute, + RelativeLinkNestedDeepIndexRoute: RelativeLinkNestedDeepIndexRoute, + RelativeLinkPathPathIndexRoute: RelativeLinkPathPathIndexRoute, +} + +const RelativeLinkRouteRouteWithChildren = + RelativeLinkRouteRoute._addFileChildren(RelativeLinkRouteRouteChildren) + +interface RelativeUseNavigateRouteRouteChildren { + RelativeUseNavigateRelativeUseNavigateARoute: typeof RelativeUseNavigateRelativeUseNavigateARoute + RelativeUseNavigateRelativeUseNavigateBRoute: typeof RelativeUseNavigateRelativeUseNavigateBRoute + RelativeUseNavigateNestedIndexRoute: typeof RelativeUseNavigateNestedIndexRoute + RelativeUseNavigatePathIndexRoute: typeof RelativeUseNavigatePathIndexRoute + RelativeUseNavigateWithSearchIndexRoute: typeof RelativeUseNavigateWithSearchIndexRoute + RelativeUseNavigateNestedDeepIndexRoute: typeof RelativeUseNavigateNestedDeepIndexRoute + RelativeUseNavigatePathPathIndexRoute: typeof RelativeUseNavigatePathPathIndexRoute +} + +const RelativeUseNavigateRouteRouteChildren: RelativeUseNavigateRouteRouteChildren = + { + RelativeUseNavigateRelativeUseNavigateARoute: + RelativeUseNavigateRelativeUseNavigateARoute, + RelativeUseNavigateRelativeUseNavigateBRoute: + RelativeUseNavigateRelativeUseNavigateBRoute, + RelativeUseNavigateNestedIndexRoute: RelativeUseNavigateNestedIndexRoute, + RelativeUseNavigatePathIndexRoute: RelativeUseNavigatePathIndexRoute, + RelativeUseNavigateWithSearchIndexRoute: + RelativeUseNavigateWithSearchIndexRoute, + RelativeUseNavigateNestedDeepIndexRoute: + RelativeUseNavigateNestedDeepIndexRoute, + RelativeUseNavigatePathPathIndexRoute: + RelativeUseNavigatePathPathIndexRoute, + } + +const RelativeUseNavigateRouteRouteWithChildren = + RelativeUseNavigateRouteRoute._addFileChildren( + RelativeUseNavigateRouteRouteChildren, + ) + interface groupLayoutRouteChildren { groupLayoutInsidelayoutRoute: typeof groupLayoutInsidelayoutRoute } @@ -786,10 +1179,13 @@ const rootRouteChildren: RootRouteChildren = { NotRemountDepsRoute: NotRemountDepsRoute, PostsRoute: PostsRouteWithChildren, RemountDepsRoute: RemountDepsRoute, + RelativeLinkRouteRoute: RelativeLinkRouteRouteWithChildren, + RelativeUseNavigateRouteRoute: RelativeUseNavigateRouteRouteWithChildren, anotherGroupOnlyrouteinsideRoute: anotherGroupOnlyrouteinsideRoute, groupRoute: groupRouteWithChildren, RedirectTargetRoute: RedirectTargetRouteWithChildren, RedirectIndexRoute: RedirectIndexRoute, + RelativeIndexRoute: RelativeIndexRoute, ParamsSingleValueRoute: ParamsSingleValueRoute, PostsPostIdEditRoute: PostsPostIdEditRoute, RedirectPreloadFirstRoute: RedirectPreloadFirstRoute, diff --git a/e2e/solid-router/basic-file-based/src/routes/__root.tsx b/e2e/solid-router/basic-file-based/src/routes/__root.tsx index c9ff803463..0997c45b37 100644 --- a/e2e/solid-router/basic-file-based/src/routes/__root.tsx +++ b/e2e/solid-router/basic-file-based/src/routes/__root.tsx @@ -122,6 +122,14 @@ function RootComponent() { > redirect {' '} + + relative routing + {' '} +
+ Relative Routing Tests - Home +
+
+ Using Links + Using useNavigate +
+
+ +
+ + ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx new file mode 100644 index 0000000000..d92d2b5e7c --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/nested/deep/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/link/nested/deep/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/nested/deep/"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/nested/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/nested/index.tsx new file mode 100644 index 0000000000..5ddaa68d75 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/nested/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/link/nested/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/nested/"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx new file mode 100644 index 0000000000..1cf079d4b8 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/path/$path/index.tsx @@ -0,0 +1,31 @@ +import { Link, createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/link/path/$path/')({ + component: RouteComponent, + loader: ({ params }) => { + return params + }, +}) + +function RouteComponent() { + const params = Route.useParams() + + return ( +
+
+ Hello from "/relative/links/path/{params().path}"! +
+
+ + To {params().path === 'a' ? 'b' : 'a'} + +
+
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/path/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/path/index.tsx new file mode 100644 index 0000000000..36bf3f5cde --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/path/index.tsx @@ -0,0 +1,18 @@ +import { Outlet, createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/link/path/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+
+ Relative Routing Tests - Path Params +
+
+ +
+
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx new file mode 100644 index 0000000000..daa2cea064 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-a.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/link/relative-link-a')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/relative-link-a"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx new file mode 100644 index 0000000000..9f80899b73 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/relative-link-b.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/link/relative-link-b')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/link/relative-link-b"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/route.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/route.tsx new file mode 100644 index 0000000000..2d77690c4e --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/route.tsx @@ -0,0 +1,95 @@ +import { + Link, + Outlet, + createFileRoute, + useNavigate, +} from '@tanstack/solid-router' +import { createEffect } from 'solid-js' + +export const Route = createFileRoute('/relative/link')({ + component: RouteComponent, +}) + +function RouteComponent() { + const navigate = useNavigate() + + createEffect(() => { + console.log('navigate') + }) + + return ( +
+
+ Relative Routing - Links - Index +
+
+ + Return To Home + + + Return To Index + + + Reload + + + Back + + + To Relative Link A + + + To Relative Link B + + + To Deeply Nested + + + To Path Param A + + + To With Search Params + +
+
+ +
+
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/link/with-search/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/link/with-search/index.tsx new file mode 100644 index 0000000000..f571340a56 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/link/with-search/index.tsx @@ -0,0 +1,29 @@ +import { Link, createFileRoute } from '@tanstack/solid-router' +import { z } from 'zod' + +export const Route = createFileRoute('/relative/link/with-search/')({ + component: RouteComponent, + validateSearch: z.object({ + searchParam: z.string().default('1'), + }), +}) + +function RouteComponent() { + const searchParams = Route.useSearch() + return ( + <> +
+ Hello "/relative/link/with-search/" searchParam:{' '} + {searchParams().searchParam}! +
+
+ + Update Search + + + ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx new file mode 100644 index 0000000000..a373967b11 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/deep/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/useNavigate/nested/deep/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/nested/deep/"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx new file mode 100644 index 0000000000..5e41c4c6db --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/nested/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/useNavigate/nested/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/nested/"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx new file mode 100644 index 0000000000..167aca58d7 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/$path/index.tsx @@ -0,0 +1,40 @@ +import { createFileRoute, useNavigate } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/useNavigate/path/$path/')({ + component: RouteComponent, + loader: ({ params }) => { + return params + }, +}) + +function RouteComponent() { + const navigate = useNavigate() + + const params = Route.useParams() + + return ( +
+
+ Hello from "/relative/useNavigate/path/{params().path}"! +
+
+ +
+
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx new file mode 100644 index 0000000000..6734648ae5 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/path/index.tsx @@ -0,0 +1,18 @@ +import { Outlet, createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/relative/useNavigate/path/')({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+
+ Relative Routing Tests - Path Params +
+
+ +
+
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx new file mode 100644 index 0000000000..bbe5625a62 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-a.tsx @@ -0,0 +1,15 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute( + '/relative/useNavigate/relative-useNavigate-a', +)({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/relative-useNavigate-a"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx new file mode 100644 index 0000000000..9be49cfcdc --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx @@ -0,0 +1,15 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute( + '/relative/useNavigate/relative-useNavigate-b', +)({ + component: RouteComponent, +}) + +function RouteComponent() { + return ( +
+ Hello "/relative/useNavigate/relative-useNavigate-b"! +
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/route.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/route.tsx new file mode 100644 index 0000000000..7bdaeaecb5 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/route.tsx @@ -0,0 +1,134 @@ +import { Outlet, createFileRoute, useNavigate } from '@tanstack/solid-router' +import { createEffect } from 'solid-js' + +export const Route = createFileRoute('/relative/useNavigate')({ + component: RouteComponent, +}) + +function RouteComponent() { + const navigate = useNavigate() + + createEffect(() => { + console.log('navigate') + }) + + return ( +
+
+ Relative Routing - Links - Index +
+
+ + + + + + + + + +
+
+ +
+
+ ) +} diff --git a/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx new file mode 100644 index 0000000000..524eae04a7 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/routes/relative/useNavigate/with-search/index.tsx @@ -0,0 +1,35 @@ +import { createFileRoute, useNavigate } from '@tanstack/solid-router' +import { z } from 'zod' + +export const Route = createFileRoute('/relative/useNavigate/with-search/')({ + component: RouteComponent, + validateSearch: z.object({ + searchParam: z.string().default('1'), + }), +}) + +function RouteComponent() { + const navigate = useNavigate() + const searchParams = Route.useSearch() + + return ( + <> +
+ Hello "/relative/useNavigate/with-search/" searchParam:{' '} + {searchParams().searchParam}! +
+
+ + + ) +} diff --git a/e2e/solid-router/basic-file-based/tests/relative.spec.ts b/e2e/solid-router/basic-file-based/tests/relative.spec.ts new file mode 100644 index 0000000000..4850d3630d --- /dev/null +++ b/e2e/solid-router/basic-file-based/tests/relative.spec.ts @@ -0,0 +1,273 @@ +import { expect, test } from '@playwright/test' +import combinateImport from 'combinate' +import { getTestServerPort } from '@tanstack/router-e2e-utils' +import packageJson from '../package.json' with { type: 'json' } + +// somehow playwright does not correctly import default exports +const combinate = (combinateImport as any).default as typeof combinateImport + +const PORT = await getTestServerPort(packageJson.name) + +test.describe('relative_routing', () => { + const internalNavigationTestMatrix = combinate({ + navigation: ['link', 'useNavigate'] as const, + }) + + internalNavigationTestMatrix.forEach(({ navigation }) => { + test(`simple relative navigation. navigation: ${navigation}`, async ({ + page, + }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const indexLink = page.getByTestId(`relative-${navigation}-index`) + const backLink = page.getByTestId(`relative-${navigation}-back`) + const relativeRouteA = page.getByTestId(`relative-${navigation}-a`) + const relativeRouteB = page.getByTestId(`relative-${navigation}-b`) + + await relativeRouteA.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/relative-${navigation}-a`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-a-header`), + ).toBeInViewport() + + await relativeRouteB.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/relative-${navigation}-b`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-b-header`), + ).toBeInViewport() + + await indexLink.click() + + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-b-header`), + ).not.toBeInViewport() + + await backLink.click() + + await page.waitForURL(`http://localhost:${PORT}/relative`) + + await expect(page.getByTestId(`relative-routing-home`)).toBeInViewport() + }) + + test(`nested chilren. navigation: ${navigation}`, async ({ page }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const backLink = page.getByTestId(`relative-${navigation}-back`) + + const deeplyNestedChildRoute = page.getByTestId( + `relative-${navigation}-deeply-nested`, + ) + + await deeplyNestedChildRoute.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/nested/deep`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-nested-deep-header`), + ).toBeInViewport() + + await backLink.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/nested`, + ) + + await expect( + page.getByTestId(`relative-${navigation}-nested-header`), + ).toBeInViewport() + }) + + test(`with path params. navigation: ${navigation}`, async ({ page }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const pathParamRoute = page.getByTestId(`relative-${navigation}-path`) + + await pathParamRoute.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/path/a`, + ) + + expect(page.url().endsWith('/path/a')).toBe(true) + + await expect( + page.getByTestId(`relative-${navigation}-path-param-header`), + ).toBeInViewport() + + const switchParamLink = page.getByTestId( + `relative-${navigation}-path-param-switchAB`, + ) + + await switchParamLink.click() + + await page.waitForURL( + `http://localhost:${PORT}/relative/${navigation}/path/b`, + ) + + expect(page.url().endsWith('/path/b')).toBe(true) + + await expect( + page.getByTestId(`relative-${navigation}-path-param-header`), + ).toBeInViewport() + }) + + test(`with search params. navigation: ${navigation}`, async ({ page }) => { + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + const searchParamRoute = page.getByTestId( + `relative-${navigation}-withSearch`, + ) + + await searchParamRoute.click() + + let expectedUrl = new URL( + `http://localhost:${PORT}/relative/${navigation}/with-search?searchParam="1"`, + ) + + await page.waitForLoadState('domcontentloaded') + + expect(page.url().toString()).toBe(expectedUrl.toString()) + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toBeInViewport() + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toContainText('searchParam: 1') + + const updateSearchLink = page.getByTestId( + `relative-${navigation}-withSearch-update-param`, + ) + + await updateSearchLink.click() + + await page.waitForLoadState('domcontentloaded') + + expectedUrl = new URL( + `http://localhost:${PORT}/relative/${navigation}/with-search?searchParam="2"`, + ) + + expect(page.url().toString()).toBe(expectedUrl.toString()) + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toContainText('searchParam: 2') + + await expect( + page.getByTestId(`relative-${navigation}-withSearch-header`), + ).toBeInViewport() + }) + + test(`shouldn't cause excessive rendering. navigation: ${navigation}`, async ({ + page, + }) => { + let navigateMsgs = 0 + + page.on('console', (msg) => { + if (msg.text() === 'navigate') { + navigateMsgs++ + } + }) + + await page.waitForLoadState('networkidle') + await page.goto(`/relative/${navigation}`) + await page.waitForURL(`http://localhost:${PORT}/relative/${navigation}`) + + await expect( + page.getByTestId(`relative-${navigation}-header`), + ).toBeInViewport() + + expect(navigateMsgs).toBe(1) + const indexLink = page.getByTestId(`relative-${navigation}-index`) + const backLink = page.getByTestId(`relative-${navigation}-back`) + const relativeRouteA = page.getByTestId(`relative-${navigation}-a`) + const relativeRouteB = page.getByTestId(`relative-${navigation}-b`) + const deeplyNestedChildRoute = page.getByTestId( + `relative-${navigation}-deeply-nested`, + ) + const pathParamRoute = page.getByTestId(`relative-${navigation}-path`) + const searchParamRoute = page.getByTestId( + `relative-${navigation}-withSearch`, + ) + + await relativeRouteA.click() + await page.waitForLoadState('domcontentloaded') + await relativeRouteB.click() + await page.waitForLoadState('domcontentloaded') + await deeplyNestedChildRoute.click() + await page.waitForLoadState('domcontentloaded') + await backLink.click() + await page.waitForLoadState('domcontentloaded') + await pathParamRoute.click() + await page.waitForLoadState('domcontentloaded') + const switchParamLink = page.getByTestId( + `relative-${navigation}-path-param-switchAB`, + ) + await switchParamLink.click() + await page.waitForLoadState('domcontentloaded') + await searchParamRoute.click() + await page.waitForLoadState('domcontentloaded') + + const updateSearchLink = page.getByTestId( + `relative-${navigation}-withSearch-update-param`, + ) + + await updateSearchLink.click() + await page.waitForLoadState('domcontentloaded') + + await indexLink.click() + await page.waitForLoadState('domcontentloaded') + + expect(navigateMsgs).toBe(1) + }) + }) +}) From 31035c777fc2d8857ca06c91fcc869f019dc8359 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 31 Aug 2025 11:41:39 +0000 Subject: [PATCH 8/8] ci: apply automated fixes --- .../routes/relative/useNavigate/relative-useNavigate-b.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx index d5b2a4e798..b6e1d607dd 100644 --- a/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx +++ b/e2e/react-router/basic-file-based/src/routes/relative/useNavigate/relative-useNavigate-b.tsx @@ -1,6 +1,8 @@ import { createFileRoute } from '@tanstack/react-router' -export const Route = createFileRoute('/relative/useNavigate/relative-useNavigate-b')({ +export const Route = createFileRoute( + '/relative/useNavigate/relative-useNavigate-b', +)({ component: RouteComponent, })