-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
test(vue-router) basepath file based #6110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| node_modules | ||
| .DS_Store | ||
| dist | ||
| dist-hash | ||
| dist-ssr | ||
| *.local | ||
|
|
||
| /test-results/ | ||
| /playwright-report/ | ||
| /blob-report/ | ||
| /playwright/.cache/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| </head> | ||
| <body> | ||
| <div id="app"></div> | ||
| <script type="module" src="/src/main.tsx"></script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| { | ||
| "name": "tanstack-router-e2e-vue-basepath-file-based", | ||
| "private": true, | ||
| "type": "module", | ||
| "scripts": { | ||
| "dev": "vite --port 3000", | ||
| "dev:e2e": "vite", | ||
| "build": "vite build && tsc --noEmit", | ||
| "preview": "vite preview", | ||
| "start": "vite", | ||
| "test:e2e": "rm -rf port*.txt; playwright test --project=chromium" | ||
| }, | ||
| "dependencies": { | ||
| "@tailwindcss/postcss": "^4.1.15", | ||
| "@tanstack/router-plugin": "workspace:^", | ||
| "@tanstack/vue-query": "^5.90.0", | ||
| "@tanstack/vue-query-devtools": "^6.1.2", | ||
| "@tanstack/vue-router": "workspace:^", | ||
| "@tanstack/vue-router-devtools": "workspace:^", | ||
| "postcss": "^8.5.1", | ||
| "redaxios": "^0.5.1", | ||
| "tailwindcss": "^4.1.17", | ||
| "vue": "^3.5.16" | ||
| }, | ||
| "devDependencies": { | ||
| "@playwright/test": "^1.50.1", | ||
| "@tanstack/router-e2e-utils": "workspace:^", | ||
| "@vitejs/plugin-vue": "^5.2.3", | ||
| "@vitejs/plugin-vue-jsx": "^4.1.2", | ||
| "typescript": "~5.8.3", | ||
| "vite": "^7.1.7", | ||
| "vue-tsc": "^3.1.5" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { defineConfig, devices } from '@playwright/test' | ||
| import { | ||
| getDummyServerPort, | ||
| getTestServerPort, | ||
| } from '@tanstack/router-e2e-utils' | ||
| import packageJson from './package.json' with { type: 'json' } | ||
|
|
||
| const PORT = await getTestServerPort(packageJson.name) | ||
| const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) | ||
| const baseURL = `http://localhost:${PORT}` | ||
| /** | ||
| * See https://playwright.dev/docs/test-configuration. | ||
| */ | ||
| export default defineConfig({ | ||
| testDir: './tests', | ||
| workers: 1, | ||
|
|
||
| reporter: [['line']], | ||
|
|
||
| globalSetup: './tests/setup/global.setup.ts', | ||
| globalTeardown: './tests/setup/global.teardown.ts', | ||
|
|
||
| use: { | ||
| /* Base URL to use in actions like `await page.goto('/')`. */ | ||
| baseURL, | ||
| }, | ||
|
|
||
| webServer: { | ||
| command: `VITE_NODE_ENV="test" VITE_SERVER_PORT=${PORT} VITE_EXTERNAL_PORT=${EXTERNAL_PORT} pnpm build && VITE_SERVER_PORT=${PORT} pnpm preview --port ${PORT}`, | ||
| 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,30 @@ | ||
| import { createApp, h } from 'vue' | ||
| import { RouterProvider, createRouter } from '@tanstack/vue-router' | ||
| import { routeTree } from './routeTree.gen' | ||
|
|
||
| // Set up a Router instance | ||
| const router = createRouter({ | ||
| routeTree, | ||
| defaultPreload: 'intent', | ||
| defaultStaleTime: 5000, | ||
| scrollRestoration: true, | ||
| basepath: '/app/', | ||
| }) | ||
|
|
||
| // Register things for typesafety | ||
| declare module '@tanstack/vue-router' { | ||
| interface Register { | ||
| router: typeof router | ||
| } | ||
| } | ||
|
|
||
| const rootElement = document.getElementById('app')! | ||
|
|
||
| if (!rootElement.innerHTML) { | ||
| const app = createApp({ | ||
| setup() { | ||
| return () => h(RouterProvider, { router }) | ||
| }, | ||
| }) | ||
| app.mount('#app') | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| /* 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 AboutRouteImport } from './routes/about' | ||
| import { Route as IndexRouteImport } from './routes/index' | ||
|
|
||
| const AboutRoute = AboutRouteImport.update({ | ||
| id: '/about', | ||
| path: '/about', | ||
| getParentRoute: () => rootRouteImport, | ||
| } as any) | ||
| const IndexRoute = IndexRouteImport.update({ | ||
| id: '/', | ||
| path: '/', | ||
| getParentRoute: () => rootRouteImport, | ||
| } as any) | ||
|
|
||
| export interface FileRoutesByFullPath { | ||
| '/': typeof IndexRoute | ||
| '/about': typeof AboutRoute | ||
| } | ||
| export interface FileRoutesByTo { | ||
| '/': typeof IndexRoute | ||
| '/about': typeof AboutRoute | ||
| } | ||
| export interface FileRoutesById { | ||
| __root__: typeof rootRouteImport | ||
| '/': typeof IndexRoute | ||
| '/about': typeof AboutRoute | ||
| } | ||
| export interface FileRouteTypes { | ||
| fileRoutesByFullPath: FileRoutesByFullPath | ||
| fullPaths: '/' | '/about' | ||
| fileRoutesByTo: FileRoutesByTo | ||
| to: '/' | '/about' | ||
| id: '__root__' | '/' | '/about' | ||
| fileRoutesById: FileRoutesById | ||
| } | ||
| export interface RootRouteChildren { | ||
| IndexRoute: typeof IndexRoute | ||
| AboutRoute: typeof AboutRoute | ||
| } | ||
|
|
||
| declare module '@tanstack/vue-router' { | ||
| interface FileRoutesByPath { | ||
| '/about': { | ||
| id: '/about' | ||
| path: '/about' | ||
| fullPath: '/about' | ||
| preLoaderRoute: typeof AboutRouteImport | ||
| parentRoute: typeof rootRouteImport | ||
| } | ||
| '/': { | ||
| id: '/' | ||
| path: '/' | ||
| fullPath: '/' | ||
| preLoaderRoute: typeof IndexRouteImport | ||
| parentRoute: typeof rootRouteImport | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const rootRouteChildren: RootRouteChildren = { | ||
| IndexRoute: IndexRoute, | ||
| AboutRoute: AboutRoute, | ||
| } | ||
| export const routeTree = rootRouteImport | ||
| ._addFileChildren(rootRouteChildren) | ||
| ._addFileTypes<FileRouteTypes>() |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,3 @@ | ||||||||||||||||||
| import { createRootRoute } from '@tanstack/vue-router' | ||||||||||||||||||
|
|
||||||||||||||||||
| export const Route = createRootRoute() | ||||||||||||||||||
|
Comment on lines
+1
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing Outlet component in root route. The root route lacks a component with an Apply this diff to add the required component with Outlet: -import { createRootRoute } from '@tanstack/vue-router'
+import { createRootRoute, Outlet } from '@tanstack/vue-router'
-export const Route = createRootRoute()
+export const Route = createRootRoute({
+ component: () => <Outlet />,
+})📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { createFileRoute } from '@tanstack/vue-router' | ||
|
|
||
| export const Route = createFileRoute('/about')({ | ||
| component: RouteComponent, | ||
| }) | ||
|
|
||
| function RouteComponent() { | ||
| const navigate = Route.useNavigate() | ||
|
|
||
| return ( | ||
| <div data-testid="about-component"> | ||
| <button | ||
| onClick={() => navigate({ to: '/', reloadDocument: true })} | ||
| data-testid="to-home-btn" | ||
| > | ||
| Navigate to / with document reload | ||
| </button> | ||
| </div> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import { createFileRoute } from '@tanstack/vue-router' | ||
|
|
||
| export const Route = createFileRoute('/')({ | ||
| component: App, | ||
| }) | ||
|
|
||
| function App() { | ||
| const navigate = Route.useNavigate() | ||
|
|
||
| return ( | ||
| <div data-testid="home-component"> | ||
| <button | ||
| data-testid="to-about-btn" | ||
| onClick={() => | ||
| navigate({ | ||
| to: '/about', | ||
| reloadDocument: true, | ||
| }) | ||
| } | ||
| > | ||
| Navigate to /about with document reload | ||
| </button> | ||
| </div> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { expect, test } from '@playwright/test' | ||
|
|
||
| test('navigate() respects basepath for when reloadDocument=true', async ({ | ||
| page, | ||
| }) => { | ||
| await page.goto(`/app/`) | ||
| await expect(page.getByTestId(`home-component`)).toBeInViewport() | ||
|
|
||
| const aboutBtn = page.getByTestId(`to-about-btn`) | ||
| await aboutBtn.click() | ||
| await page.waitForURL('/app/about') | ||
| await expect(page.getByTestId(`about-component`)).toBeInViewport() | ||
|
|
||
| const homeBtn = page.getByTestId(`to-home-btn`) | ||
| await homeBtn.click() | ||
| await page.waitForURL('/app/') | ||
| await expect(page.getByTestId(`home-component`)).toBeInViewport() | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import { e2eStartDummyServer } from '@tanstack/router-e2e-utils' | ||
| import packageJson from '../../package.json' with { type: 'json' } | ||
|
|
||
| export default async function setup() { | ||
| await e2eStartDummyServer(packageJson.name) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import { e2eStopDummyServer } from '@tanstack/router-e2e-utils' | ||
| import packageJson from '../../package.json' with { type: 'json' } | ||
|
|
||
| export default async function teardown() { | ||
| await e2eStopDummyServer(packageJson.name) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "strict": true, | ||
| "esModuleInterop": true, | ||
| "jsx": "preserve", | ||
| "jsxImportSource": "vue", | ||
| "target": "ESNext", | ||
| "moduleResolution": "Bundler", | ||
| "module": "ESNext", | ||
| "skipLibCheck": true, | ||
| "resolveJsonModule": true, | ||
| "allowJs": true, | ||
| "types": ["vite/client"] | ||
| }, | ||
| "exclude": ["node_modules", "dist"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { defineConfig } from 'vite' | ||
| import vue from '@vitejs/plugin-vue' | ||
| import vueJsx from '@vitejs/plugin-vue-jsx' | ||
| import { tanstackRouter } from '@tanstack/router-plugin/vite' | ||
|
|
||
| // https://vitejs.dev/config/ | ||
| export default defineConfig({ | ||
| base: '/app/', | ||
| plugins: [ | ||
| tanstackRouter({ | ||
| target: 'vue', | ||
| autoCodeSplitting: true, | ||
| }), | ||
| vue(), | ||
| vueJsx(), | ||
| ], | ||
| }) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-null assertion could fail if element is missing.
The non-null assertion (
!) assumes the#appelement always exists. If the element is missing from the HTML, this will cause a runtime error.Consider adding a null check:
📝 Committable suggestion
🤖 Prompt for AI Agents