@@ -1002,6 +1002,7 @@ describe('Experimental Router', () => {
10021002
10031003 beforeEach ( ( ) => {
10041004 scrollTo . mockClear ( )
1005+ window . history . replaceState ( null , '' , '/' )
10051006 } )
10061007
10071008 afterAll ( ( ) => {
@@ -1017,6 +1018,46 @@ describe('Experimental Router', () => {
10171018 '/p/a' : 2000 ,
10181019 }
10191020
1021+ it ( 'does not restore scroll positions for pop navigations with unknown direction' , async ( ) => {
1022+ const scrollBehavior = vi . fn ( )
1023+ const { router } = await newRouter ( {
1024+ history : createWebHashHistory ( ) ,
1025+ scrollBehavior,
1026+ } )
1027+ scrollBehavior . mockClear ( )
1028+
1029+ // Plain `<a href="#...">` links and manual `location.hash` writes create
1030+ // a history entry with no state, so the popstate fires with
1031+ // `state: null` and the router cannot compute a direction (delta 0).
1032+ // happy-dom does not fire popstate on hash changes, so dispatch it like
1033+ // a browser would.
1034+ function changeHash ( hash : string ) {
1035+ window . location . hash = hash
1036+ window . dispatchEvent ( new PopStateEvent ( 'popstate' , { state : null } ) )
1037+ }
1038+
1039+ changeHash ( '#/foo' )
1040+ await nextNavigation ( router )
1041+ changeHash ( '#/' )
1042+ await nextNavigation ( router )
1043+
1044+ expect ( scrollBehavior ) . toHaveBeenCalledTimes ( 2 )
1045+ expect ( scrollBehavior ) . toHaveBeenNthCalledWith (
1046+ 1 ,
1047+ expect . objectContaining ( { path : '/foo' } ) ,
1048+ expect . objectContaining ( { path : '/' } ) ,
1049+ null
1050+ )
1051+ // a stale position saved under the unknown-direction key would show up
1052+ // here as a non-null savedPosition and override the target anchor
1053+ expect ( scrollBehavior ) . toHaveBeenNthCalledWith (
1054+ 2 ,
1055+ expect . objectContaining ( { path : '/' } ) ,
1056+ expect . objectContaining ( { path : '/foo' } ) ,
1057+ null
1058+ )
1059+ } )
1060+
10201061 it ( 'ignores the scroll of navigations superseded before they finish' , async ( ) => {
10211062 // scrollBehavior resolves asynchronously, simulating waiting for the DOM
10221063 const scrollBehavior = vi . fn ( ( to : { path : string } ) => {
0 commit comments