@@ -630,6 +630,10 @@ function setup({
630
630
let popHref = history . createHref ( history . location ) ;
631
631
if ( currentRouter ?. basename ) {
632
632
popHref = stripBasename ( popHref , currentRouter . basename ) as string ;
633
+ invariant (
634
+ popHref ,
635
+ "href passed to navigate should start with basename"
636
+ ) ;
633
637
}
634
638
helpers = getNavigationHelpers ( popHref , navigationId ) ;
635
639
unsubscribe ( ) ;
@@ -645,6 +649,10 @@ function setup({
645
649
let navHref = href ;
646
650
if ( currentRouter . basename ) {
647
651
navHref = stripBasename ( navHref , currentRouter . basename ) as string ;
652
+ invariant (
653
+ navHref ,
654
+ "href passed to t.navigate() should start with basename"
655
+ ) ;
648
656
}
649
657
helpers = getNavigationHelpers ( navHref , navigationId ) ;
650
658
shims ?. forEach ( ( routeId ) =>
@@ -6293,6 +6301,56 @@ describe("a router", () => {
6293
6301
} ) ;
6294
6302
} ) ;
6295
6303
6304
+ it ( "properly handles same-origin absolute URLs when using a basename" , async ( ) => {
6305
+ let t = setup ( { routes : REDIRECT_ROUTES , basename : "/base" } ) ;
6306
+
6307
+ let A = await t . navigate ( "/base/parent/child" , {
6308
+ formMethod : "post" ,
6309
+ formData : createFormData ( { } ) ,
6310
+ } ) ;
6311
+
6312
+ let B = await A . actions . child . redirectReturn (
6313
+ "http://localhost/base/parent" ,
6314
+ undefined ,
6315
+ undefined ,
6316
+ [ "parent" ]
6317
+ ) ;
6318
+ await B . loaders . parent . resolve ( "PARENT" ) ;
6319
+ expect ( t . router . state . location ) . toMatchObject ( {
6320
+ hash : "" ,
6321
+ pathname : "/base/parent" ,
6322
+ search : "" ,
6323
+ state : {
6324
+ _isRedirect : true ,
6325
+ } ,
6326
+ } ) ;
6327
+ } ) ;
6328
+
6329
+ it ( "treats same-origin absolute URLs as external if they don't match the basename" , async ( ) => {
6330
+ // This is gross, don't blame me, blame SO :)
6331
+ // https://stackoverflow.com/a/60697570
6332
+ let oldLocation = window . location ;
6333
+ const location = new URL ( window . location . href ) as unknown as Location ;
6334
+ location . assign = jest . fn ( ) ;
6335
+ location . replace = jest . fn ( ) ;
6336
+ delete ( window as any ) . location ;
6337
+ window . location = location as unknown as Location ;
6338
+
6339
+ let t = setup ( { routes : REDIRECT_ROUTES , basename : "/base" } ) ;
6340
+
6341
+ let A = await t . navigate ( "/base/parent/child" , {
6342
+ formMethod : "post" ,
6343
+ formData : createFormData ( { } ) ,
6344
+ } ) ;
6345
+
6346
+ let url = "http://localhost/not/the/same/basename" ;
6347
+ await A . actions . child . redirectReturn ( url ) ;
6348
+ expect ( window . location . assign ) . toHaveBeenCalledWith ( url ) ;
6349
+ expect ( window . location . replace ) . not . toHaveBeenCalled ( ) ;
6350
+
6351
+ window . location = oldLocation ;
6352
+ } ) ;
6353
+
6296
6354
describe ( "redirect status code handling" , ( ) => {
6297
6355
it ( "should not treat 300 as a redirect" , async ( ) => {
6298
6356
let t = setup ( { routes : REDIRECT_ROUTES } ) ;
0 commit comments