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
6 changes: 6 additions & 0 deletions e2e/react-start/server-functions-global-middleware/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
dist
.nitro
.output
port*.txt
test-results
34 changes: 34 additions & 0 deletions e2e/react-start/server-functions-global-middleware/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "tanstack-react-start-e2e-server-functions-global-middleware",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"dev": "vite dev --port 3000",
"dev:e2e": "vite dev",
"build": "vite build && tsc --noEmit",
"preview": "vite preview",
"start": "pnpx srvx --prod -s ../client dist/server/server.js",
"test:e2e": "rm -rf port*.txt; playwright test --project=chromium"
},
"dependencies": {
"@tanstack/react-router": "workspace:^",
"@tanstack/react-start": "workspace:^",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"vite": "^7.1.7"
},
"devDependencies": {
"@playwright/test": "^1.50.1",
"@tailwindcss/vite": "^4.1.18",
"@tanstack/router-e2e-utils": "workspace:^",
"@types/node": "^22.10.2",
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"@vitejs/plugin-react": "^4.3.4",
"srvx": "^0.9.8",
"tailwindcss": "^4.1.18",
"typescript": "^5.7.2",
"vite-tsconfig-paths": "^5.1.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { defineConfig, devices } from '@playwright/test'
import { getTestServerPort } from '@tanstack/router-e2e-utils'
import packageJson from './package.json' with { type: 'json' }

export const PORT = await getTestServerPort(packageJson.name)
const baseURL = `http://localhost:${PORT}`

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
workers: 1,

reporter: [['line']],

use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL,
},

webServer: {
command: `VITE_SERVER_PORT=${PORT} pnpm build && PORT=${PORT} VITE_SERVER_PORT=${PORT} pnpm start`,
url: baseURL,
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
},

projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* eslint-disable */

// @ts-nocheck

// noinspection JSUnusedGlobalSymbols

// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.

import { Route as rootRouteImport } from './routes/__root'
import { Route as SimpleRouteImport } from './routes/simple'
import { Route as MultipleServerFunctionsRouteImport } from './routes/multiple-server-functions'
import { Route as IndexRouteImport } from './routes/index'

const SimpleRoute = SimpleRouteImport.update({
id: '/simple',
path: '/simple',
getParentRoute: () => rootRouteImport,
} as any)
const MultipleServerFunctionsRoute = MultipleServerFunctionsRouteImport.update({
id: '/multiple-server-functions',
path: '/multiple-server-functions',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)

export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/multiple-server-functions': typeof MultipleServerFunctionsRoute
'/simple': typeof SimpleRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/multiple-server-functions': typeof MultipleServerFunctionsRoute
'/simple': typeof SimpleRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/multiple-server-functions': typeof MultipleServerFunctionsRoute
'/simple': typeof SimpleRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/multiple-server-functions' | '/simple'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/multiple-server-functions' | '/simple'
id: '__root__' | '/' | '/multiple-server-functions' | '/simple'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
MultipleServerFunctionsRoute: typeof MultipleServerFunctionsRoute
SimpleRoute: typeof SimpleRoute
}

declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/simple': {
id: '/simple'
path: '/simple'
fullPath: '/simple'
preLoaderRoute: typeof SimpleRouteImport
parentRoute: typeof rootRouteImport
}
'/multiple-server-functions': {
id: '/multiple-server-functions'
path: '/multiple-server-functions'
fullPath: '/multiple-server-functions'
preLoaderRoute: typeof MultipleServerFunctionsRouteImport
parentRoute: typeof rootRouteImport
}
'/': {
id: '/'
path: '/'
fullPath: '/'
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
}
}

const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
MultipleServerFunctionsRoute: MultipleServerFunctionsRoute,
SimpleRoute: SimpleRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()

import type { getRouter } from './router.tsx'
import type { startInstance } from './start.ts'
declare module '@tanstack/react-start' {
interface Register {
ssr: true
router: Awaited<ReturnType<typeof getRouter>>
config: Awaited<ReturnType<typeof startInstance.getOptions>>
}
}
12 changes: 12 additions & 0 deletions e2e/react-start/server-functions-global-middleware/src/router.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

export function getRouter() {
const router = createRouter({
routeTree,
defaultPreload: 'intent',
scrollRestoration: true,
})

return router
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/// <reference types="vite/client" />
import * as React from 'react'
import {
HeadContent,
Link,
Outlet,
Scripts,
createRootRoute,
} from '@tanstack/react-router'
import appCss from '~/styles/app.css?url'

export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
],
links: [{ rel: 'stylesheet', href: appCss }],
}),
component: RootComponent,
})

function RootComponent() {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<div className="p-2 flex gap-2 text-lg">
<Link
to="/"
activeProps={{
className: 'font-bold',
}}
activeOptions={{ exact: true }}
>
Home
</Link>
</div>
<hr />
<Outlet />
<Scripts />
</body>
</html>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Link, createFileRoute } from '@tanstack/react-router'

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

function Home() {
return (
<div className="p-8">
<h1 className="font-bold text-lg">
Global Middleware Deduplication E2E Tests
</h1>
<p className="text-gray-600 mb-4">
Tests for issue #5239: global request middleware is executed multiple
times for single request
</p>
<ul className="list-disc p-4">
<li>
<Link to="/simple" data-testid="link-simple">
Simple test - single server function with global middleware
</Link>
</li>
<li>
<Link to="/multiple-server-functions" data-testid="link-multiple">
Complex test - multiple server functions in loader with shared
global middleware
</Link>
</li>
</ul>
</div>
)
}
Loading
Loading