await checkGuards([SingleGuardNamed, SingleGuardNamed], 4)
})
- it('works with async components', async () => {
+ // TODO: async components
+ it.skip('works with async components', async () => {
await checkGuards([makeAsync(NoGuard)], 0)
await checkGuards([makeAsync(SingleGuard)], 1)
await checkGuards([makeAsync(SingleGuard), makeAsync(SingleGuardNamed)], 3)
await router[navigationMethod]('/named')
expect(named.default).toHaveBeenCalledTimes(1)
expect(named.other).toHaveBeenCalledTimes(1)
- expect(router.currentRoute.fullPath).toBe('/named')
+ expect(router.currentRoute.value.fullPath).toBe('/named')
})
it('aborts navigation if one of the named views aborts', async () => {
named.other.mockImplementationOnce(noGuard)
await router[navigationMethod]('/named').catch(err => {}) // catch abort
expect(named.default).toHaveBeenCalledTimes(1)
- expect(router.currentRoute.fullPath).not.toBe('/named')
+ expect(router.currentRoute.value.fullPath).not.toBe('/named')
})
- it('resolves async components before guarding', async () => {
+ // TODO: async components
+ it.skip('resolves async components before guarding', async () => {
const spy = jest.fn(noGuard)
const component = {
template: `<div></div>`,
next()
})
const p = router[navigationMethod]('/foo')
- expect(router.currentRoute.fullPath).toBe('/')
+ expect(router.currentRoute.value.fullPath).toBe('/')
resolve()
await p
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
})
// not implemented yet as it depends on Vue 3 Suspense
const router = createRouter({ routes })
beforeRouteEnter.mockImplementationOnce((to, from, next) => {
next(vm => {
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
expect(vm).toBeTruthy()
done()
})
beforeRouteEnter.mockImplementationOnce(async (to, from, next) => {
await promise
next(vm => {
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
expect(vm).toBeTruthy()
done()
})
expect(nested.nestedNestedFoo).toHaveBeenCalledTimes(1)
})
- it('works when a lazy loaded component', async () => {
+ // TODO: implem async components
+ it.skip('works when a lazy loaded component', async () => {
const router = createRouter({
routes: [
...routes,
})
await router.push('/guard')
const p = router[navigationMethod]('/')
- expect(router.currentRoute.fullPath).toBe('/guard')
+ const currentRoute = router.currentRoute.value
+ expect(currentRoute.fullPath).toBe('/guard')
await p.catch(err => {}) // catch the navigation abortion
- expect(router.currentRoute.fullPath).toBe('/guard')
+ expect(currentRoute.fullPath).toBe('/guard')
})
})
})
expect(beforeRouteUpdate).toHaveBeenCalledTimes(1)
})
- it('resolves async components before guarding', async () => {
+ // TODO: add async component
+ it.skip('resolves async components before guarding', async () => {
const spy = jest.fn((to, from, next) => next())
const component = {
template: `<div></div>`,
})
await router[navigationMethod]('/guard/one')
const p = router[navigationMethod]('/guard/foo')
- expect(router.currentRoute.fullPath).toBe('/guard/one')
+ expect(router.currentRoute.value.fullPath).toBe('/guard/one')
resolve()
await p
- expect(router.currentRoute.fullPath).toBe('/guard/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/guard/foo')
})
})
})
expect.objectContaining({ path: '/foo' }),
expect.any(Function)
)
- expect(router.currentRoute.fullPath).toBe('/other')
+ expect(router.currentRoute.value.fullPath).toBe('/other')
})
async function assertRedirect(redirectFn: (i: string) => RouteLocation) {
expect(spy).not.toHaveBeenCalled()
await router[navigationMethod]('/n/0')
expect(spy).toHaveBeenCalledTimes(4)
- expect(router.currentRoute.fullPath).toBe('/n/3')
+ expect(router.currentRoute.value.fullPath).toBe('/n/3')
}
it('can redirect multiple times with string redirect', async () => {
next()
})
const p = router[navigationMethod]('/foo')
- expect(router.currentRoute.fullPath).toBe('/')
+ expect(router.currentRoute.value.fullPath).toBe('/')
resolve()
await p
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
})
it('waits in the right order', async () => {
})
router.beforeEach(guard2)
let navigation = router[navigationMethod]('/foo')
- expect(router.currentRoute.fullPath).toBe('/')
+ expect(router.currentRoute.value.fullPath).toBe('/')
expect(guard1).not.toHaveBeenCalled()
expect(guard2).not.toHaveBeenCalled()
r1() // resolve the first guard
await tick() // mocha requires an extra tick here
expect(guard1).toHaveBeenCalled()
// we haven't resolved the second gurad yet
- expect(router.currentRoute.fullPath).toBe('/')
+ expect(router.currentRoute.value.fullPath).toBe('/')
r2()
await navigation
expect(guard2).toHaveBeenCalled()
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
})
it('adds meta information', async () => {
next()
})
const p = router[navigationMethod]('/foo')
- expect(router.currentRoute.fullPath).toBe('/')
+ expect(router.currentRoute.value.fullPath).toBe('/')
resolve()
await p
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
})
it('waits before navigating in an array of beforeEnter', async () => {
next()
})
const p = router[navigationMethod]('/multiple')
- expect(router.currentRoute.fullPath).toBe('/')
+ expect(router.currentRoute.value.fullPath).toBe('/')
expect(beforeEnters[1]).not.toHaveBeenCalled()
r1()
await p1
await tick()
r2()
await p
- expect(router.currentRoute.fullPath).toBe('/multiple')
+ expect(router.currentRoute.value.fullPath).toBe('/multiple')
})
})
})
it('can be instantiated', () => {
const history = createMemoryHistory()
const router = createRouter({ history, routes })
- expect(router.currentRoute).toEqual({
+ expect(router.currentRoute.value).toEqual({
name: undefined,
fullPath: '/',
hash: '',
// the second one will have already been resolved
r2()
await pB
- expect(router.currentRoute.fullPath).toBe('/p/b')
+ expect(router.currentRoute.value.fullPath).toBe('/p/b')
r1()
try {
await pA
} catch (err) {
expect(err).toBeInstanceOf(NavigationCancelled)
}
- expect(router.currentRoute.fullPath).toBe('/p/b')
+ expect(router.currentRoute.value.fullPath).toBe('/p/b')
}
it('cancels navigation abort if a newer one is finished on push', async () => {
history.back()
history.back()
- expect(router.currentRoute.fullPath).toBe('/p/b')
+ expect(router.currentRoute.value.fullPath).toBe('/p/b')
// resolves the last call to history.back() first
// so we end up on /p/initial
r1()
await tick()
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
// resolves the pending navigation, this should be cancelled
r2()
await tick()
- expect(router.currentRoute.fullPath).toBe('/foo')
+ expect(router.currentRoute.value.fullPath).toBe('/foo')
}
it('cancels pending navigations if a newer one is finished on user navigation (from history)', async () => {
it('allows base option in abstract history', async () => {
const history = createMemoryHistory('/app/')
const router = createRouter({ history, routes })
- expect(router.currentRoute).toEqual({
+ expect(router.currentRoute.value).toEqual({
name: undefined,
fullPath: '/',
hash: '',
meta: {},
})
await router.replace('/foo')
- expect(router.currentRoute).toMatchObject({
+ expect(router.currentRoute.value).toMatchObject({
name: 'Foo',
fullPath: '/foo',
hash: '',
it('allows base option with html5 history', async () => {
const history = createHistory('/app/')
const router = createRouter({ history, routes })
- expect(router.currentRoute).toEqual({
+ expect(router.currentRoute.value).toEqual({
name: undefined,
fullPath: '/',
hash: '',
meta: {},
})
await router.replace('/foo')
- expect(router.currentRoute).toMatchObject({
+ expect(router.currentRoute.value).toMatchObject({
name: 'Foo',
fullPath: '/foo',
hash: '',
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`SSR: basicRenderer renders the view 1`] = `"<div data-server-rendered=\\"true\\"><div>Home</div></div>"`;
+++ /dev/null
-import { renderApp, renderer } from './shared'
-
-describe('SSR: basicRenderer', () => {
- it('renders the view', async () => {
- const app = await renderApp({ url: '/' })
- const result = await renderer.renderToString(app)
- expect(result).toMatchSnapshot()
- })
-
- /**
- * TODO:
- * - KeepAlive
- * - Suspense
- * - Navigation Guards
- * - Cancelled
- * - Redirection
- * - Async components
- * - Views
- * - Inner components
- */
-
- it('should work', async () => {
- const app = await renderApp(
- { url: '/' },
- {},
- {
- template: `
- <div>
- <p class="hi">yoyo</p>
- <div id="ho" :class="{ red: isRed }"></div>
- <span>{{ test }}</span>
- <input :value="test">
- <img :src="imageUrl">
- <test></test>
- <test-async></test-async>
- </div>
- `,
- data: {
- test: 'hi',
- isRed: true,
- imageUrl: 'https://vuejs.org/images/logo.png',
- },
- components: {
- test: {
- template: `<div class="a">test</div>`,
- },
- testAsync(resolve) {
- resolve({
- render() {
- return this.$createElement(
- 'span',
- { class: ['b'] },
- 'testAsync'
- )
- },
- })
- },
- },
- }
- )
- const result = await renderer.renderToString(app)
-
- expect(result).toContain(
- '<div data-server-rendered="true">' +
- '<p class="hi">yoyo</p> ' +
- '<div id="ho" class="red"></div> ' +
- '<span>hi</span> ' +
- '<input value="hi"> ' +
- '<img src="https://vuejs.org/images/logo.png"> ' +
- '<div class="a">test</div> ' +
- '<span class="b">testAsync</span>' +
- '</div>'
- )
- })
-})
+++ /dev/null
-import Vue, { ComponentOptions } from 'vue'
-import {
- createRouter as newRouter,
- createMemoryHistory,
- plugin,
-} from '../../src'
-import { components } from '../utils'
-
-import { createRenderer } from 'vue-server-renderer'
-import { RouterOptions } from '../../src/router'
-
-Vue.use(plugin)
-
-export const renderer = createRenderer()
-
-export function createRouter(options?: Partial<RouterOptions>) {
- // TODO: a more complex routing that can be used for most tests
- return newRouter({
- history: createMemoryHistory(),
- routes: [
- {
- path: '/',
- component: components.Home,
- },
- {
- path: '/foo',
- component: components.Foo,
- },
- ],
- ...options,
- })
-}
-
-export function createApp(
- routerOptions?: Partial<RouterOptions>,
- options?: any
-) {
- // create router instance
- const router = createRouter(routerOptions)
-
- const app = new Vue({
- // @ts-ignore
- router,
- template: `<div>
- <router-view/>
- </div>`,
- ...options,
- // render: h => h('div', {}, [h('RouterView')]),
- })
-
- // return both the app and the router
- return { app, router }
-}
-
-export function renderApp(
- context: { url: string },
- routerOptions?: Partial<RouterOptions>,
- vueOptions?: ComponentOptions<Vue>
-) {
- return new Promise<ReturnType<typeof createApp>['app']>((resolve, reject) => {
- const { app, router } = createApp(routerOptions, vueOptions)
-
- // wait until router has resolved possible async components and hooks
- router.isReady().then(() => {
- // const matchedComponents = router.getMatchedComponents()
- const matchedComponents = router.currentRoute.matched
- // no matched routes, reject with 404
- if (!matchedComponents.length) {
- return reject({ code: 404 })
- }
-
- // the Promise should resolve to the app instance so it can be rendered
- resolve(app)
- }, reject)
-
- // set server-side router's location
- router.push(context.url).catch(err => {
- console.error('ssr push failed', err)
- })
- })
-}
it('encodes params when resolving', async () => {
const router = createRouter()
await router.push({ name: 'params', params: { p: '%€' } })
- const { currentRoute } = router
+ const currentRoute = router.currentRoute.value
expect(currentRoute.path).toBe(encodeURI('/p/%€'))
expect(currentRoute.fullPath).toBe(encodeURI('/p/%€'))
expect(currentRoute.query).toEqual({