import Router from '../../../src/index' import Vue from 'vue' describe('router.onReady', () => { it('should work', done => { const calls = [] const router = new Router({ mode: 'abstract', routes: [ { path: '/a', component: { name: 'A', beforeRouteEnter: (to, from, next) => { setTimeout(() => { calls.push(2) next() }, 1) } } } ] }) router.beforeEach((to, from, next) => { setTimeout(() => { calls.push(1) next() }, 1) }) router.onReady(() => { expect(calls).toEqual([1, 2]) // sync call when already ready router.onReady(() => { calls.push(3) }) expect(calls).toEqual([1, 2, 3]) done() }) router.push('/a') expect(calls).toEqual([]) }) }) describe('route matching', () => { it('resolves parent params when using current route', () => { const router = new Router({ mode: 'abstract', routes: [ { path: '/a/:id', component: { name: 'A' }, children: [{ name: 'b', path: 'b', component: { name: 'B' }}] } ] }) router.push('/a/1') const { route, resolved } = router.resolve({ name: 'b' }) expect(route.params).toEqual({ id: '1' }) expect(resolved.params).toEqual({ id: '1' }) }) it('can override currentRoute', () => { const router = new Router({ mode: 'abstract', routes: [ { path: '/a/:id', component: { name: 'A' }, children: [{ name: 'b', path: 'b', component: { name: 'B' }}] } ] }) router.push('/a/1') const { route, resolved } = router.resolve({ name: 'b' }, { params: { id: '2' }, path: '/a/2' }) expect(route.params).toEqual({ id: '2' }) expect(resolved.params).toEqual({ id: '2' }) }) }) describe('router.addRoutes', () => { it('should work', () => { const router = new Router({ mode: 'abstract', routes: [ { path: '/a', component: { name: 'A' }} ] }) router.push('/a') let components = router.getMatchedComponents() expect(components.length).toBe(1) expect(components[0].name).toBe('A') router.push('/b') components = router.getMatchedComponents() expect(components.length).toBe(0) router.addRoutes([ { path: '/b', component: { name: 'B' }} ]) components = router.getMatchedComponents() expect(components.length).toBe(1) expect(components[0].name).toBe('B') // make sure it preserves previous routes router.push('/a') components = router.getMatchedComponents() expect(components.length).toBe(1) expect(components[0].name).toBe('A') }) it('allows navigating to the same as current location', () => { const router = new Router({ routes: [ { path: '/', component: {}}, { path: '*', component: {}} ] }) router.push('/not-found') expect(router.currentRoute.params).toEqual({ pathMatch: '/not-found' }) router.addRoutes([{ path: '/not-found', component: {}}]) // the navigation should have changed locations expect(router.currentRoute.params).toEqual({}) }) }) describe('router.push/replace', () => { let calls = [] let router, spy1, spy2 const Foo = { beforeRouteEnter (to, from, next) { calls.push(3) setTimeout(() => { calls.push(4) next() }, 1) } } beforeEach(() => { calls = [] spy1 = jasmine.createSpy('complete') spy2 = jasmine.createSpy('abort') router = new Router({ routes: [ { path: '/foo', component: Foo } ] }) router.beforeEach((to, from, next) => { calls.push(1) setTimeout(() => { calls.push(2) next() }, 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 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 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() }) }) }) 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() }) }) }) }) describe('router app destroy handling', () => { Vue.use(Router) let router, app1, app2, app3 beforeEach(() => { router = new Router({ mode: 'abstract', routes: [ { path: '/', component: { name: 'A' }} ] }) // Add main app app1 = new Vue({ router, render (h) { return h('div') } }) // Add 2nd app app2 = new Vue({ router, render (h) { return h('div') } }) // Add 3rd app app3 = new Vue({ router, render (h) { return h('div') } }) }) it('all apps point to the same router instance', () => { expect(app1.$router).toBe(app2.$router) expect(app2.$router).toBe(app3.$router) }) it('should have all 3 registered apps', () => { expect(app1.$router.app).toBe(app1) expect(app1.$router.apps.length).toBe(3) expect(app1.$router.apps[0]).toBe(app1) expect(app1.$router.apps[1]).toBe(app2) expect(app1.$router.apps[2]).toBe(app3) }) it('should remove 2nd destroyed app from this.apps', () => { app2.$destroy() expect(app1.$router.app).toBe(app1) expect(app1.$router.apps.length).toBe(2) expect(app1.$router.apps[0]).toBe(app1) expect(app1.$router.apps[1]).toBe(app3) }) it('should remove 1st destroyed app and replace current app', () => { app1.$destroy() expect(app3.$router.app).toBe(app2) expect(app3.$router.apps.length).toBe(2) expect(app3.$router.apps[0]).toBe(app2) expect(app1.$router.apps[1]).toBe(app3) }) it('should remove all apps', () => { app1.$destroy() app3.$destroy() app2.$destroy() expect(app3.$router.app).toBe(null) expect(app3.$router.apps.length).toBe(0) }) it('should keep current app if already defined', () => { const app4 = new Vue({ router, render (h) { return h('div') } }) expect(app4.$router.app).toBe(app1) expect(app4.$router.apps.length).toBe(4) expect(app4.$router.apps[3]).toBe(app4) }) it('should replace current app if none is assigned when creating the app', () => { app1.$destroy() app3.$destroy() app2.$destroy() const app4 = new Vue({ router, render (h) { return h('div') } }) expect(router.app).toBe(app4) expect(app4.$router).toBe(router) expect(app4.$router.apps.length).toBe(1) expect(app4.$router.apps[0]).toBe(app4) }) })