import { START_LOCATION_NORMALIZED } from '../src/types'
import { ref, markNonReactive } from 'vue'
import { mount, tick } from './mount'
+import { mockWarn } from 'jest-mock-warn'
-const routes: Record<string, RouteLocationNormalizedLoose> = {
+// to have autocompletion
+function createRoutes<T extends Record<string, RouteLocationNormalizedLoose>>(
+ routes: T
+): T {
+ return routes
+}
+
+const routes = createRoutes({
root: {
fullPath: '/',
name: undefined,
meta: {},
matched: [{ components: { foo: components.Foo }, path: '/' }],
},
-}
+ withParams: {
+ fullPath: '/users/3',
+ name: undefined,
+ path: '/users/3',
+ query: {},
+ params: { id: '1' },
+ hash: '',
+ meta: {},
+ matched: [
+ {
+ components: { default: components.User },
+ path: '/users/:id',
+ props: true,
+ },
+ ],
+ },
+})
describe('RouterView', () => {
+ mockWarn()
+
function factory(route: RouteLocationNormalizedLoose, props: any = {}) {
const router = {
- currentRoute: ref(markNonReactive(route)),
+ currentRoute: ref(markNonReactive({ ...route })),
}
const { app, el } = mount(
it('displays nothing when route is unmatched', () => {
const { el } = factory(START_LOCATION_NORMALIZED as any)
// NOTE: I wonder if this will stay stable in future releases
+ expect('Router').not.toHaveBeenWarned()
expect(el.childElementCount).toBe(0)
})
await tick()
expect(el.innerHTML).toBe(`<div>Foo</div>`)
})
+
+ it('does not pass params as props by default', async () => {
+ let noPropsWithParams = {
+ ...routes.withParams,
+ matched: [{ ...routes.withParams.matched[0], props: false }],
+ }
+ const { el, router } = factory(noPropsWithParams)
+ expect(el.innerHTML).toBe(`<div>User: default</div>`)
+ router.currentRoute.value = { ...noPropsWithParams, params: { id: '4' } }
+ await tick()
+ expect(el.innerHTML).toBe(`<div>User: default</div>`)
+ })
+
+ it('passes params as props with props: true', async () => {
+ const { el, router } = factory(routes.withParams)
+ expect(el.innerHTML).toBe(`<div>User: 1</div>`)
+ router.currentRoute.value = { ...routes.withParams, params: { id: '4' } }
+ await tick()
+ expect(el.innerHTML).toBe(`<div>User: 4</div>`)
+ })
})
RouteRecordMultipleViews,
MatcherLocationNormalized,
RouteLocationNormalized,
+ RouteRecordCommon,
} from '../src/types'
-import { h, resolveComponent } from 'vue'
+import { h, resolveComponent, defineComponent } from 'vue'
export const tick = (time?: number) =>
new Promise(resolve => {
'path' | 'name' | 'components' | 'children' | 'meta' | 'beforeEnter'
> {
leaveGuards?: any
+ props?: RouteRecordCommon['props']
aliasOf: RouteRecordViewLoose | undefined
}
Home: { render: () => h('div', {}, 'Home') },
Foo: { render: () => h('div', {}, 'Foo') },
Bar: { render: () => h('div', {}, 'Bar') },
+ User: defineComponent({
+ props: {
+ id: {
+ default: 'default',
+ },
+ },
+ render() {
+ return h('div', {}, 'User: ' + this.id)
+ },
+ }),
Nested: {
render: () => {
const RouterView = resolveComponent('RouterView')
() => matchedRoute.value && matchedRoute.value.components[props.name]
)
+ const propsData = computed(() => {
+ if (!matchedRoute.value.props) return {}
+
+ return route.value.params
+ })
+
provide(matchedRouteKey, matchedRoute)
return () => {
return ViewComponent.value
- ? h(ViewComponent.value as any, { ...attrs })
+ ? h(ViewComponent.value as any, { ...propsData.value, ...attrs })
: null
}
},
children: (record as any).children || [],
name: record.name,
beforeEnter,
+ props: record.props || false,
meta: record.meta || {},
leaveGuards: [],
aliasOf: undefined,
-import { RouteRecordMultipleViews, NavigationGuard } from '../types'
+import {
+ RouteRecordMultipleViews,
+ NavigationGuard,
+ RouteRecordCommon,
+} from '../types'
// normalize component/components into components and make every property always present
export interface RouteRecordNormalized {
components: RouteRecordMultipleViews['components']
children: Exclude<RouteRecordMultipleViews['children'], void>
meta: Exclude<RouteRecordMultipleViews['meta'], void>
+ props: Exclude<RouteRecordCommon['props'], void>
beforeEnter: RouteRecordMultipleViews['beforeEnter']
leaveGuards: NavigationGuard[]
aliasOf: RouteRecordNormalized | undefined
path: string
alias?: string | string[]
name?: string
+ props?: boolean
// TODO: beforeEnter has no effect with redirect, move and test
beforeEnter?: NavigationGuard | NavigationGuard[]
meta?: Record<string | number | symbol, any>
)
// make matched non enumerable for easy printing
-Object.defineProperty(START_LOCATION_NORMALIZED, 'matched', {
- enumerable: false,
-})
+// NOTE: commented for tests at RouterView.spec
+// Object.defineProperty(START_LOCATION_NORMALIZED, 'matched', {
+// enumerable: false,
+// })
// Matcher types
// the matcher doesn't care about query and hash