From: Eduardo San Martin Morote Date: Mon, 6 May 2019 19:47:46 +0000 (+0200) Subject: feat: allow beforeEnter as array X-Git-Tag: v4.0.0-alpha.0~373 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7724317f607f0153114796ffda45ab297d8cc94b;p=thirdparty%2Fvuejs%2Frouter.git feat: allow beforeEnter as array --- diff --git a/__tests__/guards/route-beforeEnter.spec.js b/__tests__/guards/route-beforeEnter.spec.js index f1583eb2..ed48bcce 100644 --- a/__tests__/guards/route-beforeEnter.spec.js +++ b/__tests__/guards/route-beforeEnter.spec.js @@ -4,10 +4,13 @@ const expect = require('expect') const { HTML5History } = require('../../src/history/html5') const { Router } = require('../../src/router') const fakePromise = require('faked-promise') -const { NAVIGATION_TYPES, createDom, noGuard } = require('../utils') +const { NAVIGATION_TYPES, createDom, noGuard, tick } = require('../utils') + +/** @typedef {import('../../src/types').RouteRecord} RouteRecord */ +/** @typedef {import('../../src/router').RouterOptions} RouterOptions */ /** - * @param {Partial & { routes: import('../../src/types').RouteRecord[]}} options + * @param {Partial & { routes: RouteRecord[]}} options */ function createRouter(options) { return new Router({ @@ -20,7 +23,8 @@ const Home = { template: `
Home
` } const Foo = { template: `
Foo
` } const beforeEnter = jest.fn() -/** @type {import('../../src/types').RouteRecord[]} */ +const beforeEnters = [jest.fn(), jest.fn()] +/** @type {RouteRecord[]} */ const routes = [ { path: '/', component: Home }, { path: '/home', component: Home, beforeEnter }, @@ -30,10 +34,23 @@ const routes = [ component: Foo, beforeEnter, }, + { + path: '/multiple', + beforeEnter: beforeEnters, + component: Foo, + }, ] -beforeEach(() => { +function resetMocks() { beforeEnter.mockReset() + beforeEnters.forEach(spy => { + spy.mockReset() + spy.mockImplementationOnce(noGuard) + }) +} + +beforeEach(() => { + resetMocks() }) describe('beforeEnter', () => { @@ -50,6 +67,18 @@ describe('beforeEnter', () => { expect(beforeEnter).toHaveBeenCalledTimes(1) }) + it('supports an array of beforeEnter', async () => { + const router = createRouter({ routes }) + await router[navigationMethod]('/multiple') + expect(beforeEnters[0]).toHaveBeenCalledTimes(1) + expect(beforeEnters[1]).toHaveBeenCalledTimes(1) + expect(beforeEnters[0]).toHaveBeenCalledWith( + expect.objectContaining({ path: '/multiple' }), + expect.objectContaining({ path: '/' }), + expect.any(Function) + ) + }) + it('calls beforeEnter different records, same component', async () => { const router = createRouter({ routes }) beforeEnter.mockImplementationOnce(noGuard) @@ -81,6 +110,29 @@ describe('beforeEnter', () => { await p expect(router.currentRoute.fullPath).toBe('/foo') }) + + it('waits before navigating in an array of beforeEnter', async () => { + const [p1, r1] = fakePromise() + const [p2, r2] = fakePromise() + const router = createRouter({ routes }) + beforeEnters[0].mockImplementationOnce(async (to, from, next) => { + await p1 + next() + }) + beforeEnters[1].mockImplementationOnce(async (to, from, next) => { + await p2 + next() + }) + const p = router[navigationMethod]('/multiple') + expect(router.currentRoute.fullPath).toBe('/') + expect(beforeEnters[1]).not.toHaveBeenCalled() + r1() + await p1 + await tick() + r2() + await p + expect(router.currentRoute.fullPath).toBe('/multiple') + }) }) }) }) diff --git a/src/router.ts b/src/router.ts index e41f6c13..3d0ddaf1 100644 --- a/src/router.ts +++ b/src/router.ts @@ -179,8 +179,6 @@ export class Router { await this.runGuardQueue(guards) // check global guards beforeEach - // avoid if we are not changing route - // TODO: trigger on child navigation guards = [] for (const guard of this.beforeGuards) { guards.push(guardToPromiseFn(guard, to, from)) @@ -201,12 +199,17 @@ export class Router { await this.runGuardQueue(guards) // check the route beforeEnter - // TODO: check children. Should we also check reused routes guards guards = [] for (const record of to.matched) { // do not trigger beforeEnter on reused views - if (record.beforeEnter && from.matched.indexOf(record) < 0) - guards.push(guardToPromiseFn(record.beforeEnter, to, from)) + if (record.beforeEnter && from.matched.indexOf(record) < 0) { + if (Array.isArray(record.beforeEnter)) { + for (const beforeEnter of record.beforeEnter) + guards.push(guardToPromiseFn(beforeEnter, to, from)) + } else { + guards.push(guardToPromiseFn(record.beforeEnter, to, from)) + } + } } // run the queue of per route beforeEnter guards diff --git a/src/types/index.ts b/src/types/index.ts index cbee6c39..1a569019 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -97,7 +97,7 @@ export type RouteComponent = { interface RouteRecordCommon { path: string // | RegExp name?: string - beforeEnter?: NavigationGuard + beforeEnter?: NavigationGuard | NavigationGuard[] } export type RouteRecordRedirectOption = @@ -121,12 +121,6 @@ export type RouteRecord = | RouteRecordMultipleViews | RouteRecordRedirect -export const START_RECORD: RouteRecord = { - path: '/', - // @ts-ignore - component: { render: h => h() }, -} - // TODO: this should probably be generate by ensureLocation export const START_LOCATION_NORMALIZED: RouteLocationNormalized = { path: '/',