Skip to content

Commit d907a13

Browse files
Mighty683posva
authored andcommitted
feat: return a promise with push and replace (#2862)
Closes #1769 * fix: push/replace return promise close(#1769) * feat: organize tests and add overloading * fix: text names * feat: Add promise rejection
1 parent f00f1fc commit d907a13

File tree

4 files changed

+117
-40
lines changed

4 files changed

+117
-40
lines changed

src/index.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,25 @@ export default class VueRouter {
151151
}
152152

153153
push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
154-
this.history.push(location, onComplete, onAbort)
154+
// $flow-disable-line
155+
if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
156+
return new Promise((resolve, reject) => {
157+
this.history.push(location, resolve, reject)
158+
})
159+
} else {
160+
this.history.push(location, onComplete, onAbort)
161+
}
155162
}
156163

157164
replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
158-
this.history.replace(location, onComplete, onAbort)
165+
// $flow-disable-line
166+
if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
167+
return new Promise((resolve, reject) => {
168+
this.history.replace(location, resolve, reject)
169+
})
170+
} else {
171+
this.history.replace(location, onComplete, onAbort)
172+
}
159173
}
160174

161175
go (n: number) {

test/unit/specs/api.spec.js

+76-25
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ describe('router.addRoutes', () => {
118118
})
119119
})
120120

