@@ -435,6 +435,17 @@ implementations.forEach((implementation) => {
435435                        } 
436436                      ] 
437437                    }, 
438+                     { 
439+                       id: "throw-external-redirect-server-action", 
440+                       path: "throw-external-redirect-server-action", 
441+                       children: [ 
442+                         { 
443+                           id: "throw-external-redirect-server-action.home", 
444+                           index: true, 
445+                           lazy: () => import("./routes/throw-external-redirect-server-action/home"), 
446+                         } 
447+                       ] 
448+                     }, 
438449                    { 
439450                      id: "side-effect-redirect-server-action", 
440451                      path: "side-effect-redirect-server-action", 
@@ -446,6 +457,17 @@ implementations.forEach((implementation) => {
446457                        } 
447458                      ] 
448459                    }, 
460+                     { 
461+                       id: "side-effect-external-redirect-server-action", 
462+                       path: "side-effect-external-redirect-server-action", 
463+                       children: [ 
464+                         { 
465+                           id: "side-effect-external-redirect-server-action.home", 
466+                           index: true, 
467+                           lazy: () => import("./routes/side-effect-external-redirect-server-action/home"), 
468+                         } 
469+                       ] 
470+                     }, 
449471                    { 
450472                      id: "server-function-reference", 
451473                      path: "server-function-reference", 
@@ -986,6 +1008,82 @@ implementations.forEach((implementation) => {
9861008                ); 
9871009              } 
9881010            ` , 
1011+             "src/routes/throw-external-redirect-server-action/home.actions.ts" : js ` 
1012+               "use server"; 
1013+               import { redirect } from "react-router"; 
1014+ 
1015+               export async function redirectAction(formData: FormData) { 
1016+                 // Throw a redirect to an external URL 
1017+                 throw redirect("https://example.com/"); 
1018+               } 
1019+             ` , 
1020+             "src/routes/throw-external-redirect-server-action/home.client.tsx" : js ` 
1021+               "use client"; 
1022+ 
1023+               import { useState } from "react"; 
1024+ 
1025+               export function Counter() { 
1026+                 const [count, setCount] = useState(0); 
1027+                 return <button type="button" onClick={() => setCount(c => c + 1)} data-count>Count: {count}</button>; 
1028+               } 
1029+             ` , 
1030+             "src/routes/throw-external-redirect-server-action/home.tsx" : js ` 
1031+               import { redirectAction } from "./home.actions"; 
1032+               import { Counter } from "./home.client"; 
1033+ 
1034+               export default function HomeRoute(props) { 
1035+                 return ( 
1036+                   <div> 
1037+                     <form action={redirectAction}> 
1038+                       <button type="submit" data-submit> 
1039+                         Redirect via Server Function 
1040+                       </button> 
1041+                     </form> 
1042+                     <Counter /> 
1043+                   </div> 
1044+                 ); 
1045+               } 
1046+             ` , 
1047+             "src/routes/side-effect-external-redirect-server-action/home.actions.ts" : js ` 
1048+               "use server"; 
1049+               import { redirect } from "react-router"; 
1050+ 
1051+               export async function redirectAction() { 
1052+                 // Perform a side-effect redirect to an external URL 
1053+                 redirect("https://example.com/", { headers: { "x-test": "test" } }); 
1054+                 return "redirected"; 
1055+               } 
1056+             ` , 
1057+             "src/routes/side-effect-external-redirect-server-action/home.client.tsx" : js ` 
1058+               "use client"; 
1059+               import { useState } from "react"; 
1060+ 
1061+               export function Counter() { 
1062+                 const [count, setCount] = useState(0); 
1063+                 return <button type="button" onClick={() => setCount(c => c + 1)} data-count>Count: {count}</button>; 
1064+               } 
1065+             ` , 
1066+             "src/routes/side-effect-external-redirect-server-action/home.tsx" : js ` 
1067+               "use client"; 
1068+               import {useActionState} from "react"; 
1069+               import { redirectAction } from "./home.actions"; 
1070+               import { Counter } from "./home.client"; 
1071+ 
1072+               export default function HomeRoute(props) { 
1073+                 const [state, action] = useActionState(redirectAction, null); 
1074+                 return ( 
1075+                   <div> 
1076+                     <form action={action}> 
1077+                       <button type="submit" data-submit> 
1078+                         Redirect via Server Function 
1079+                       </button> 
1080+                     </form> 
1081+                     {state && <div data-testid="state">{state}</div>} 
1082+                     <Counter /> 
1083+                   </div> 
1084+                 ); 
1085+               } 
1086+             ` , 
9891087
9901088            "src/routes/server-function-reference/home.actions.ts" : js ` 
9911089              "use server"; 
@@ -1736,6 +1834,33 @@ implementations.forEach((implementation) => {
17361834          validateRSCHtml ( await  page . content ( ) ) ; 
17371835        } ) ; 
17381836
1837+         test ( "Supports React Server Functions thrown external redirects" ,  async  ( { 
1838+           page, 
1839+         } )  =>  { 
1840+           // Test is expected to fail currently — skip running it 
1841+           // test.skip(true, "Known failing test for external redirect behavior"); 
1842+ 
1843+           await  page . goto ( 
1844+             `http://localhost:${ port }  /throw-external-redirect-server-action/` , 
1845+           ) ; 
1846+ 
1847+           // Verify initial server render 
1848+           await  page . waitForSelector ( "[data-count]" ) ; 
1849+           expect ( await  page . locator ( "[data-count]" ) . textContent ( ) ) . toBe ( 
1850+             "Count: 0" , 
1851+           ) ; 
1852+           await  page . click ( "[data-count]" ) ; 
1853+           expect ( await  page . locator ( "[data-count]" ) . textContent ( ) ) . toBe ( 
1854+             "Count: 1" , 
1855+           ) ; 
1856+ 
1857+           // Submit the form to trigger server function redirect to external URL 
1858+           await  page . click ( "[data-submit]" ) ; 
1859+ 
1860+           // We expect the browser to navigate to the external site (example.com) 
1861+           await  expect ( page ) . toHaveURL ( `https://example.com/` ) ; 
1862+         } ) ; 
1863+ 
17391864        test ( "Supports React Server Functions side-effect redirects" ,  async  ( { 
17401865          page, 
17411866        } )  =>  { 
@@ -1789,6 +1914,46 @@ implementations.forEach((implementation) => {
17891914          validateRSCHtml ( await  page . content ( ) ) ; 
17901915        } ) ; 
17911916
1917+         test ( "Supports React Server Functions side-effect external redirects" ,  async  ( { 
1918+           page, 
1919+         } )  =>  { 
1920+           // Test is expected to fail currently — skip running it 
1921+           test . skip ( implementation . name  ===  "parcel" ,  "Not working in parcel?" ) ; 
1922+ 
1923+           await  page . goto ( 
1924+             `http://localhost:${ port }  /side-effect-external-redirect-server-action` , 
1925+           ) ; 
1926+ 
1927+           // Verify initial server render 
1928+           await  page . waitForSelector ( "[data-count]" ) ; 
1929+           expect ( await  page . locator ( "[data-count]" ) . textContent ( ) ) . toBe ( 
1930+             "Count: 0" , 
1931+           ) ; 
1932+           await  page . click ( "[data-count]" ) ; 
1933+           expect ( await  page . locator ( "[data-count]" ) . textContent ( ) ) . toBe ( 
1934+             "Count: 1" , 
1935+           ) ; 
1936+ 
1937+           const  responseHeadersPromise  =  new  Promise < Record < string ,  string > > ( 
1938+             ( resolve )  =>  { 
1939+               page . addListener ( "response" ,  ( response )  =>  { 
1940+                 if  ( response . request ( ) . method ( )  ===  "POST" )  { 
1941+                   resolve ( response . headers ( ) ) ; 
1942+                 } 
1943+               } ) ; 
1944+             } , 
1945+           ) ; 
1946+ 
1947+           // Submit the form to trigger server function redirect to external URL 
1948+           await  page . click ( "[data-submit]" ) ; 
1949+ 
1950+           // We expect the browser to navigate to the external site (example.com) 
1951+           await  expect ( page ) . toHaveURL ( `https://example.com/` ) ; 
1952+ 
1953+           // Optionally assert that the server sent the header 
1954+           expect ( ( await  responseHeadersPromise ) [ "x-test" ] ) . toBe ( "test" ) ; 
1955+         } ) ; 
1956+ 
17921957        test ( "Supports React Server Function References" ,  async  ( {  page } )  =>  { 
17931958          await  page . goto ( `http://localhost:${ port }  /server-function-reference` ) ; 
17941959
0 commit comments