@@ -549,20 +549,25 @@ describe('Router', () => {
549549 expect ( loadEnd ) . not . to . have . been . called ;
550550 } ) ;
551551
552- // TODO: Relies on upcoming property being added to navigation events
553- describe . skip ( 'intercepted VS external links' , ( ) => {
554- const shouldIntercept = [ null , '' , '_self' , 'self' , '_SELF' ] ;
555- const shouldNavigate = [ '_top' , '_parent' , '_blank' , 'custom' , '_BLANK' ] ;
552+ describe ( 'intercepted VS external links' , ( ) => {
553+ const shouldIntercept = [ null , '' , '_self' , '_SELF' ] ;
554+ const shouldNavigate = [ '_top' , '_parent' , '_blank' , '_BLANK' , 'custom' ] ;
555+
556+ // Create an ID as Chrome & Safari don't support the
557+ // case-sensitivity flag for attribute selectors, meaning
558+ // we can't distinguish between `_self` and `_SELF`.
559+ const createId = ( target ) => {
560+ if ( target === null ) return 'null' ;
561+ if ( target === '' ) return 'emptyString' ;
562+ return target ;
563+ }
556564
557- const Route = ( ) => (
558- < div >
559- { [ ...shouldIntercept , ...shouldNavigate ] . map ( ( target , i ) => {
560- const url = '/' + i + '/' + target ;
561- if ( target === null ) return < a href = { url } > target = { target + '' } </ a > ;
562- return < a href = { url } target = { target } > target = { target } </ a > ;
563- } ) }
564- </ div >
565- ) ;
565+ const Links = ( ) => < div >
566+ { [ ...shouldIntercept , ...shouldNavigate ] . map ( ( target , i ) => {
567+ const url = '/' + i + '/' + target ;
568+ return < a href = { url } target = { target } id = { createId ( target ) } > target = { target } </ a > ;
569+ } ) }
570+ </ div > ;
566571
567572 let triedToNavigate = false ;
568573 const handler = ( e ) => {
@@ -572,34 +577,30 @@ describe('Router', () => {
572577 }
573578 }
574579
575- beforeEach ( async ( ) => {
576- const App = ( ) => {
577- useEffect ( ( ) => {
578- navigation . addEventListener ( 'navigate' , handler ) ;
579- return ( ) => navigation . removeEventListener ( 'navigate' , handler ) ;
580- } , [ ] ) ;
580+ const App = ( ) => {
581+ useEffect ( ( ) => {
582+ navigation . addEventListener ( 'navigate' , handler ) ;
583+ return ( ) => navigation . removeEventListener ( 'navigate' , handler ) ;
584+ } , [ ] ) ;
581585
582- return (
583- < LocationProvider >
584- < Router >
585- < Route default />
586- </ Router >
587- < ShallowLocation />
588- </ LocationProvider >
589- ) ;
590- }
586+ return (
587+ < LocationProvider >
588+ < Links / >
589+ < ShallowLocation />
590+ </ LocationProvider >
591+ ) ;
592+ }
593+
594+ beforeEach ( async ( ) => {
591595 render ( < App /> , scratch ) ;
592596 await sleep ( 10 ) ;
593597 } ) ;
594598
595599 const getName = target => ( target == null ? 'no target attribute' : `target="${ target } "` ) ;
596600
597- // these should all be intercepted by the router.
598601 for ( const target of shouldIntercept ) {
599602 it ( `should intercept clicks on links with ${ getName ( target ) } ` , async ( ) => {
600- const sel = target == null ? `a:not([target])` : `a[target="${ target } "]` ;
601- const el = scratch . querySelector ( sel ) ;
602- if ( ! el ) throw Error ( `Unable to find link: ${ sel } ` ) ;
603+ const el = scratch . querySelector ( `#${ createId ( target ) } ` ) ;
603604 const url = el . getAttribute ( 'href' ) ;
604605 el . click ( ) ;
605606 await sleep ( 1 ) ;
@@ -610,13 +611,17 @@ describe('Router', () => {
610611 } ) ;
611612 }
612613
613- // these should all navigate.
614+ // TODO: These tests are rather flakey, for some reason the additional handler
615+ // occasionally isn't running prior browser actually navigates away.
614616 for ( const target of shouldNavigate ) {
615617 it ( `should allow default browser navigation for links with ${ getName ( target ) } ` , async ( ) => {
616- const sel = target == null ? `a:not([target])` : `a[target="${ target } "]` ;
617- const el = scratch . querySelector ( sel ) ;
618- if ( ! el ) throw Error ( `Unable to find link: ${ sel } ` ) ;
619- el . click ( ) ;
618+ // Currently cross-window navigations, (e.g., `target="_blank"`), do not trigger a
619+ // `navigate` event, which makes this difficult to observe. Per the spec, however, this
620+ // might be a bug in Chrome's implementation:
621+ // https://github.com/WICG/navigation-api?tab=readme-ov-file#restrictions-on-firing-canceling-and-responding
622+ if ( target === '_blank' || target === '_BLANK' || target === 'custom' ) return ;
623+
624+ scratch . querySelector ( `#${ createId ( target ) } ` ) . click ( ) ;
620625 await sleep ( 1 ) ;
621626 expect ( triedToNavigate ) . to . be . true ;
622627
0 commit comments