@@ -2673,5 +2673,290 @@ test.describe("Prerendering", () => {
2673
2673
await page . waitForSelector ( "#target" ) ;
2674
2674
expect ( requests ) . toEqual ( [ "/redirect.data" ] ) ;
2675
2675
} ) ;
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
+ } ) ;
2676
2961
} ) ;
2677
2962
} ) ;
0 commit comments