From: Eduardo San Martin Morote Date: Tue, 21 Jul 2020 12:39:29 +0000 (+0200) Subject: feat(guards): allow guards to return a value instead of calling next (#343) X-Git-Tag: v4.0.0-beta.3~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5cb209f3bb53ac0ddf62152f695da610facf4724;p=thirdparty%2Fvuejs%2Frouter.git feat(guards): allow guards to return a value instead of calling next (#343) --- diff --git a/__tests__/guards/guardToPromiseFn.spec.ts b/__tests__/guards/guardToPromiseFn.spec.ts index 7648737b..c593c4d6 100644 --- a/__tests__/guards/guardToPromiseFn.spec.ts +++ b/__tests__/guards/guardToPromiseFn.spec.ts @@ -110,4 +110,126 @@ describe('guardToPromiseFn', () => { expect(err).toBe(error) } }) + + describe('no next argument', () => { + it('rejects if returns false', async () => { + expect.assertions(1) + try { + await guardToPromiseFn((to, from) => false, to, from)() + } catch (err) { + expect(err).toMatchObject({ + from, + to, + type: ErrorTypes.NAVIGATION_ABORTED, + }) + } + }) + + it('resolves no value is returned', async () => { + await expect( + guardToPromiseFn((to, from) => {}, to, from)() + ).resolves.toEqual(undefined) + }) + + it('resolves if true is returned', async () => { + await expect( + guardToPromiseFn((to, from) => true, to, from)() + ).resolves.toEqual(undefined) + }) + + it('rejects if false is returned', async () => { + expect.assertions(1) + try { + await guardToPromiseFn((to, from) => false, to, from)() + } catch (err) { + expect(err).toMatchObject({ + from, + to, + type: ErrorTypes.NAVIGATION_ABORTED, + }) + } + }) + + it('rejects if async false is returned', async () => { + expect.assertions(1) + try { + await guardToPromiseFn(async (to, from) => false, to, from)() + } catch (err) { + expect(err).toMatchObject({ + from, + to, + type: ErrorTypes.NAVIGATION_ABORTED, + }) + } + }) + + it('rejects if a string location is returned', async () => { + expect.assertions(1) + try { + await guardToPromiseFn((to, from) => '/new', to, from)() + } catch (err) { + expect(err).toMatchObject({ + from: to, + to: '/new', + type: ErrorTypes.NAVIGATION_GUARD_REDIRECT, + }) + } + }) + + it('rejects if an object location is returned', async () => { + expect.assertions(1) + let redirectTo = { path: '/new' } + try { + await guardToPromiseFn((to, from) => redirectTo, to, from)() + } catch (err) { + expect(err).toMatchObject({ + from: to, + to: redirectTo, + type: ErrorTypes.NAVIGATION_GUARD_REDIRECT, + }) + } + }) + + it('rejects if an error is returned', async () => { + expect.assertions(1) + let error = new Error('nope') + try { + await guardToPromiseFn((to, from) => error, to, from)() + } catch (err) { + expect(err).toBe(error) + } + }) + + it('rejects if guard rejects a Promise', async () => { + expect.assertions(1) + let error = new Error('nope') + try { + await guardToPromiseFn( + async (to, from) => { + throw error + }, + to, + from + )() + } catch (err) { + expect(err).toBe(error) + } + }) + + it('rejects if guard throws an error', async () => { + expect.assertions(1) + let error = new Error('nope') + try { + await guardToPromiseFn( + (to, from) => { + throw error + }, + to, + from + )() + } catch (err) { + expect(err).toBe(error) + } + }) + }) }) diff --git a/src/navigationGuards.ts b/src/navigationGuards.ts index 74a734f7..2f09b2cf 100644 --- a/src/navigationGuards.ts +++ b/src/navigationGuards.ts @@ -152,14 +152,17 @@ export function guardToPromiseFn( } // wrapping with Promise.resolve allows it to work with both async and sync guards - Promise.resolve( + let guardCall = Promise.resolve( guard.call( record && record.instances[name!], to, from, __DEV__ ? canOnlyBeCalledOnce(next, to, from) : next ) - ).catch(err => reject(err)) + ) + + if (guard.length < 3) guardCall.then(next) + guardCall.catch(err => reject(err)) }) }