@@ -4476,4 +4476,197 @@ test.describe("single-fetch", () => {
44764476 await page . waitForSelector ( "h1" ) ;
44774477 expect ( await app . getHtml ( "h1" ) ) . toMatch ( "It worked!" ) ;
44784478 } ) ;
4479+
4480+ test ( "always uses /{path}.data without future.unstable_trailingSlashAwareDataRequests flag" , async ( {
4481+ page,
4482+ } ) => {
4483+ let fixture = await createFixture ( {
4484+ files : {
4485+ ...files ,
4486+ "app/routes/_index.tsx" : js `
4487+ import { Link } from "react-router";
4488+
4489+ export default function Index() {
4490+ return (
4491+ <div>
4492+ <h1>Home</h1>
4493+ <Link to="/about/">Go to About (with trailing slash)</Link>
4494+ <Link to="/about">Go to About (without trailing slash)</Link>
4495+ </div>
4496+ );
4497+ }
4498+ ` ,
4499+ "app/routes/about.tsx" : js `
4500+ import { Link, useLoaderData } from "react-router";
4501+
4502+ export function loader({ request }) {
4503+ let url = new URL(request.url);
4504+ return {
4505+ pathname: url.pathname,
4506+ hasTrailingSlash: url.pathname.endsWith("/"),
4507+ };
4508+ }
4509+
4510+ export default function About() {
4511+ let { pathname, hasTrailingSlash } = useLoaderData();
4512+ return (
4513+ <div>
4514+ <h1>About</h1>
4515+ <p id="pathname">{pathname}</p>
4516+ <p id="trailing-slash">{String(hasTrailingSlash)}</p>
4517+ <Link to="/">Go back home</Link>
4518+ </div>
4519+ );
4520+ }
4521+ ` ,
4522+ } ,
4523+ } ) ;
4524+ let appFixture = await createAppFixture ( fixture ) ;
4525+ let app = new PlaywrightFixture ( appFixture , page ) ;
4526+
4527+ let requests : string [ ] = [ ] ;
4528+ page . on ( "request" , ( req ) => {
4529+ let url = new URL ( req . url ( ) ) ;
4530+ if ( url . pathname . endsWith ( ".data" ) ) {
4531+ requests . push ( url . pathname + url . search ) ;
4532+ }
4533+ } ) ;
4534+
4535+ // Document load without trailing slash
4536+ await app . goto ( "/about" ) ;
4537+ await page . waitForSelector ( "#pathname" ) ;
4538+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about" ) ;
4539+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "false" ) ;
4540+
4541+ // Client-side navigation without trailing slash
4542+ await app . goto ( "/" ) ;
4543+ await app . clickLink ( "/about" ) ;
4544+ await page . waitForSelector ( "#pathname" ) ;
4545+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about" ) ;
4546+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "false" ) ;
4547+ expect ( requests ) . toEqual ( [ "/about.data" ] ) ;
4548+ requests = [ ] ;
4549+
4550+ // Document load with trailing slash
4551+ await app . goto ( "/about/" ) ;
4552+ await page . waitForSelector ( "#pathname" ) ;
4553+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about/" ) ;
4554+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "true" ) ;
4555+
4556+ // Client-side navigation with trailing slash
4557+ await app . goto ( "/" ) ;
4558+ await app . clickLink ( "/about/" ) ;
4559+ await page . waitForSelector ( "#pathname" ) ;
4560+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about" ) ;
4561+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "false" ) ;
4562+ expect ( requests ) . toEqual ( [ "/about.data" ] ) ;
4563+ requests = [ ] ;
4564+
4565+ // Client-side navigation back to /
4566+ await app . clickLink ( "/" ) ;
4567+ await page . waitForSelector ( "h1:has-text('Home')" ) ;
4568+ expect ( requests ) . toEqual ( [ "/_root.data" ] ) ;
4569+ requests = [ ] ;
4570+ } ) ;
4571+
4572+ test ( "uses {path}.data or {path}/_.data depending on trailing slash with future.unstable_trailingSlashAwareDataRequests flag" , async ( {
4573+ page,
4574+ } ) => {
4575+ let fixture = await createFixture ( {
4576+ files : {
4577+ ...files ,
4578+ "react-router.config.ts" : js `
4579+ import type { Config } from "@react-router/dev/config";
4580+
4581+ export default {
4582+ future: {
4583+ unstable_trailingSlashAwareDataRequests: true,
4584+ }
4585+ } satisfies Config;
4586+ ` ,
4587+ "app/routes/_index.tsx" : js `
4588+ import { Link } from "react-router";
4589+
4590+ export default function Index() {
4591+ return (
4592+ <div>
4593+ <h1>Home</h1>
4594+ <Link to="/about/">Go to About (with trailing slash)</Link>
4595+ <Link to="/about">Go to About (without trailing slash)</Link>
4596+ </div>
4597+ );
4598+ }
4599+ ` ,
4600+ "app/routes/about.tsx" : js `
4601+ import { Link, useLoaderData } from "react-router";
4602+
4603+ export function loader({ request }) {
4604+ let url = new URL(request.url);
4605+ return {
4606+ pathname: url.pathname,
4607+ hasTrailingSlash: url.pathname.endsWith("/"),
4608+ };
4609+ }
4610+
4611+ export default function About() {
4612+ let { pathname, hasTrailingSlash } = useLoaderData();
4613+ return (
4614+ <div>
4615+ <h1>About</h1>
4616+ <p id="pathname">{pathname}</p>
4617+ <p id="trailing-slash">{String(hasTrailingSlash)}</p>
4618+ <Link to="/">Go back home</Link>
4619+ </div>
4620+ );
4621+ }
4622+ ` ,
4623+ } ,
4624+ } ) ;
4625+ let appFixture = await createAppFixture ( fixture ) ;
4626+ let app = new PlaywrightFixture ( appFixture , page ) ;
4627+
4628+ let requests : string [ ] = [ ] ;
4629+ page . on ( "request" , ( req ) => {
4630+ let url = new URL ( req . url ( ) ) ;
4631+ if ( url . pathname . endsWith ( ".data" ) ) {
4632+ requests . push ( url . pathname + url . search ) ;
4633+ }
4634+ } ) ;
4635+
4636+ // Document load without trailing slash
4637+ await app . goto ( "/about" ) ;
4638+ await page . waitForSelector ( "#pathname" ) ;
4639+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about" ) ;
4640+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "false" ) ;
4641+
4642+ // Client-side navigation without trailing slash
4643+ await app . goto ( "/" ) ;
4644+ await app . clickLink ( "/about" ) ;
4645+ await page . waitForSelector ( "#pathname" ) ;
4646+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about" ) ;
4647+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "false" ) ;
4648+ expect ( requests ) . toEqual ( [ "/about.data" ] ) ;
4649+ requests = [ ] ;
4650+
4651+ // Document load with trailing slash
4652+ await app . goto ( "/about/" ) ;
4653+ await page . waitForSelector ( "#pathname" ) ;
4654+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about/" ) ;
4655+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "true" ) ;
4656+
4657+ // Client-side navigation with trailing slash
4658+ await app . goto ( "/" ) ;
4659+ await app . clickLink ( "/about/" ) ;
4660+ await page . waitForSelector ( "#pathname" ) ;
4661+ expect ( await page . locator ( "#pathname" ) . innerText ( ) ) . toEqual ( "/about/" ) ;
4662+ expect ( await page . locator ( "#trailing-slash" ) . innerText ( ) ) . toEqual ( "true" ) ;
4663+ expect ( requests ) . toEqual ( [ "/about/_.data" ] ) ;
4664+ requests = [ ] ;
4665+
4666+ // Client-side navigation back to /
4667+ await app . clickLink ( "/" ) ;
4668+ await page . waitForSelector ( "h1:has-text('Home')" ) ;
4669+ expect ( requests ) . toEqual ( [ "/_.data" ] ) ;
4670+ requests = [ ] ;
4671+ } ) ;
44794672} ) ;
0 commit comments