121-
describe('router.push/replace callbacks', () => {
121+
describe('router.push/replace', () => {
122122
let calls = []
123123
let router, spy1, spy2
124124

@@ -151,38 +151,89 @@ describe('router.push/replace callbacks', () => {
151151
}, 1)
152152
})
153153
})
154+
describe('callbacks', () => {
155+
it('push does not return a Promise when a callback is passed', done => {
156+
expect(router.push('/foo', done)).toEqual(undefined)
157+
})
154158

155-
it('push complete', done => {
156-
router.push('/foo', () => {
157-
expect(calls).toEqual([1, 2, 3, 4])
158-
done()
159+
it('push complete', done => {
160+
router.push('/foo', () => {
161+
expect(calls).toEqual([1, 2, 3, 4])
162+
done()
163+
})
159164
})
160-
})
161165

162-
it('push abort', done => {
163-
router.push('/foo', spy1, spy2)
164-
router.push('/bar', () => {
165-
expect(calls).toEqual([1, 1, 2, 2])
166-
expect(spy1).not.toHaveBeenCalled()
167-
expect(spy2).toHaveBeenCalled()
168-
done()
166+
it('push abort', done => {
167+
router.push('/foo', spy1, spy2)
168+
router.push('/bar', () => {
169+
expect(calls).toEqual([1, 1, 2, 2])
170+
expect(spy1).not.toHaveBeenCalled()
171+
expect(spy2).toHaveBeenCalled()
172+
done()
173+
})
169174
})
170-
})
171175

172-
it('replace complete', done => {
173-
router.replace('/foo', () => {
174-
expect(calls).toEqual([1, 2, 3, 4])
175-
done()
176+
it('replace does not return a Promise when a callback is passed', done => {
177+
expect(router.replace('/foo', done)).toEqual(undefined)
178+
})
179+
180+
it('replace complete', done => {
181+
router.replace('/foo', () => {
182+
expect(calls).toEqual([1, 2, 3, 4])
183+
done()
184+
})
185+
})
186+
187+
it('replace abort', done => {
188+
router.replace('/foo', spy1, spy2)
189+
router.replace('/bar', () => {
190+
expect(calls).toEqual([1, 1, 2, 2])
191+
expect(spy1).not.toHaveBeenCalled()
192+
expect(spy2).toHaveBeenCalled()
193+
done()
194+
})
176195
})
177196
})
178197

179-
it('replace abort', done => {
180-
router.replace('/foo', spy1, spy2)
181-
router.replace('/bar', () => {
182-
expect(calls).toEqual([1, 1, 2, 2])
183-
expect(spy1).not.toHaveBeenCalled()
184-
expect(spy2).toHaveBeenCalled()
185-
done()
198+
describe('promises', () => {
199+
it('push complete', done => {
200+
router.push('/foo')
201+
.then(spy1)
202+
.finally(() => {
203+
expect(calls).toEqual([1, 2, 3, 4])
204+
expect(spy1).toHaveBeenCalledWith(router.currentRoute)
205+
done()
206+
})
207+
})
208+
209+
it('push abort', done => {
210+
router.push('/foo').catch(spy2)
211+
router.push('/bar').finally(() => {
212+
expect(calls).toEqual([1, 1, 2, 2])
213+
expect(spy1).not.toHaveBeenCalled()
214+
expect(spy2).toHaveBeenCalled()
215+
done()
216+
})
217+
})
218+
219+
it('replace complete', done => {
220+
router.replace('/foo')
221+
.then(spy1)
222+
.finally(() => {
223+
expect(calls).toEqual([1, 2, 3, 4])
224+
expect(spy1).toHaveBeenCalledWith(router.currentRoute)
225+
done()
226+
})
227+
})
228+
229+
it('replace abort', done => {
230+
router.replace('/foo').catch(spy2)
231+
router.replace('/bar').finally(() => {
232+
expect(calls).toEqual([1, 1, 2, 2])
233+
expect(spy1).not.toHaveBeenCalled()
234+
expect(spy2).toHaveBeenCalled()
235+
done()
236+
})
186237
})
187238
})
188239
})

test/unit/specs/error-handling.spec.js

+23-13
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,47 @@ import VueRouter from '../../../src/index'
44
Vue.use(VueRouter)
55

66
describe('error handling', () => {
7-
it('onReady errors', () => {
7+
it('onReady errors', done => {
88
const router = new VueRouter()
99
const err = new Error('foo')
1010
router.beforeEach(() => { throw err })
1111
router.onError(() => {})
1212

1313
const onReady = jasmine.createSpy('ready')
1414
const onError = jasmine.createSpy('error')
15+
const onPromiseReject = jasmine.createSpy('promise reject')
1516
router.onReady(onReady, onError)
1617

17-
router.push('/')
18-
19-
expect(onReady).not.toHaveBeenCalled()
20-
expect(onError).toHaveBeenCalledWith(err)
18+
router.push('/').catch(onPromiseReject).finally(() => {
19+
expect(onReady).not.toHaveBeenCalled()
20+
expect(onError).toHaveBeenCalledWith(err)
21+
expect(onPromiseReject).toHaveBeenCalled()
22+
done()
23+
})
2124
})
2225

23-
it('navigation errors', () => {
26+
it('navigation errors', done => {
2427
const router = new VueRouter()
2528
const err = new Error('foo')
2629
const spy = jasmine.createSpy('error')
30+
const spy1 = jasmine.createSpy('promise reject')
2731
router.onError(spy)
2832

2933
router.push('/')
3034
router.beforeEach(() => { throw err })
3135

32-
router.push('/foo')
33-
expect(spy).toHaveBeenCalledWith(err)
36+
router.push('/foo').catch(spy1).finally(() => {
37+
expect(spy).toHaveBeenCalledWith(err)
38+
expect(spy1).toHaveBeenCalled()
39+
done()
40+
})
3441
})
3542

36-
it('async component errors', () => {
43+
it('async component errors', done => {
3744
const err = new Error('foo')
3845
const spy1 = jasmine.createSpy('error')
3946
const spy2 = jasmine.createSpy('errpr')
47+
const spy3 = jasmine.createSpy('promise reject')
4048
const Comp = () => { throw err }
4149
const router = new VueRouter({
4250
routes: [
@@ -47,9 +55,11 @@ describe('error handling', () => {
4755
router.onError(spy1)
4856
router.onReady(() => {}, spy2)
4957

50-
router.push('/')
51-
52-
expect(spy1).toHaveBeenCalledWith(err)
53-
expect(spy2).toHaveBeenCalledWith(err)
58+
router.push('/').catch(spy3).finally(() => {
59+
expect(spy1).toHaveBeenCalledWith(err)
60+
expect(spy2).toHaveBeenCalledWith(err)
61+
expect(spy3).toHaveBeenCalled()
62+
done()
63+
})
5464
})
5565
})

types/router.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export declare class VueRouter {
2525
afterEach (hook: (to: Route, from: Route) => any): Function;
2626
push (location: RawLocation, onComplete?: Function, onAbort?: ErrorHandler): void;
2727
replace (location: RawLocation, onComplete?: Function, onAbort?: ErrorHandler): void;
28+
push (location: RawLocation): Promise<Route>;
29+
replace (location: RawLocation): Promise<Route>;
2830
go (n: number): void;
2931
back (): void;
3032
forward (): void;

0 commit comments

Comments
 (0)