await router.isReady()
})
}
+
+ describe('in-component guards', () => {
+ it('beforeRouteEnter', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ {
+ path: '/',
+ component: {
+ template: `<div>Page</div>`,
+ beforeRouteEnter() {
+ expect(inject('test')).toBe('hello')
+ },
+ },
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/')
+ })
+
+ it('beforeRouteEnter + lazy load', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ {
+ path: '/',
+ component: () =>
+ new Promise(r =>
+ r({
+ template: `<div>Page</div>`,
+ beforeRouteEnter() {
+ expect(inject('test')).toBe('hello')
+ },
+ })
+ ),
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/')
+ })
+
+ it('beforeRouteUpdate', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ {
+ path: '/',
+ component: {
+ template: `<div>Page</div>`,
+ beforeRouteUpdate() {
+ expect(inject('test')).toBe('hello')
+ },
+ },
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/')
+ await router.push('/#other')
+ })
+
+ it('beforeRouteLeave', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ { path: '/', component: PageComponent },
+ {
+ path: '/foo',
+ component: {
+ template: `<div>Page</div>`,
+ beforeRouteLeave() {
+ expect(inject('test')).toBe('hello')
+ },
+ },
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/foo')
+ await router.push('/')
+ })
+ })
})
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded,
record: RouteRecordNormalized,
- name: string
+ name: string,
+ runWithContext: <T>(fn: () => T) => T
): () => Promise<void>
export function guardToPromiseFn(
guard: NavigationGuard,
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded,
record?: RouteRecordNormalized,
- name?: string
+ name?: string,
+ runWithContext: <T>(fn: () => T) => T = fn => fn()
): () => Promise<void> {
// keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place
const enterCallbackArray =
}
// wrapping with Promise.resolve allows it to work with both async and sync guards
- const guardReturn = guard.call(
- record && record.instances[name!],
- to,
- from,
- __DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
+ const guardReturn = runWithContext(() =>
+ guard.call(
+ record && record.instances[name!],
+ to,
+ from,
+ __DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
+ )
)
let guardCall = Promise.resolve(guardReturn)
matched: RouteRecordNormalized[],
guardType: GuardType,
to: RouteLocationNormalized,
- from: RouteLocationNormalizedLoaded
+ from: RouteLocationNormalizedLoaded,
+ runWithContext: <T>(fn: () => T) => T = fn => fn()
) {
const guards: Array<() => Promise<void>> = []
const options: ComponentOptions =
(rawComponent as any).__vccOpts || rawComponent
const guard = options[guardType]
- guard && guards.push(guardToPromiseFn(guard, to, from, record, name))
+ guard &&
+ guards.push(
+ guardToPromiseFn(guard, to, from, record, name, runWithContext)
+ )
} else {
// start requesting the chunk already
let componentPromise: Promise<
const options: ComponentOptions =
(resolvedComponent as any).__vccOpts || resolvedComponent
const guard = options[guardType]
- return guard && guardToPromiseFn(guard, to, from, record, name)()
+ return (
+ guard &&
+ guardToPromiseFn(guard, to, from, record, name, runWithContext)()
+ )
})
)
}