1
1
import fs from "node:fs" ;
2
2
import path from "node:path" ;
3
3
import { PassThrough } from "node:stream" ;
4
+ import type { Page } from "@playwright/test" ;
4
5
import { test , expect } from "@playwright/test" ;
5
6
6
7
import {
@@ -784,6 +785,20 @@ test.describe("Prerendering", () => {
784
785
} ) ;
785
786
786
787
test . describe ( "ssr: false" , ( ) => {
788
+ function captureRequests ( page : Page ) {
789
+ let requests : string [ ] = [ ] ;
790
+ page . on ( "request" , ( request ) => {
791
+ let url = new URL ( request . url ( ) ) ;
792
+ if (
793
+ url . pathname . endsWith ( ".data" ) ||
794
+ url . pathname . endsWith ( "__manifest" )
795
+ ) {
796
+ requests . push ( url . pathname + url . search ) ;
797
+ }
798
+ } ) ;
799
+ return requests ;
800
+ }
801
+
787
802
test ( "Errors on headers/action functions in any route" , async ( ) => {
788
803
let cwd = await createProject ( {
789
804
"react-router.config.ts" : reactRouterConfig ( {
@@ -979,14 +994,7 @@ test.describe("Prerendering", () => {
979
994
} ) ;
980
995
appFixture = await createAppFixture ( fixture ) ;
981
996
982
- let requests : string [ ] = [ ] ;
983
- page . on ( "request" , ( request ) => {
984
- let pathname = new URL ( request . url ( ) ) . pathname ;
985
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
986
- requests . push ( pathname ) ;
987
- }
988
- } ) ;
989
-
997
+ let requests = captureRequests ( page ) ;
990
998
let app = new PlaywrightFixture ( appFixture , page ) ;
991
999
await app . goto ( "/" ) ;
992
1000
await page . waitForSelector ( "[data-mounted]" ) ;
@@ -1048,7 +1056,7 @@ test.describe("Prerendering", () => {
1048
1056
) ;
1049
1057
} ) ;
1050
1058
1051
- test ( "Properly navigates across SPA/prerender pages when starting from a SPA page" , async ( {
1059
+ test ( "Navigates across SPA/prerender pages when starting from a SPA page" , async ( {
1052
1060
page,
1053
1061
} ) => {
1054
1062
fixture = await createFixture ( {
@@ -1138,14 +1146,7 @@ test.describe("Prerendering", () => {
1138
1146
} ) ;
1139
1147
appFixture = await createAppFixture ( fixture ) ;
1140
1148
1141
- let requests : string [ ] = [ ] ;
1142
- page . on ( "request" , ( request ) => {
1143
- let pathname = new URL ( request . url ( ) ) . pathname ;
1144
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
1145
- requests . push ( pathname ) ;
1146
- }
1147
- } ) ;
1148
-
1149
+ let requests = captureRequests ( page ) ;
1149
1150
let app = new PlaywrightFixture ( appFixture , page ) ;
1150
1151
await app . goto ( "/" , true ) ;
1151
1152
await page . waitForSelector ( 'a[href="/page"]' ) ;
@@ -1194,7 +1195,7 @@ test.describe("Prerendering", () => {
1194
1195
expect ( requests ) . toEqual ( [ "/page.data" , "/page.data" ] ) ;
1195
1196
} ) ;
1196
1197
1197
- test ( "Properly navigates across SPA/prerender pages when starting from a prerendered page" , async ( {
1198
+ test ( "Navigates across SPA/prerender pages when starting from a prerendered page" , async ( {
1198
1199
page,
1199
1200
} ) => {
1200
1201
fixture = await createFixture ( {
@@ -1284,14 +1285,7 @@ test.describe("Prerendering", () => {
1284
1285
} ) ;
1285
1286
appFixture = await createAppFixture ( fixture ) ;
1286
1287
1287
- let requests : string [ ] = [ ] ;
1288
- page . on ( "request" , ( request ) => {
1289
- let pathname = new URL ( request . url ( ) ) . pathname ;
1290
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
1291
- requests . push ( pathname ) ;
1292
- }
1293
- } ) ;
1294
-
1288
+ let requests = captureRequests ( page ) ;
1295
1289
let app = new PlaywrightFixture ( appFixture , page ) ;
1296
1290
await app . goto ( "/" , true ) ;
1297
1291
await page . waitForSelector ( 'a[href="/page"]' ) ;
@@ -1340,7 +1334,7 @@ test.describe("Prerendering", () => {
1340
1334
expect ( requests ) . toEqual ( [ "/page.data" , "/page.data" ] ) ;
1341
1335
} ) ;
1342
1336
1343
- test ( "Properly navigates across SPA/prerender pages when starting from a SPA page and a root loader exists" , async ( {
1337
+ test ( "Navigates across SPA/prerender pages when starting from a SPA page and a root loader exists" , async ( {
1344
1338
page,
1345
1339
} ) => {
1346
1340
fixture = await createFixture ( {
@@ -1439,14 +1433,7 @@ test.describe("Prerendering", () => {
1439
1433
} ) ;
1440
1434
appFixture = await createAppFixture ( fixture ) ;
1441
1435
1442
- let requests : string [ ] = [ ] ;
1443
- page . on ( "request" , ( request ) => {
1444
- let pathname = new URL ( request . url ( ) ) . pathname ;
1445
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
1446
- requests . push ( pathname ) ;
1447
- }
1448
- } ) ;
1449
-
1436
+ let requests = captureRequests ( page ) ;
1450
1437
let app = new PlaywrightFixture ( appFixture , page ) ;
1451
1438
await app . goto ( "/" , true ) ;
1452
1439
await page . waitForSelector ( "[data-root]" ) ;
@@ -1498,7 +1485,7 @@ test.describe("Prerendering", () => {
1498
1485
expect ( requests ) . toEqual ( [ "/page.data" , "/page.data" ] ) ;
1499
1486
} ) ;
1500
1487
1501
- test ( "Properly navigates across SPA/prerender pages when starting from a prerendered page and a root loader exists" , async ( {
1488
+ test ( "Navigates across SPA/prerender pages when starting from a prerendered page and a root loader exists" , async ( {
1502
1489
page,
1503
1490
} ) => {
1504
1491
fixture = await createFixture ( {
@@ -1597,14 +1584,7 @@ test.describe("Prerendering", () => {
1597
1584
} ) ;
1598
1585
appFixture = await createAppFixture ( fixture ) ;
1599
1586
1600
- let requests : string [ ] = [ ] ;
1601
- page . on ( "request" , ( request ) => {
1602
- let pathname = new URL ( request . url ( ) ) . pathname ;
1603
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
1604
- requests . push ( pathname ) ;
1605
- }
1606
- } ) ;
1607
-
1587
+ let requests = captureRequests ( page ) ;
1608
1588
let app = new PlaywrightFixture ( appFixture , page ) ;
1609
1589
await app . goto ( "/" , true ) ;
1610
1590
await page . waitForSelector ( "[data-root]" ) ;
@@ -1656,7 +1636,7 @@ test.describe("Prerendering", () => {
1656
1636
expect ( requests ) . toEqual ( [ "/page.data" , "/page.data" ] ) ;
1657
1637
} ) ;
1658
1638
1659
- test ( "Properly navigates between prerendered parent and child SPA route" , async ( {
1639
+ test ( "Navigates between prerendered parent and child SPA route" , async ( {
1660
1640
page,
1661
1641
} ) => {
1662
1642
fixture = await createFixture ( {
@@ -1743,14 +1723,7 @@ test.describe("Prerendering", () => {
1743
1723
} ) ;
1744
1724
appFixture = await createAppFixture ( fixture ) ;
1745
1725
1746
- let requests : string [ ] = [ ] ;
1747
- page . on ( "request" , ( request ) => {
1748
- let pathname = new URL ( request . url ( ) ) . pathname ;
1749
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
1750
- requests . push ( pathname ) ;
1751
- }
1752
- } ) ;
1753
-
1726
+ let requests = captureRequests ( page ) ;
1754
1727
let app = new PlaywrightFixture ( appFixture , page ) ;
1755
1728
await app . goto ( "/parent" , true ) ;
1756
1729
await expect ( page . getByText ( "PARENT DATA" ) ) . toBeVisible ( ) ;
@@ -1796,7 +1769,7 @@ test.describe("Prerendering", () => {
1796
1769
expect ( requests ) . toEqual ( [ ] ) ;
1797
1770
} ) ;
1798
1771
1799
- test ( "Properly navigates between SPA parent and prerendered child route" , async ( {
1772
+ test ( "Navigates between SPA parent and prerendered child route" , async ( {
1800
1773
page,
1801
1774
} ) => {
1802
1775
fixture = await createFixture ( {
@@ -1880,14 +1853,7 @@ test.describe("Prerendering", () => {
1880
1853
} ) ;
1881
1854
appFixture = await createAppFixture ( fixture ) ;
1882
1855
1883
- let requests : string [ ] = [ ] ;
1884
- page . on ( "request" , ( request ) => {
1885
- let pathname = new URL ( request . url ( ) ) . pathname ;
1886
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
1887
- requests . push ( pathname ) ;
1888
- }
1889
- } ) ;
1890
-
1856
+ let requests = captureRequests ( page ) ;
1891
1857
let app = new PlaywrightFixture ( appFixture , page ) ;
1892
1858
await app . goto ( "/parent" , true ) ;
1893
1859
await expect ( page . getByText ( "PARENT DATA" ) ) . toBeVisible ( ) ;
@@ -1911,7 +1877,7 @@ test.describe("Prerendering", () => {
1911
1877
1912
1878
// Initial navigation and submission from /parent
1913
1879
expect ( requests ) . toEqual ( [ "/parent/child.data" , "/parent/child.data" ] ) ;
1914
- requests = [ ] ;
1880
+ while ( requests . length ) requests . pop ( ) ;
1915
1881
1916
1882
await app . goto ( "/parent/child" , true ) ;
1917
1883
await expect ( page . getByText ( "PARENT DATA" ) ) . toBeVisible ( ) ;
@@ -1935,7 +1901,7 @@ test.describe("Prerendering", () => {
1935
1901
expect ( requests ) . toEqual ( [ "/parent/child.data" ] ) ;
1936
1902
} ) ;
1937
1903
1938
- test ( "Properly navigates between prerendered parent and child SPA route (with a root loader)" , async ( {
1904
+ test ( "Navigates between prerendered parent and child SPA route (with a root loader)" , async ( {
1939
1905
page,
1940
1906
} ) => {
1941
1907
fixture = await createFixture ( {
@@ -2035,14 +2001,7 @@ test.describe("Prerendering", () => {
2035
2001
} ) ;
2036
2002
appFixture = await createAppFixture ( fixture ) ;
2037
2003
2038
- let requests : string [ ] = [ ] ;
2039
- page . on ( "request" , ( request ) => {
2040
- let pathname = new URL ( request . url ( ) ) . pathname ;
2041
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
2042
- requests . push ( pathname ) ;
2043
- }
2044
- } ) ;
2045
-
2004
+ let requests = captureRequests ( page ) ;
2046
2005
let app = new PlaywrightFixture ( appFixture , page ) ;
2047
2006
await app . goto ( "/parent" , true ) ;
2048
2007
await expect ( page . getByText ( "ROOT DATA" ) ) . toBeVisible ( ) ;
@@ -2090,7 +2049,7 @@ test.describe("Prerendering", () => {
2090
2049
expect ( requests ) . toEqual ( [ ] ) ;
2091
2050
} ) ;
2092
2051
2093
- test ( "Properly navigates between SPA parent and prerendered child route (with a root loader)" , async ( {
2052
+ test ( "Navigates between SPA parent and prerendered child route (with a root loader)" , async ( {
2094
2053
page,
2095
2054
} ) => {
2096
2055
fixture = await createFixture ( {
@@ -2183,14 +2142,7 @@ test.describe("Prerendering", () => {
2183
2142
} ) ;
2184
2143
appFixture = await createAppFixture ( fixture ) ;
2185
2144
2186
- let requests : string [ ] = [ ] ;
2187
- page . on ( "request" , ( request ) => {
2188
- let pathname = new URL ( request . url ( ) ) . pathname ;
2189
- if ( pathname . endsWith ( ".data" ) || pathname . endsWith ( "__manifest" ) ) {
2190
- requests . push ( pathname ) ;
2191
- }
2192
- } ) ;
2193
-
2145
+ let requests = captureRequests ( page ) ;
2194
2146
let app = new PlaywrightFixture ( appFixture , page ) ;
2195
2147
await app . goto ( "/parent" , true ) ;
2196
2148
await expect ( page . getByText ( "ROOT DATA" ) ) . toBeVisible ( ) ;
@@ -2215,7 +2167,7 @@ test.describe("Prerendering", () => {
2215
2167
2216
2168
// Initial navigation and submission from /parent
2217
2169
expect ( requests ) . toEqual ( [ "/parent/child.data" , "/parent/child.data" ] ) ;
2218
- requests = [ ] ;
2170
+ while ( requests . length ) requests . pop ( ) ;
2219
2171
2220
2172
await app . goto ( "/parent/child" , true ) ;
2221
2173
await expect ( page . getByText ( "PARENT DATA" ) ) . toBeVisible ( ) ;
@@ -2239,6 +2191,77 @@ test.describe("Prerendering", () => {
2239
2191
expect ( requests ) . toEqual ( [ "/parent/child.data" ] ) ;
2240
2192
} ) ;
2241
2193
2194
+ test ( "Navigates to prerendered parent with clientLoader calling loader" , async ( {
2195
+ page,
2196
+ } ) => {
2197
+ fixture = await createFixture ( {
2198
+ prerender : true ,
2199
+ files : {
2200
+ "react-router.config.ts" : reactRouterConfig ( {
2201
+ ssr : false ,
2202
+ prerender : [ "/" , "/parent" ] ,
2203
+ } ) ,
2204
+ "vite.config.ts" : files [ "vite.config.ts" ] ,
2205
+ "app/root.tsx" : js `
2206
+ import * as React from "react";
2207
+ import { Link, Outlet, Scripts } from "react-router";
2208
+
2209
+ export function Layout({ children }) {
2210
+ return (
2211
+ <html lang="en">
2212
+ <head />
2213
+ <body>
2214
+ {children}
2215
+ <Scripts />
2216
+ </body>
2217
+ </html>
2218
+ );
2219
+ }
2220
+
2221
+ export default function Root({ loaderData }) {
2222
+ return (
2223
+ <>
2224
+ <Link to="/parent">Go to parent</Link>
2225
+ <Outlet/>
2226
+ </>
2227
+ );
2228
+ }
2229
+
2230
+ export function HydrateFallback() {
2231
+ return <p>Loading...</p>;
2232
+ }
2233
+ ` ,
2234
+ "app/routes/parent.tsx" : js `
2235
+ import { Link, Form, Outlet } from 'react-router';
2236
+ export async function loader() {
2237
+ return "PARENT DATA"
2238
+ }
2239
+ export async function clientLoader({ serverLoader }) {
2240
+ let str = await serverLoader();
2241
+ return str + " - CLIENT"
2242
+ }
2243
+ export function clientAction() {
2244
+ return "PARENT ACTION"
2245
+ }
2246
+ export default function Parent({ loaderData, actionData }) {
2247
+ return <p data-parent>{loaderData}</p>;
2248
+ }
2249
+ ` ,
2250
+ } ,
2251
+ } ) ;
2252
+ appFixture = await createAppFixture ( fixture ) ;
2253
+
2254
+ let requests = captureRequests ( page ) ;
2255
+ let app = new PlaywrightFixture ( appFixture , page ) ;
2256
+ await app . goto ( "/" , true ) ;
2257
+ await expect ( page . getByText ( "Go to parent" ) ) . toBeVisible ( ) ;
2258
+
2259
+ await app . clickLink ( "/parent" ) ;
2260
+ await expect ( page . getByText ( "PARENT DATA - CLIENT" ) ) . toBeVisible ( ) ;
2261
+
2262
+ expect ( requests ) . toEqual ( [ "/parent.data?_routes=routes%2Fparent" ] ) ;
2263
+ } ) ;
2264
+
2242
2265
test ( "Handles 404s on data requests" , async ( { page } ) => {
2243
2266
fixture = await createFixture ( {
2244
2267
prerender : true ,
@@ -2266,14 +2289,7 @@ test.describe("Prerendering", () => {
2266
2289
} ) ;
2267
2290
appFixture = await createAppFixture ( fixture ) ;
2268
2291
2269
- let requests : string [ ] = [ ] ;
2270
- page . on ( "request" , ( request ) => {
2271
- let pathname = new URL ( request . url ( ) ) . pathname ;
2272
- if ( pathname . endsWith ( ".data" ) ) {
2273
- requests . push ( pathname ) ;
2274
- }
2275
- } ) ;
2276
-
2292
+ let requests = captureRequests ( page ) ;
2277
2293
let app = new PlaywrightFixture ( appFixture , page ) ;
2278
2294
await app . goto ( "/" ) ;
2279
2295
await page . waitForSelector ( "[data-mounted]" ) ;
0 commit comments