)
})
+ it('replaces if a guard redirects', async () => {
+ const history = createMemoryHistory()
+ const { router } = await newRouter({ history })
+ // move somewhere else
+ await router.push('/search')
+ jest.spyOn(history, 'replace')
+ await router.replace('/home-before')
+ expect(history.replace).toHaveBeenCalledTimes(1)
+ expect(history.replace).toHaveBeenCalledWith(
+ expect.objectContaining({
+ fullPath: '/',
+ path: '/',
+ query: {},
+ hash: '',
+ }),
+ undefined
+ )
+ })
+
it('allows to customize parseQuery', async () => {
const parseQuery = jest.fn()
const { router } = await newRouter({ parseQuery })
// we nee the value at the time we render because when we unmount, we
// navigated to a different location so the value is different
const currentMatched = matchedRoute.value
+ const currentName = props.name
function onVnodeUnmounted() {
if (currentMatched) {
// remove the instance reference to prevent leak
- currentMatched.instances[props.name] = null
+ currentMatched.instances[currentName] = null
}
}
export {
RouteLocationRaw,
+ RouteLocation,
RouteLocationNormalized,
RouteLocationNormalizedLoaded,
START_LOCATION_NORMALIZED as START_LOCATION,
RouteRecordName,
isRouteName,
NavigationGuardWithThis,
+ RouteLocationOptions,
} from './types'
import { RouterHistory, HistoryState } from './history/common'
import {
): Promise<NavigationFailure | void> {
const targetLocation: RouteLocation = (pendingLocation = resolve(to))
const from = currentRoute.value
- const data: HistoryState | undefined = (to as any).state
- const force: boolean | undefined = (to as any).force
- const replace: boolean | undefined = (to as any).replace === true
+ const data: HistoryState | undefined = (to as RouteLocationOptions).state
+ const force: boolean | undefined = (to as RouteLocationOptions).force
+ // to could be a string where `replace` is a function
+ const replace = (to as RouteLocationOptions).replace === true
if (!force && isSameRouteLocation(from, targetLocation)) return
} else if (error.type === ErrorTypes.NAVIGATION_GUARD_REDIRECT) {
// preserve the original redirectedFrom if any
return pushWithRedirect(
- (error as NavigationRedirectError).to,
+ // keep options
+ {
+ ...locationAsObject((error as NavigationRedirectError).to),
+ state: data,
+ force,
+ replace,
+ },
redirectedFrom || toLocation
)
} else {
return pushWithRedirect(
(error as NavigationRedirectError).to,
toLocation
+ // TODO: in dev show warning, in prod noop, same as initial navigation
).catch(() => {})
} else {
// TODO: test on different browsers ensure consistent behavior
import { LocationQuery, LocationQueryRaw } from '../utils/query'
import { PathParserOptions } from '../matcher/path-parser-ranker'
-import { markRaw, Ref, ComputedRef, Component } from 'vue'
+import { markRaw, Ref, ComputedRef, ComponentOptions } from 'vue'
import { RouteRecord, RouteRecordNormalized } from '../matcher/types'
import { HistoryState } from '../history/common'
matched: RouteRecordNormalized[] // non-enumerable
}
-export type RouteComponent = Component
+export type RouteComponent = ComponentOptions
export type RawRouteComponent = RouteComponent | Lazy<RouteComponent>
export type RouteRecordName = string | symbol