import { test, expect, Page } from '@playwright/test'; import AxeBuilder from '@axe-core/playwright'; import path from 'path'; const INLINE = path.resolve(__dirname, '../examples/routing-spa-fallback-inline.html'); const FILE = path.resolve(__dirname, '../examples/routing-spa-fallback-file.html'); const PAGES: Record = { '/spa-file/pages/index.tpl': '

Index from file

', '/spa-file/pages/about.tpl': '

About from file

', '/spa-file/pages/p/hello.tpl': '

Hello from file

', }; // SPA fallback server: known .tpl files are served, every other URL under the // base answers 200 with the app's index.html (like try_files ... /index.html). async function spaServer(page: Page, base: string, fixture: string) { const tplRequests: string[] = []; await page.route(new RegExp('^[^?#]*' + base + '(/|$)'), (route) => { const { pathname } = new URL(route.request().url()); if (pathname.endsWith('.tpl')) tplRequests.push(pathname); if (PAGES[pathname]) return route.fulfill({ body: PAGES[pathname], contentType: 'text/html' }); return route.fulfill({ path: fixture, contentType: 'text/html' }); }); return tplRequests; } test.describe('Routing — inline routes behind an SPA fallback', () => { test('1 — Boot makes no template requests for inline routes', async ({ page }) => { const tpl = await spaServer(page, '/spa-inline', INLINE); await page.goto('/spa-inline/'); await expect(page.getByTestId('page-home')).toBeVisible(); await page.waitForLoadState('networkidle'); // Only the link with no inline route (/nope) may resolve to a file; // /about and /p/hello are covered by