RouteLocationNormalized,
} from '../src/types'
import { createMemoryHistory, RouterOptions } from '../src'
-import { mount, createMockedRoute } from './mount'
-import { defineComponent, nextTick, PropType } from 'vue'
+import { createMockedRoute } from './mount'
+import { defineComponent, PropType } from 'vue'
import { RouteRecordNormalized } from '../src/matcher/types'
import { routerKey } from '../src/injectionSymbols'
import { tick } from './utils'
+import { mount } from '@vue/test-utils'
const records = {
home: {} as RouteRecordNormalized,
}
router.resolve.mockReturnValueOnce(resolvedLocation)
- const wrapper = await mount(RouterLink, {
+ const wrapper = mount(RouterLink as any, {
propsData,
- provide: {
- [routerKey as any]: router,
- ...route.provides,
+ global: {
+ provide: {
+ [routerKey as any]: router,
+ ...route.provides,
+ },
},
slots: { default: slotTemplate },
})
{ to: locations.basic.string },
locations.basic.normalized
)
- expect(wrapper.find('a')!.getAttribute('href')).toBe('/home')
+ expect(wrapper.find('a')!.attributes('href')).toBe('/home')
})
it('can change the value', async () => {
{ to: locations.basic.string },
locations.basic.normalized
)
- expect(wrapper.find('a')!.getAttribute('href')).toBe('/home')
+ expect(wrapper.find('a')!.attributes('href')).toBe('/home')
router.resolve.mockReturnValueOnce(locations.foo.normalized)
await wrapper.setProps({ to: locations.foo.string })
- expect(wrapper.find('a')!.getAttribute('href')).toBe('/foo')
+ expect(wrapper.find('a')!.attributes('href')).toBe('/foo')
})
it('displays a link with an object with path prop', async () => {
{ to: { path: locations.basic.string } },
locations.basic.normalized
)
- expect(wrapper.find('a')!.getAttribute('href')).toBe('/home')
+ expect(wrapper.find('a')!.attributes('href')).toBe('/home')
})
it('can be active', async () => {
{ to: locations.basic.string },
locations.basic.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
+ expect(wrapper.find('a').classes()).toContain('router-link-active')
})
it('sets aria-current to page by default when exact active', async () => {
{ to: locations.parent.string },
locations.parent.normalized
)
- expect(wrapper.find('a')!.getAttribute('aria-current')).toBe('page')
+ expect(wrapper.find('a')!.attributes('aria-current')).toBe('page')
route.set(locations.child.normalized)
await tick()
- expect(wrapper.find('a')!.getAttribute('aria-current')).not.toBe('page')
+ expect(wrapper.find('a')!.attributes('aria-current')).not.toBe('page')
})
it('can customize aria-current value', async () => {
{ to: locations.basic.string, ariaCurrentValue: 'time' },
locations.basic.normalized
)
- expect(wrapper.find('a')!.getAttribute('aria-current')).toBe('time')
+ expect(wrapper.find('a')!.attributes('aria-current')).toBe('time')
})
it('can customize active class', async () => {
{ to: locations.basic.string, activeClass: 'is-active' },
locations.basic.normalized
)
- expect(wrapper.find('a')!.className).not.toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('is-active')
+ expect(wrapper.find('a')!.classes()).not.toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('is-active')
})
it('prop classes take over global', async () => {
// force render because options is not reactive
router.resolve.mockReturnValueOnce(locations.basic.normalized)
await wrapper.setProps({ to: locations.basic.string })
- expect(wrapper.find('a')!.className).not.toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).not.toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
- expect(wrapper.find('a')!.className).not.toContain('custom')
- expect(wrapper.find('a')!.className).not.toContain('custom-exact')
- expect(wrapper.find('a')!.className).toContain('is-active')
- expect(wrapper.find('a')!.className).toContain('is-exact')
+ expect(wrapper.find('a')!.classes()).not.toContain('custom')
+ expect(wrapper.find('a')!.classes()).not.toContain('custom-exact')
+ expect(wrapper.find('a')!.classes()).toContain('is-active')
+ expect(wrapper.find('a')!.classes()).toContain('is-exact')
})
it('can globally customize active class', async () => {
// force render because options is not reactive
router.resolve.mockReturnValueOnce(locations.basic.normalized)
await wrapper.setProps({ to: locations.basic.string })
- expect(wrapper.find('a')!.className).not.toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('custom')
+ expect(wrapper.find('a')!.classes()).not.toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('custom')
})
it('can globally customize exact active class', async () => {
// force render because options is not reactive
router.resolve.mockReturnValueOnce(locations.basic.normalized)
await wrapper.setProps({ to: locations.basic.string })
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
- expect(wrapper.find('a')!.className).toContain('custom')
+ expect(wrapper.find('a')!.classes()).toContain('custom')
})
it('can customize exact active class', async () => {
{ to: locations.basic.string, exactActiveClass: 'is-active' },
locations.basic.normalized
)
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
- expect(wrapper.find('a')!.className).toContain('is-active')
+ expect(wrapper.find('a')!.classes()).toContain('is-active')
})
it('can be active with custom class', async () => {
{ to: locations.basic.string, class: 'nav-item' },
locations.basic.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('nav-item')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('nav-item')
})
it('is not active on a non matched location', async () => {
{ to: locations.basic.string },
locations.basic.normalized
)
- expect(wrapper.find('a')!.className).toBe('')
+ expect(wrapper.find('a')!.classes()).toHaveLength(0)
})
it('is not active with different params type', async () => {
{ to: locations.singleStringParams.string },
locations.singleStringParams.normalized
)
- expect(wrapper.find('a')!.className).toBe('')
+ expect(wrapper.find('a')!.classes()).toHaveLength(0)
})
it('is not active with different repeated params', async () => {
{ to: locations.anotherRepeatedParams2.string },
locations.anotherRepeatedParams2.normalized
)
- expect(wrapper.find('a')!.className).toBe('')
+ expect(wrapper.find('a')!.classes()).toHaveLength(0)
})
it('is not active with more repeated params', async () => {
{ to: locations.repeatedParams3.string },
locations.repeatedParams3.normalized
)
- expect(wrapper.find('a')!.className).toBe('')
+ expect(wrapper.find('a')!.classes()).toHaveLength(0)
})
it('is not active with partial repeated params', async () => {
{ to: locations.repeatedParams2.string },
locations.repeatedParams2.normalized
)
- expect(wrapper.find('a')!.className).toBe('')
+ expect(wrapper.find('a')!.classes()).toHaveLength(0)
})
it('can be active as an alias', async () => {
{ to: locations.alias.string },
locations.alias.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
wrapper = (
await factory(
locations.alias.normalized,
locations.basic.normalized
)
).wrapper
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
})
it('is active when a child is active', async () => {
{ to: locations.parent.string },
locations.parent.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.child.string },
locations.child.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
})
it('child is not active if the parent is active', async () => {
{ to: locations.child.string },
locations.child.normalized
)
- expect(wrapper.find('a')!.className).not.toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).not.toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.parent.string },
locations.parent.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.childEmpty.string },
locations.childEmpty.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.childEmptyAlias.string },
locations.childEmptyAlias.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.childEmpty.string },
locations.childEmpty.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.childEmptyAlias.string },
locations.childEmptyAlias.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.parentAlias.string },
locations.parentAlias.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.parentAlias.string },
locations.parentAlias.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
wrapper = (
locations.parentAlias.normalized
)
).wrapper
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).not.toContain(
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).not.toContain(
'router-link-exact-active'
)
})
{ to: locations.parentAlias.string },
locations.parentAlias.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
wrapper = (
await factory(
locations.parent.normalized
)
).wrapper
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
})
it('child and parent with alias', async () => {
{ to: locations.childDoubleAlias.string },
locations.childDoubleAlias.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
wrapper = (
await factory(
locations.childParentAlias.normalized
)
).wrapper
- expect(wrapper.find('a')!.className).toContain('router-link-active')
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
})
it('can be exact-active', async () => {
{ to: locations.basic.string },
locations.basic.normalized
)
- expect(wrapper.find('a')!.className).toContain('router-link-exact-active')
+ expect(wrapper.find('a')!.classes()).toContain('router-link-exact-active')
})
it('calls ensureLocation', async () => {
{ to: locations.basic.string },
locations.basic.normalized
)
- wrapper.find('a')!.click()
- await nextTick()
+ wrapper.find('a')!.trigger('click')
expect(router.push).toHaveBeenCalledTimes(1)
})
{ to: locations.alias.string },
locations.alias.normalized
)
- wrapper.find('a')!.click()
- await nextTick()
+ wrapper.find('a')!.trigger('click')
expect(router.push).toHaveBeenCalledTimes(1)
expect(router.push).not.toHaveBeenCalledWith(
expect.objectContaining({
describe('v-slot', () => {
const slotTemplate = `
+ <template #default="{ route, href, isActive, isExactActive }">
<span>
route: {{ JSON.stringify(route) }}
href: "{{ href }}"
isActive: "{{ isActive }}"
isExactActive: "{{ isExactActive }}"
</span>
+ </template>
`
it('provides information on v-slot', async () => {
slotTemplate
)
- expect(wrapper.rootEl.children[0].tagName).toBe('A')
- expect(wrapper.rootEl.children).toHaveLength(1)
+ expect(wrapper.element.tagName).toBe('A')
+ expect(wrapper.element.childElementCount).toBe(1)
})
it('can customize the rendering and remove the wrapping `a`', async () => {
}
router.resolve.mockReturnValueOnce(resolvedLocation)
- const wrapper = await mount(AppLink, {
+ const wrapper = await mount(AppLink as any, {
propsData,
- provide: {
- [routerKey as any]: router,
- ...route.provides,
+ global: {
+ provide: {
+ [routerKey as any]: router,
+ ...route.provides,
+ },
},
slots: { default: slotTemplate },
})
locations.foo.normalized
)
- expect(wrapper.find('a')!.className).toEqual('inactive')
+ expect(wrapper.find('a')!.classes()).toEqual(['inactive'])
})
it('can extend RouterLink with external link', async () => {
locations.foo.normalized
)
- expect(wrapper.find('a')!.className).toEqual('')
- expect(wrapper.find('a')!.href).toEqual('https://esm.dev/')
+ expect(wrapper.find('a')!.classes()).toHaveLength(0)
+ expect(wrapper.find('a')!.attributes('href')).toEqual('https://esm.dev')
})
})
})
RouteLocationNormalized,
} from '../src/types'
import { markRaw } from 'vue'
-import { mount, createMockedRoute } from './mount'
+import { createMockedRoute } from './mount'
import { mockWarn } from 'jest-mock-warn'
+import { mount } from '@vue/test-utils'
// to have autocompletion
function createRoutes<T extends Record<string, RouteLocationNormalizedLoose>>(
propsData: any = {}
) {
const route = createMockedRoute(initialRoute)
- const wrapper = await mount(RouterView, {
+ const wrapper = mount(RouterView as any, {
propsData,
- provide: route.provides,
- components: { RouterView },
+ global: {
+ provide: route.provides,
+ components: { RouterView },
+ },
})
return { route, wrapper }
const { wrapper } = await factory(START_LOCATION_NORMALIZED as any)
// NOTE: I wonder if this will stay stable in future releases
expect('Router').not.toHaveBeenWarned()
- expect(wrapper.rootEl.childElementCount).toBe(0)
+ expect(wrapper.element.childNodes).toHaveLength(0)
})
it('displays nested views', async () => {
})
describe('warnings', () => {
- it('does not warn RouterView is wrapped', async () => {
+ it('does not warn RouterView is wrapped', () => {
const route = createMockedRoute(routes.root)
- const wrapper = await mount(
+ const wrapper = mount(
{
template: `
<div>
},
{
propsData: {},
- provide: route.provides,
- components: { RouterView },
+ global: {
+ provide: route.provides,
+ components: { RouterView },
+ },
}
)
expect(wrapper.html()).toBe(`<div><div>Home</div></div>`)
expect('can no longer be used directly inside').not.toHaveBeenWarned()
})
- it('warns if KeepAlive wraps a RouterView', async () => {
+ it('warns if KeepAlive wraps a RouterView', () => {
const route = createMockedRoute(routes.root)
- const wrapper = await mount(
+ const wrapper = mount(
{
template: `
<keep-alive>
},
{
propsData: {},
- provide: route.provides,
- components: { RouterView },
+ global: {
+ provide: route.provides,
+ components: { RouterView },
+ },
}
)
expect(wrapper.html()).toBe(`<div>Home</div>`)
it('warns if KeepAlive and Transition wrap a RouterView', async () => {
const route = createMockedRoute(routes.root)
- const wrapper = await mount(
+ const wrapper = mount(
{
template: `
<transition>
},
{
propsData: {},
- provide: route.provides,
- components: { RouterView },
+ global: {
+ stubs: {
+ transition: false,
+ },
+ provide: route.provides,
+ components: { RouterView },
+ },
}
)
expect(wrapper.html()).toBe(`<div>Home</div>`)
expect('can no longer be used directly inside').toHaveBeenWarned()
})
- it('warns if Transition wraps a RouterView', async () => {
+ it('warns if Transition wraps a RouterView', () => {
const route = createMockedRoute(routes.root)
- const wrapper = await mount(
+ const wrapper = mount(
{
template: `
<transition>
},
{
propsData: {},
- provide: route.provides,
- components: { RouterView },
+ global: {
+ stubs: {
+ transition: false,
+ },
+ provide: route.provides,
+ components: { RouterView },
+ },
}
)
expect(wrapper.html()).toBe(`<div>Home</div>`)
propsData: any = {}
) {
const route = createMockedRoute(initialRoute)
- const wrapper = await mount(RouterView, {
+ const wrapper = await mount(RouterView as any, {
propsData,
- provide: route.provides,
- components: { RouterView },
+ global: {
+ provide: route.provides,
+ components: { RouterView },
+ },
slots: {
default: `
- <span>{{ route.name }}</span>
- <component :is="Component"/>
- `,
+ <template #default="{ route, Component }">
+ <span>{{ route.name }}</span>
+ <component :is="Component"/>
+ </template>`,
},
})
propsData: any = {}
) {
const route = createMockedRoute(initialRoute)
- const wrapper = await mount(RouterView, {
+ const wrapper = await mount(RouterView as any, {
propsData,
- provide: route.provides,
- components: { RouterView },
+ global: {
+ provide: route.provides,
+ components: { RouterView },
+ },
slots: {
default: `
- <keep-alive>
- <component :is="Component"/>
- </keep-alive>
- `,
+ <template #default="{ Component }">
+ <keep-alive>
+ <component :is="Component"/>
+ </keep-alive>
+ </template>`,
},
})
-import {
- createApp,
- defineComponent,
- h,
- ComponentPublicInstance,
- reactive,
- nextTick,
- ComponentObjectPropsOptions,
- ComputedRef,
- computed,
- App,
- VNode,
- shallowRef,
- ComponentOptions,
-} from 'vue'
-import { compile } from '@vue/compiler-dom'
-import * as runtimeDom from '@vue/runtime-dom'
+import { reactive, nextTick, ComputedRef, computed, shallowRef } from 'vue'
import { RouteLocationNormalizedLoose } from './utils'
import {
routeLocationKey,
routerViewLocationKey,
} from '../src/injectionSymbols'
-import { Router } from '../src'
-
-export interface MountOptions {
- propsData: Record<string, any>
- provide: Record<string | symbol, any>
- components: ComponentOptions['components']
- slots: Record<string, string>
- router?: Router
-}
-
-interface Wrapper {
- app: App
- vm: ComponentPublicInstance
- rootEl: HTMLDivElement
- setProps(props: MountOptions['propsData']): Promise<void>
- html(): string
- find: typeof document['querySelector']
-}
-
-function initialProps<P>(propsOption: ComponentObjectPropsOptions<P>) {
- let copy = {} as ComponentPublicInstance<typeof propsOption>['$props']
-
- for (let key in propsOption) {
- const prop = propsOption[key]!
- // @ts-ignore
- if (!prop.required && prop.default)
- // @ts-ignore
- copy[key] = prop.default
- }
-
- return copy
-}
-
-// cleanup wrappers after a suite runs
-let activeWrapperRemovers: Array<() => void> = []
-afterAll(() => {
- activeWrapperRemovers.forEach(remove => remove())
- activeWrapperRemovers = []
-})
-
-export function mount(
- targetComponent: Parameters<typeof createApp>[0],
- options: Partial<MountOptions> = {}
-): Promise<Wrapper> {
- const TargetComponent = targetComponent
- return new Promise(resolve => {
- // NOTE: only supports props as an object
- const propsData = reactive(
- Object.assign(
- initialProps(
- // @ts-ignore
- TargetComponent.props || {}
- ),
- options.propsData
- )
- )
-
- function setProps(partialProps: Record<string, any>) {
- Object.assign(propsData, partialProps)
- return nextTick()
- }
-
- let slots: Record<string, (propsData: any) => VNode> = {}
-
- const Wrapper = defineComponent({
- setup(_props, { emit }) {
- const componentInstanceRef = shallowRef<ComponentPublicInstance>()
-
- return () => {
- return h(
- TargetComponent as any,
- {
- ref: componentInstanceRef,
- onVnodeMounted() {
- emit('ready', componentInstanceRef.value)
- },
- ...propsData,
- },
- slots
- )
- }
- },
- })
-
- const app = createApp(Wrapper, {
- onReady: (instance: ComponentPublicInstance) => {
- resolve({ app, vm: instance!, rootEl, setProps, html, find })
- },
- })
-
- if (options.provide) {
- const keys = getKeys(options.provide)
-
- for (let key of keys) {
- app.provide(key, options.provide[key as any])
- }
- }
-
- if (options.components) {
- for (let key in options.components) {
- app.component(key, options.components[key])
- }
- }
-
- if (options.slots) {
- for (let key in options.slots) {
- slots[key] = compileSlot(options.slots[key])
- }
- }
-
- const rootEl = document.createElement('div')
- document.body.appendChild(rootEl)
-
- function html() {
- return rootEl.innerHTML
- }
-
- function find(selector: string) {
- return rootEl.querySelector(selector)
- }
-
- if (options.router) app.use(options.router)
-
- app.mount(rootEl)
-
- activeWrapperRemovers.push(() => {
- app.unmount(rootEl)
- rootEl.remove()
- })
- })
-}
-
-function getKeys(object: Record<string | symbol, any>): Array<symbol | string> {
- return (Object.getOwnPropertyNames(object) as Array<string | symbol>).concat(
- Object.getOwnPropertySymbols(object)
- )
-}
export function createMockedRoute(initialValue: RouteLocationNormalizedLoose) {
const route = {} as {
},
}
}
-
-function compileSlot(template: string) {
- const codegen = compile(template, {
- mode: 'function',
- hoistStatic: true,
- prefixIdentifiers: true,
- })
-
- const render = new Function('Vue', codegen.code)(runtimeDom)
-
- const ToRender = defineComponent({
- render,
- inheritAttrs: false,
-
- setup(props, { attrs }) {
- return { ...attrs }
- },
- })
-
- return (propsData: any) => h(ToRender, { ...propsData })
-}