diff --git a/src/index.js b/src/index.js index b3eb25dd3..e95ace6d1 100644 --- a/src/index.js +++ b/src/index.js @@ -151,11 +151,25 @@ export default class VueRouter { } push (location: RawLocation, onComplete?: Function, onAbort?: Function) { - this.history.push(location, onComplete, onAbort) + // $flow-disable-line + if (!onComplete && !onAbort && typeof Promise !== 'undefined') { + return new Promise((resolve, reject) => { + this.history.push(location, resolve, reject) + }) + } else { + this.history.push(location, onComplete, onAbort) + } } replace (location: RawLocation, onComplete?: Function, onAbort?: Function) { - this.history.replace(location, onComplete, onAbort) + // $flow-disable-line + if (!onComplete && !onAbort && typeof Promise !== 'undefined') { + return new Promise((resolve, reject) => { + this.history.replace(location, resolve, reject) + }) + } else { + this.history.replace(location, onComplete, onAbort) + } } go (n: number) { diff --git a/test/unit/specs/api.spec.js b/test/unit/specs/api.spec.js index 1fba4977b..8611b1987 100644 --- a/test/unit/specs/api.spec.js +++ b/test/unit/specs/api.spec.js @@ -118,7 +118,7 @@ describe('router.addRoutes', () => { }) }) -describe('router.push/replace callbacks', () => { +describe('router.push/replace', () => { let calls = [] let router, spy1, spy2 @@ -151,38 +151,89 @@ describe('router.push/replace callbacks', () => { }, 1) }) }) + describe('callbacks', () => { + it('push does not return a Promise when a callback is passed', done => { + expect(router.push('/foo', done)).toEqual(undefined) + }) - it('push complete', done => { - router.push('/foo', () => { - expect(calls).toEqual([1, 2, 3, 4]) - done() + it('push complete', done => { + router.push('/foo', () => { + expect(calls).toEqual([1, 2, 3, 4]) + done() + }) }) - }) - it('push abort', done => { - router.push('/foo', spy1, spy2) - router.push('/bar', () => { - expect(calls).toEqual([1, 1, 2, 2]) - expect(spy1).not.toHaveBeenCalled() - expect(spy2).toHaveBeenCalled() - done() + it('push abort', done => { + router.push('/foo', spy1, spy2) + router.push('/bar', () => { + expect(calls).toEqual([1, 1, 2, 2]) + expect(spy1).not.toHaveBeenCalled() + expect(spy2).toHaveBeenCalled() + done() + }) }) - }) - it('replace complete', done => { - router.replace('/foo', () => { - expect(calls).toEqual([1, 2, 3, 4]) - done() + it('replace does not return a Promise when a callback is passed', done => { + expect(router.replace('/foo', done)).toEqual(undefined) + }) + + it('replace complete', done => { + router.replace('/foo', () => { + expect(calls).toEqual([1, 2, 3, 4]) + done() + }) + }) + + it('replace abort', done => { + router.replace('/foo', spy1, spy2) + router.replace('/bar', () => { + expect(calls).toEqual([1, 1, 2, 2]) + expect(spy1).not.toHaveBeenCalled() + expect(spy2).toHaveBeenCalled() + done() + }) }) }) - it('replace abort', done => { - router.replace('/foo', spy1, spy2) - router.replace('/bar', () => { - expect(calls).toEqual([1, 1, 2, 2]) - expect(spy1).not.toHaveBeenCalled() - expect(spy2).toHaveBeenCalled() - done() + describe('promises', () => { + it('push complete', done => { + router.push('/foo') + .then(spy1) + .finally(() => { + expect(calls).toEqual([1, 2, 3, 4]) + expect(spy1).toHaveBeenCalledWith(router.currentRoute) + done() + }) + }) + + it('push abort', done => { + router.push('/foo').catch(spy2) + router.push('/bar').finally(() => { + expect(calls).toEqual([1, 1, 2, 2]) + expect(spy1).not.toHaveBeenCalled() + expect(spy2).toHaveBeenCalled() + done() + }) + }) + + it('replace complete', done => { + router.replace('/foo') + .then(spy1) + .finally(() => { + expect(calls).toEqual([1, 2, 3, 4]) + expect(spy1).toHaveBeenCalledWith(router.currentRoute) + done() + }) + }) + + it('replace abort', done => { + router.replace('/foo').catch(spy2) + router.replace('/bar').finally(() => { + expect(calls).toEqual([1, 1, 2, 2]) + expect(spy1).not.toHaveBeenCalled() + expect(spy2).toHaveBeenCalled() + done() + }) }) }) }) diff --git a/test/unit/specs/error-handling.spec.js b/test/unit/specs/error-handling.spec.js index b912dca62..6ac2944ff 100644 --- a/test/unit/specs/error-handling.spec.js +++ b/test/unit/specs/error-handling.spec.js @@ -4,7 +4,7 @@ import VueRouter from '../../../src/index' Vue.use(VueRouter) describe('error handling', () => { - it('onReady errors', () => { + it('onReady errors', done => { const router = new VueRouter() const err = new Error('foo') router.beforeEach(() => { throw err }) @@ -12,31 +12,39 @@ describe('error handling', () => { const onReady = jasmine.createSpy('ready') const onError = jasmine.createSpy('error') + const onPromiseReject = jasmine.createSpy('promise reject') router.onReady(onReady, onError) - router.push('/') - - expect(onReady).not.toHaveBeenCalled() - expect(onError).toHaveBeenCalledWith(err) + router.push('/').catch(onPromiseReject).finally(() => { + expect(onReady).not.toHaveBeenCalled() + expect(onError).toHaveBeenCalledWith(err) + expect(onPromiseReject).toHaveBeenCalled() + done() + }) }) - it('navigation errors', () => { + it('navigation errors', done => { const router = new VueRouter() const err = new Error('foo') const spy = jasmine.createSpy('error') + const spy1 = jasmine.createSpy('promise reject') router.onError(spy) router.push('/') router.beforeEach(() => { throw err }) - router.push('/foo') - expect(spy).toHaveBeenCalledWith(err) + router.push('/foo').catch(spy1).finally(() => { + expect(spy).toHaveBeenCalledWith(err) + expect(spy1).toHaveBeenCalled() + done() + }) }) - it('async component errors', () => { + it('async component errors', done => { const err = new Error('foo') const spy1 = jasmine.createSpy('error') const spy2 = jasmine.createSpy('errpr') + const spy3 = jasmine.createSpy('promise reject') const Comp = () => { throw err } const router = new VueRouter({ routes: [ @@ -47,9 +55,11 @@ describe('error handling', () => { router.onError(spy1) router.onReady(() => {}, spy2) - router.push('/') - - expect(spy1).toHaveBeenCalledWith(err) - expect(spy2).toHaveBeenCalledWith(err) + router.push('/').catch(spy3).finally(() => { + expect(spy1).toHaveBeenCalledWith(err) + expect(spy2).toHaveBeenCalledWith(err) + expect(spy3).toHaveBeenCalled() + done() + }) }) }) diff --git a/types/router.d.ts b/types/router.d.ts index dc4516bbd..054dca896 100644 --- a/types/router.d.ts +++ b/types/router.d.ts @@ -25,6 +25,8 @@ export declare class VueRouter { afterEach (hook: (to: Route, from: Route) => any): Function; push (location: RawLocation, onComplete?: Function, onAbort?: ErrorHandler): void; replace (location: RawLocation, onComplete?: Function, onAbort?: ErrorHandler): void; + push (location: RawLocation): Promise; + replace (location: RawLocation): Promise; go (n: number): void; back (): void; forward (): void;