Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions e2e/solid-start/custom-basepath/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
import { Route as rootRouteImport } from './routes/__root'
import { Route as UsersRouteImport } from './routes/users'
import { Route as PostsRouteImport } from './routes/posts'
import { Route as LogoutRouteImport } from './routes/logout'
import { Route as DeferredRouteImport } from './routes/deferred'
import { Route as IndexRouteImport } from './routes/index'
import { Route as UsersIndexRouteImport } from './routes/users.index'
import { Route as RedirectIndexRouteImport } from './routes/redirect.index'
import { Route as PostsIndexRouteImport } from './routes/posts.index'
import { Route as UsersUserIdRouteImport } from './routes/users.$userId'
import { Route as RedirectThrowItRouteImport } from './routes/redirect.throw-it'
import { Route as PostsPostIdRouteImport } from './routes/posts.$postId'
import { Route as ApiUsersRouteImport } from './routes/api/users'
import { Route as PostsPostIdDeepRouteImport } from './routes/posts_.$postId.deep'
Expand All @@ -31,6 +34,11 @@ const PostsRoute = PostsRouteImport.update({
path: '/posts',
getParentRoute: () => rootRouteImport,
} as any)
const LogoutRoute = LogoutRouteImport.update({
id: '/logout',
path: '/logout',
getParentRoute: () => rootRouteImport,
} as any)
const DeferredRoute = DeferredRouteImport.update({
id: '/deferred',
path: '/deferred',
Expand All @@ -46,6 +54,11 @@ const UsersIndexRoute = UsersIndexRouteImport.update({
path: '/',
getParentRoute: () => UsersRoute,
} as any)
const RedirectIndexRoute = RedirectIndexRouteImport.update({
id: '/redirect/',
path: '/redirect/',
getParentRoute: () => rootRouteImport,
} as any)
const PostsIndexRoute = PostsIndexRouteImport.update({
id: '/',
path: '/',
Expand All @@ -56,6 +69,11 @@ const UsersUserIdRoute = UsersUserIdRouteImport.update({
path: '/$userId',
getParentRoute: () => UsersRoute,
} as any)
const RedirectThrowItRoute = RedirectThrowItRouteImport.update({
id: '/redirect/throw-it',
path: '/redirect/throw-it',
getParentRoute: () => rootRouteImport,
} as any)
const PostsPostIdRoute = PostsPostIdRouteImport.update({
id: '/$postId',
path: '/$postId',
Expand All @@ -80,23 +98,29 @@ const ApiUsersUserIdRoute = ApiUsersUserIdRouteImport.update({
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/deferred': typeof DeferredRoute
'/logout': typeof LogoutRoute
'/posts': typeof PostsRouteWithChildren
'/users': typeof UsersRouteWithChildren
'/api/users': typeof ApiUsersRouteWithChildren
'/posts/$postId': typeof PostsPostIdRoute
'/redirect/throw-it': typeof RedirectThrowItRoute
'/users/$userId': typeof UsersUserIdRoute
'/posts/': typeof PostsIndexRoute
'/redirect': typeof RedirectIndexRoute
'/users/': typeof UsersIndexRoute
'/api/users/$userId': typeof ApiUsersUserIdRoute
'/posts/$postId/deep': typeof PostsPostIdDeepRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/deferred': typeof DeferredRoute
'/logout': typeof LogoutRoute
'/api/users': typeof ApiUsersRouteWithChildren
'/posts/$postId': typeof PostsPostIdRoute
'/redirect/throw-it': typeof RedirectThrowItRoute
'/users/$userId': typeof UsersUserIdRoute
'/posts': typeof PostsIndexRoute
'/redirect': typeof RedirectIndexRoute
'/users': typeof UsersIndexRoute
'/api/users/$userId': typeof ApiUsersUserIdRoute
'/posts/$postId/deep': typeof PostsPostIdDeepRoute
Expand All @@ -105,12 +129,15 @@ export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/deferred': typeof DeferredRoute
'/logout': typeof LogoutRoute
'/posts': typeof PostsRouteWithChildren
'/users': typeof UsersRouteWithChildren
'/api/users': typeof ApiUsersRouteWithChildren
'/posts/$postId': typeof PostsPostIdRoute
'/redirect/throw-it': typeof RedirectThrowItRoute
'/users/$userId': typeof UsersUserIdRoute
'/posts/': typeof PostsIndexRoute
'/redirect/': typeof RedirectIndexRoute
'/users/': typeof UsersIndexRoute
'/api/users/$userId': typeof ApiUsersUserIdRoute
'/posts_/$postId/deep': typeof PostsPostIdDeepRoute
Expand All @@ -120,36 +147,45 @@ export interface FileRouteTypes {
fullPaths:
| '/'
| '/deferred'
| '/logout'
| '/posts'
| '/users'
| '/api/users'
| '/posts/$postId'
| '/redirect/throw-it'
| '/users/$userId'
| '/posts/'
| '/redirect'
| '/users/'
| '/api/users/$userId'
| '/posts/$postId/deep'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
| '/deferred'
| '/logout'
| '/api/users'
| '/posts/$postId'
| '/redirect/throw-it'
| '/users/$userId'
| '/posts'
| '/redirect'
| '/users'
| '/api/users/$userId'
| '/posts/$postId/deep'
id:
| '__root__'
| '/'
| '/deferred'
| '/logout'
| '/posts'
| '/users'
| '/api/users'
| '/posts/$postId'
| '/redirect/throw-it'
| '/users/$userId'
| '/posts/'
| '/redirect/'
| '/users/'
| '/api/users/$userId'
| '/posts_/$postId/deep'
Expand All @@ -158,9 +194,12 @@ export interface FileRouteTypes {
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
DeferredRoute: typeof DeferredRoute
LogoutRoute: typeof LogoutRoute
PostsRoute: typeof PostsRouteWithChildren
UsersRoute: typeof UsersRouteWithChildren
ApiUsersRoute: typeof ApiUsersRouteWithChildren
RedirectThrowItRoute: typeof RedirectThrowItRoute
RedirectIndexRoute: typeof RedirectIndexRoute
PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute
}

Expand All @@ -180,6 +219,13 @@ declare module '@tanstack/solid-router' {
preLoaderRoute: typeof PostsRouteImport
parentRoute: typeof rootRouteImport
}
'/logout': {
id: '/logout'
path: '/logout'
fullPath: '/logout'
preLoaderRoute: typeof LogoutRouteImport
parentRoute: typeof rootRouteImport
}
'/deferred': {
id: '/deferred'
path: '/deferred'
Expand All @@ -201,6 +247,13 @@ declare module '@tanstack/solid-router' {
preLoaderRoute: typeof UsersIndexRouteImport
parentRoute: typeof UsersRoute
}
'/redirect/': {
id: '/redirect/'
path: '/redirect'
fullPath: '/redirect'
preLoaderRoute: typeof RedirectIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/posts/': {
id: '/posts/'
path: '/'
Expand All @@ -215,6 +268,13 @@ declare module '@tanstack/solid-router' {
preLoaderRoute: typeof UsersUserIdRouteImport
parentRoute: typeof UsersRoute
}
'/redirect/throw-it': {
id: '/redirect/throw-it'
path: '/redirect/throw-it'
fullPath: '/redirect/throw-it'
preLoaderRoute: typeof RedirectThrowItRouteImport
parentRoute: typeof rootRouteImport
}
'/posts/$postId': {
id: '/posts/$postId'
path: '/$postId'
Expand Down Expand Up @@ -285,9 +345,12 @@ const ApiUsersRouteWithChildren = ApiUsersRoute._addFileChildren(
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
DeferredRoute: DeferredRoute,
LogoutRoute: LogoutRoute,
PostsRoute: PostsRouteWithChildren,
UsersRoute: UsersRouteWithChildren,
ApiUsersRoute: ApiUsersRouteWithChildren,
RedirectThrowItRoute: RedirectThrowItRoute,
RedirectIndexRoute: RedirectIndexRoute,
PostsPostIdDeepRoute: PostsPostIdDeepRoute,
}
export const routeTree = rootRouteImport
Expand Down
32 changes: 32 additions & 0 deletions e2e/solid-start/custom-basepath/src/routes/logout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { createFileRoute, redirect } from '@tanstack/solid-router'
import { createServerFn } from '@tanstack/solid-start'

const logoutFn = createServerFn({
method: 'POST',
}).handler(async () => {
// do logout stuff here
throw redirect({
to: '/',
})
})

export const Route = createFileRoute('/logout')({
component: Home,
})

function Home() {
return (
<div class="p-2">
<h3>Logout Page</h3>
<p>
This form tests that server function URLs correctly include the app's
basepath. The form action should be '/custom/basepath/_serverFn/...' not
just '/_serverFn/...'
</p>
<form action={logoutFn.url} method="post">
<input type="hidden" name="csrfToken" value="123abc" />
<button type="submit">Logout</button>
</form>
</div>
)
}
5 changes: 2 additions & 3 deletions e2e/solid-start/custom-basepath/src/routes/posts.$postId.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ErrorComponent, Link, createFileRoute } from '@tanstack/solid-router'
import type { ErrorComponentProps } from '@tanstack/solid-router'
import { Link, createFileRoute } from '@tanstack/solid-router'

import { fetchPost } from '~/utils/posts'
import { NotFound } from '~/components/NotFound'
Expand All @@ -18,7 +17,7 @@ function PostComponent() {
const post = Route.useLoaderData()

return (
<div class="space-y-2">
<div class="space-y-2" data-testid="post-view">
<h4 class="text-xl font-bold underline">{post().title}</h4>
<div class="text-sm">{post().body}</div>
<Link
Expand Down
15 changes: 15 additions & 0 deletions e2e/solid-start/custom-basepath/src/routes/redirect.index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Link, createFileRoute } from '@tanstack/solid-router'

export const Route = createFileRoute('/redirect/')({
component: RouteComponent,
})

function RouteComponent() {
return (
<div class="p-2 flex gap-2">
<Link to="/redirect/throw-it">
<div data-testid="link-to-throw-it">Throw It</div>
</Link>
</div>
)
}
10 changes: 10 additions & 0 deletions e2e/solid-start/custom-basepath/src/routes/redirect.throw-it.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createFileRoute, redirect } from '@tanstack/solid-router'

export const Route = createFileRoute('/redirect/throw-it')({
beforeLoad: () => {
throw redirect({
to: '/posts/$postId',
params: { postId: '1' },
})
},
})
36 changes: 36 additions & 0 deletions e2e/solid-start/custom-basepath/tests/navigation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,39 @@ test('Should change title on client side navigation', async ({ page }) => {

await expect(page).toHaveTitle('Posts page')
})

test('Server function URLs correctly include app basepath', async ({
page,
}) => {
await page.goto('/logout')

const form = page.locator('form')
const actionUrl = await form.getAttribute('action')

expect(actionUrl).toMatch(/^\/custom\/basepath\/_serverFn\//)
})

test('client-side redirect', async ({ page, baseURL }) => {
await page.goto('/redirect')
await page.getByTestId('link-to-throw-it').click()
await page.waitForLoadState('networkidle')

expect(await page.getByTestId('post-view').isVisible()).toBe(true)
expect(page.url()).toBe(`${baseURL}/posts/1`)
})

test('server-side redirect', async ({ page, baseURL }) => {
await page.goto('/redirect/throw-it')
await page.waitForLoadState('networkidle')

expect(await page.getByTestId('post-view').isVisible()).toBe(true)
expect(page.url()).toBe(`${baseURL}/posts/1`)

// do not follow redirects since we want to test the Location header
await page.request
.get('/redirect/throw-it', { maxRedirects: 0 })
.then((res) => {
const headers = new Headers(res.headers())
expect(headers.get('location')).toBe('/custom/basepath/posts/1')
})
})
Loading