Skip to content

Commit

Permalink
feat: allow inject within global navigation guards
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed May 11, 2023
1 parent ce2a7b9 commit 909c45b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 8 deletions.
51 changes: 51 additions & 0 deletions packages/router/__tests__/guards/navigatioGuardsInjections.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @jest-environment jsdom
*/
import { createDom, newRouter as createRouter } from '../utils'
import { mount } from '@vue/test-utils'
import { inject } from 'vue'
import { mockWarn } from 'jest-mock-warn'
import type { Router } from '../../src'

describe('inject() within navigation guards', () => {
mockWarn()
beforeAll(() => {
createDom()
})

const PageComponent = {
template: `<div>Page</div>`,
}

function factory(router: Router) {
return mount(
{
template: `<RouterView />`,
},
{
global: {
plugins: [router],
provide: {
test: 'hello',
},
},
}
)
}

const globalGuards = ['beforeEach', 'beforeResolve', 'afterEach'] as const

for (const guardName of globalGuards) {
it(`router.${guardName}()`, async () => {
expect.assertions(1)
const router = createRouter({
routes: [{ path: '/', component: PageComponent }],
})
router[guardName](() => {
expect(inject('test')).toBe('hello')
})
factory(router)
await router.isReady()
})
}
})
28 changes: 20 additions & 8 deletions packages/router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
RouteLocationOptions,
MatcherLocationRaw,
RouteParams,
NavigationGuardReturn,
} from './types'
import { RouterHistory, HistoryState, NavigationType } from './history/common'
import {
Expand Down Expand Up @@ -778,6 +779,14 @@ export function createRouter(options: RouterOptions): Router {
return error ? Promise.reject(error) : Promise.resolve()
}

function runWithContext<T>(fn: () => T): T {
const app: App | undefined = installedApps.values().next().value
// support Vue < 3.3
return app && typeof app.runWithContext === 'function'
? app.runWithContext(fn)
: fn()
}

// TODO: refactor the whole before guards by internally using router.beforeEach

function navigate(
Expand Down Expand Up @@ -907,7 +916,9 @@ export function createRouter(options: RouterOptions): Router {
): void {
// navigation is confirmed, call afterGuards
// TODO: wrap with error handlers
for (const guard of afterGuards.list()) guard(to, from, failure)
for (const guard of afterGuards.list()) {
runWithContext(() => guard(to, from, failure))
}
}

/**
Expand Down Expand Up @@ -1263,14 +1274,15 @@ export function createRouter(options: RouterOptions): Router {
},
}

return router
}
// TODO: type this as NavigationGuardReturn or similar instead of any
function runGuardQueue(guards: Lazy<any>[]): Promise<any> {
return guards.reduce(
(promise, guard) => promise.then(() => runWithContext(guard)),
Promise.resolve()
)
}

function runGuardQueue(guards: Lazy<any>[]): Promise<void> {
return guards.reduce(
(promise, guard) => promise.then(() => guard()),
Promise.resolve()
)
return router
}

function extractChangingRecords(
Expand Down

0 comments on commit 909c45b

Please sign in to comment.