@@ -2673,5 +2673,290 @@ test.describe("Prerendering", () => {
26732673 await page . waitForSelector ( "#target" ) ;
26742674 expect ( requests ) . toEqual ( [ "/redirect.data" ] ) ;
26752675 } ) ;
2676+
2677+ test ( "Navigates across SPA/prerender pages when starting from a SPA page (w/basename)" , async ( {
2678+ page,
2679+ } ) => {
2680+ fixture = await createFixture ( {
2681+ prerender : true ,
2682+ files : {
2683+ "react-router.config.ts" : reactRouterConfig ( {
2684+ ssr : false , // turn off fog of war since we're serving with a static server
2685+ prerender : [ "/page" ] ,
2686+ basename : "/base" ,
2687+ } ) ,
2688+ "vite.config.ts" : files [ "vite.config.ts" ] ,
2689+ "app/root.tsx" : js `
2690+ import * as React from "react";
2691+ import { Outlet, Scripts } from "react-router";
2692+
2693+ export function Layout({ children }) {
2694+ return (
2695+ <html lang="en">
2696+ <head />
2697+ <body>
2698+ {children}
2699+ <Scripts />
2700+ </body>
2701+ </html>
2702+ );
2703+ }
2704+
2705+ export default function Root({ loaderData }) {
2706+ return <Outlet />
2707+ }
2708+ ` ,
2709+ "app/routes/_index.tsx" : js `
2710+ import { Link } from 'react-router';
2711+ export default function Index() {
2712+ return <Link to="/page">Go to page</Link>
2713+ }
2714+ ` ,
2715+ "app/routes/page.tsx" : js `
2716+ import { Link, Form } from 'react-router';
2717+ export async function loader() {
2718+ return "PAGE DATA"
2719+ }
2720+ let count = 0;
2721+ export function clientAction() {
2722+ return "PAGE ACTION " + (++count)
2723+ }
2724+ export default function Page({ loaderData, actionData }) {
2725+ return (
2726+ <>
2727+ <p data-page>{loaderData}</p>
2728+ {actionData ? <p data-page-action>{actionData}</p> : null}
2729+ <Link to="/page2">Go to page2</Link>
2730+ <Form method="post" action="/page">
2731+ <button type="submit">Submit</button>
2732+ </Form>
2733+ <Form method="post" action="/page2">
2734+ <button type="submit">Submit /page2</button>
2735+ </Form>
2736+ </>
2737+ );
2738+ }
2739+ ` ,
2740+ "app/routes/page2.tsx" : js `
2741+ import { Form } from 'react-router';
2742+ export function clientLoader() {
2743+ return "PAGE2 DATA"
2744+ }
2745+ let count = 0;
2746+ export function clientAction() {
2747+ return "PAGE2 ACTION " + (++count)
2748+ }
2749+ export default function Page({ loaderData, actionData }) {
2750+ return (
2751+ <>
2752+ <p data-page2>{loaderData}</p>
2753+ {actionData ? <p data-page2-action>{actionData}</p> : null}
2754+ <Form method="post" action="/page">
2755+ <button type="submit">Submit</button>
2756+ </Form>
2757+ <Form method="post" action="/page2">
2758+ <button type="submit">Submit /page2</button>
2759+ </Form>
2760+ </>
2761+ );
2762+ }
2763+ ` ,
2764+ } ,
2765+ } ) ;
2766+ appFixture = await createAppFixture ( fixture ) ;
2767+
2768+ let requests = captureRequests ( page ) ;
2769+ let app = new PlaywrightFixture ( appFixture , page ) ;
2770+
2771+ await app . goto ( "/base" , true ) ;
2772+ await page . waitForSelector ( 'a[href="/base/page"]' ) ;
2773+
2774+ await app . clickLink ( "/base/page" ) ;
2775+ await page . waitForSelector ( "[data-page]" ) ;
2776+ expect ( await ( await page . $ ( "[data-page]" ) ) ?. innerText ( ) ) . toBe (
2777+ "PAGE DATA" ,
2778+ ) ;
2779+ expect ( requests ) . toEqual ( [ "/base/page.data" ] ) ;
2780+ clearRequests ( requests ) ;
2781+
2782+ await app . clickSubmitButton ( "/base/page" ) ;
2783+ await page . waitForSelector ( "[data-page-action]" ) ;
2784+ expect ( await ( await page . $ ( "[data-page-action]" ) ) ?. innerText ( ) ) . toBe (
2785+ "PAGE ACTION 1" ,
2786+ ) ;
2787+ // No revalidation after submission to self
2788+ expect ( requests ) . toEqual ( [ ] ) ;
2789+
2790+ await app . clickLink ( "/base/page2" ) ;
2791+ await page . waitForSelector ( "[data-page2]" ) ;
2792+ expect ( await ( await page . $ ( "[data-page2]" ) ) ?. innerText ( ) ) . toBe (
2793+ "PAGE2 DATA" ,
2794+ ) ;
2795+ expect ( requests ) . toEqual ( [ ] ) ;
2796+
2797+ await app . clickSubmitButton ( "/base/page2" ) ;
2798+ await page . waitForSelector ( "[data-page2-action]" ) ;
2799+ expect ( await ( await page . $ ( "[data-page2-action]" ) ) ?. innerText ( ) ) . toBe (
2800+ "PAGE2 ACTION 1" ,
2801+ ) ;
2802+ expect ( requests ) . toEqual ( [ ] ) ;
2803+
2804+ await app . clickSubmitButton ( "/base/page" ) ;
2805+ await page . waitForSelector ( "[data-page-action]" ) ;
2806+ expect ( await ( await page . $ ( "[data-page-action]" ) ) ?. innerText ( ) ) . toBe (
2807+ "PAGE ACTION 2" ,
2808+ ) ;
2809+ expect ( requests ) . toEqual ( [ "/base/page.data" ] ) ;
2810+ clearRequests ( requests ) ;
2811+
2812+ await app . clickSubmitButton ( "/base/page2" ) ;
2813+ await page . waitForSelector ( "[data-page2-action]" ) ;
2814+ expect ( await ( await page . $ ( "[data-page2-action]" ) ) ?. innerText ( ) ) . toBe (
2815+ "PAGE2 ACTION 2" ,
2816+ ) ;
2817+ expect ( requests ) . toEqual ( [ ] ) ;
2818+ } ) ;
2819+
2820+ test ( "Navigates across SPA/prerender pages when starting from a prerendered page (w/basename)" , async ( {
2821+ page,
2822+ } ) => {
2823+ fixture = await createFixture ( {
2824+ prerender : true ,
2825+ files : {
2826+ "react-router.config.ts" : reactRouterConfig ( {
2827+ ssr : false , // turn off fog of war since we're serving with a static server
2828+ prerender : [ "/" , "/page" ] ,
2829+ basename : "/base" ,
2830+ } ) ,
2831+ "vite.config.ts" : files [ "vite.config.ts" ] ,
2832+ "app/root.tsx" : js `
2833+ import * as React from "react";
2834+ import { Outlet, Scripts } from "react-router";
2835+
2836+ export function Layout({ children }) {
2837+ return (
2838+ <html lang="en">
2839+ <head />
2840+ <body>
2841+ {children}
2842+ <Scripts />
2843+ </body>
2844+ </html>
2845+ );
2846+ }
2847+
2848+ export default function Root({ loaderData }) {
2849+ return <Outlet />;
2850+ }
2851+ ` ,
2852+ "app/routes/_index.tsx" : js `
2853+ import { Link } from 'react-router';
2854+ export default function Index() {
2855+ return <Link to="/page">Go to page</Link>
2856+ }
2857+ ` ,
2858+ "app/routes/page.tsx" : js `
2859+ import { Link, Form } from 'react-router';
2860+ export async function loader() {
2861+ return "PAGE DATA"
2862+ }
2863+ let count = 0;
2864+ export function clientAction() {
2865+ return "PAGE ACTION " + (++count)
2866+ }
2867+ export default function Page({ loaderData, actionData }) {
2868+ return (
2869+ <>
2870+ <p data-page>{loaderData}</p>
2871+ {actionData ? <p data-page-action>{actionData}</p> : null}
2872+ <Link to="/page2">Go to page2</Link>
2873+ <Form method="post" action="/page">
2874+ <button type="submit">Submit</button>
2875+ </Form>
2876+ <Form method="post" action="/page2">
2877+ <button type="submit">Submit /page2</button>
2878+ </Form>
2879+ </>
2880+ );
2881+ }
2882+ ` ,
2883+ "app/routes/page2.tsx" : js `
2884+ import { Form } from 'react-router';
2885+ export function clientLoader() {
2886+ return "PAGE2 DATA"
2887+ }
2888+ let count = 0;
2889+ export function clientAction() {
2890+ return "PAGE2 ACTION " + (++count)
2891+ }
2892+ export default function Page({ loaderData, actionData }) {
2893+ return (
2894+ <>
2895+ <p data-page2>{loaderData}</p>
2896+ {actionData ? <p data-page2-action>{actionData}</p> : null}
2897+ <Form method="post" action="/page">
2898+ <button type="submit">Submit</button>
2899+ </Form>
2900+ <Form method="post" action="/page2">
2901+ <button type="submit">Submit /page2</button>
2902+ </Form>
2903+ </>
2904+ );
2905+ }
2906+ ` ,
2907+ } ,
2908+ } ) ;
2909+ appFixture = await createAppFixture ( fixture ) ;
2910+
2911+ let requests = captureRequests ( page ) ;
2912+ let app = new PlaywrightFixture ( appFixture , page ) ;
2913+ await app . goto ( "/base" , true ) ;
2914+ await page . waitForSelector ( 'a[href="/base/page"]' ) ;
2915+
2916+ await app . clickLink ( "/base/page" ) ;
2917+ await page . waitForSelector ( "[data-page]" ) ;
2918+ expect ( await ( await page . $ ( "[data-page]" ) ) ?. innerText ( ) ) . toBe (
2919+ "PAGE DATA" ,
2920+ ) ;
2921+ expect ( requests ) . toEqual ( [ "/base/page.data" ] ) ;
2922+ clearRequests ( requests ) ;
2923+
2924+ await app . clickSubmitButton ( "/base/page" ) ;
2925+ await page . waitForSelector ( "[data-page-action]" ) ;
2926+ expect ( await ( await page . $ ( "[data-page-action]" ) ) ?. innerText ( ) ) . toBe (
2927+ "PAGE ACTION 1" ,
2928+ ) ;
2929+ // No revalidation after submission to self
2930+ expect ( requests ) . toEqual ( [ ] ) ;
2931+
2932+ await app . clickLink ( "/base/page2" ) ;
2933+ await page . waitForSelector ( "[data-page2]" ) ;
2934+ expect ( await ( await page . $ ( "[data-page2]" ) ) ?. innerText ( ) ) . toBe (
2935+ "PAGE2 DATA" ,
2936+ ) ;
2937+ expect ( requests ) . toEqual ( [ ] ) ;
2938+
2939+ await app . clickSubmitButton ( "/base/page2" ) ;
2940+ await page . waitForSelector ( "[data-page2-action]" ) ;
2941+ expect ( await ( await page . $ ( "[data-page2-action]" ) ) ?. innerText ( ) ) . toBe (
2942+ "PAGE2 ACTION 1" ,
2943+ ) ;
2944+ expect ( requests ) . toEqual ( [ ] ) ;
2945+
2946+ await app . clickSubmitButton ( "/base/page" ) ;
2947+ await page . waitForSelector ( "[data-page-action]" ) ;
2948+ expect ( await ( await page . $ ( "[data-page-action]" ) ) ?. innerText ( ) ) . toBe (
2949+ "PAGE ACTION 2" ,
2950+ ) ;
2951+ expect ( requests ) . toEqual ( [ "/base/page.data" ] ) ;
2952+ clearRequests ( requests ) ;
2953+
2954+ await app . clickSubmitButton ( "/base/page2" ) ;
2955+ await page . waitForSelector ( "[data-page2-action]" ) ;
2956+ expect ( await ( await page . $ ( "[data-page2-action]" ) ) ?. innerText ( ) ) . toBe (
2957+ "PAGE2 ACTION 2" ,
2958+ ) ;
2959+ expect ( requests ) . toEqual ( [ ] ) ;
2960+ } ) ;
26762961 } ) ;
26772962} ) ;
0 commit comments