Skip to content

Commit

Permalink
fix(hash): force navigation restore on manual navigation
Browse files Browse the repository at this point in the history
Fix #916
  • Loading branch information
posva committed May 3, 2021
1 parent 0c7d80b commit 98e3088
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 3 deletions.
80 changes: 80 additions & 0 deletions __tests__/hash-manual-navigation.spec.ts
@@ -0,0 +1,80 @@
import { createMemoryHistory, createRouter } from '../src'
import { tick } from './utils'

const component = {}

declare module '../src' {
export interface RouterHistory {
changeURL(url: string): void
}
}

describe('hash history edge cases', () => {
it('correctly sets the url when it is manually changed but aborted with a redirect in guard', async () => {
const history = createMemoryHistory()
const router = createRouter({
history,
routes: [
{ path: '/', component },
{ path: '/foo', component },
],
})

await router.push('/foo?step=1')
await router.push('/foo?step=2')
await router.push('/foo?step=3')
router.back()
await tick() // wait for router listener on history
expect(router.currentRoute.value.fullPath).toBe('/foo?step=2')

// force a redirect next time
const removeListener = router.beforeEach(to => {
if (to.path === '/') {
return '/foo?step=2'
}
})

// const spy = jest.spyOn(history, 'go')

history.changeURL('/')
await tick()
expect(router.currentRoute.value.fullPath).toBe('/foo?step=2')
expect(history.location).toBe('/foo?step=2')
// expect(spy).toHaveBeenCalledTimes(1)
// expect(spy).toHaveBeenCalledWith(-1)
})

it('correctly sets the url when it is manually changed but aborted with guard', async () => {
const history = createMemoryHistory()
const router = createRouter({
history,
routes: [
{ path: '/', component },
{ path: '/foo', component },
],
})

await router.push('/foo?step=1')
await router.push('/foo?step=2')
await router.push('/foo?step=3')
router.back()
await tick() // wait for router listener on history
expect(router.currentRoute.value.fullPath).toBe('/foo?step=2')

// force a redirect next time
const removeListener = router.beforeEach(to => {
if (to.path === '/') {
return false
}
})

// const spy = jest.spyOn(history, 'go')

history.changeURL('/')
await tick()
expect(router.currentRoute.value.fullPath).toBe('/foo?step=2')
expect(history.location).toBe('/foo?step=2')
// expect(spy).toHaveBeenCalledTimes(1)
// expect(spy).toHaveBeenCalledWith(-1)
})
})
37 changes: 34 additions & 3 deletions src/router.ts
Expand Up @@ -13,7 +13,7 @@ import {
RouteLocationOptions,
MatcherLocationRaw,
} from './types'
import { RouterHistory, HistoryState } from './history/common'
import { RouterHistory, HistoryState, NavigationType } from './history/common'
import {
ScrollPosition,
getSavedScrollPosition,
Expand Down Expand Up @@ -972,7 +972,24 @@ export function createRouter(options: RouterOptions): Router {
(error as NavigationRedirectError).to,
toLocation
// avoid an uncaught rejection, let push call triggerError
).catch(noop)
)
.then(failure => {
// manual change in hash history #916 ending up in the URL not
// changing but it was changed by the manual url change, so we
// need to manually change it ourselves
if (
isNavigationFailure(
failure,
ErrorTypes.NAVIGATION_ABORTED |
ErrorTypes.NAVIGATION_DUPLICATED
) &&
!info.delta &&
info.type === NavigationType.pop
) {
routerHistory.go(-1, false)
}
})
.catch(noop)
// avoid the then branch
return Promise.reject()
}
Expand All @@ -992,7 +1009,21 @@ export function createRouter(options: RouterOptions): Router {
)

// revert the navigation
if (failure && info.delta) routerHistory.go(-info.delta, false)
if (failure) {
if (info.delta) {
routerHistory.go(-info.delta, false)
} else if (
info.type === NavigationType.pop &&
isNavigationFailure(
failure,
ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_DUPLICATED
)
) {
// manual change in hash history #916
// it's like a push but lacks the information of the direction
routerHistory.go(-1, false)
}
}

triggerAfterEach(
toLocation as RouteLocationNormalizedLoaded,
Expand Down

0 comments on commit 98e3088

Please sign in to comment.