mirror of https://github.com/vuejs/core.git
wip: add tests
This commit is contained in:
parent
b9620e8473
commit
7070f33300
|
@ -2,6 +2,10 @@ import { createVaporApp } from '../src'
|
|||
import type { App } from '@vue/runtime-dom'
|
||||
import type { VaporComponent, VaporComponentInstance } from '../src/component'
|
||||
import type { RawProps } from '../src/componentProps'
|
||||
import { compileScript, parse } from '@vue/compiler-sfc'
|
||||
import * as runtimeVapor from '../src'
|
||||
import * as runtimeDom from '@vue/runtime-dom'
|
||||
import * as VueServerRenderer from '@vue/server-renderer'
|
||||
|
||||
export interface RenderContext {
|
||||
component: VaporComponent
|
||||
|
@ -82,3 +86,50 @@ export function makeRender<C = VaporComponent>(
|
|||
|
||||
return define
|
||||
}
|
||||
|
||||
export { runtimeDom, runtimeVapor }
|
||||
export function compile(
|
||||
sfc: string,
|
||||
data: runtimeDom.Ref<any>,
|
||||
components: Record<string, any> = {},
|
||||
{
|
||||
vapor = true,
|
||||
ssr = false,
|
||||
}: {
|
||||
vapor?: boolean | undefined
|
||||
ssr?: boolean | undefined
|
||||
} = {},
|
||||
): any {
|
||||
if (!sfc.includes(`<script`)) {
|
||||
sfc =
|
||||
`<script vapor>const data = _data; const components = _components;</script>` +
|
||||
sfc
|
||||
}
|
||||
const descriptor = parse(sfc).descriptor
|
||||
|
||||
const script = compileScript(descriptor, {
|
||||
id: 'x',
|
||||
isProd: true,
|
||||
inlineTemplate: true,
|
||||
genDefaultAs: '__sfc__',
|
||||
vapor,
|
||||
templateOptions: {
|
||||
ssr,
|
||||
},
|
||||
})
|
||||
|
||||
const code =
|
||||
script.content
|
||||
.replace(/\bimport {/g, 'const {')
|
||||
.replace(/ as _/g, ': _')
|
||||
.replace(/} from ['"]vue['"]/g, `} = Vue`)
|
||||
.replace(/} from "vue\/server-renderer"/g, '} = VueServerRenderer') +
|
||||
'\nreturn __sfc__'
|
||||
|
||||
return new Function('Vue', 'VueServerRenderer', '_data', '_components', code)(
|
||||
{ ...runtimeDom, ...runtimeVapor },
|
||||
VueServerRenderer,
|
||||
data,
|
||||
components,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,11 +5,12 @@ import {
|
|||
createIf,
|
||||
createSlot,
|
||||
createTemplateRefSetter,
|
||||
delegateEvents,
|
||||
insert,
|
||||
renderEffect,
|
||||
template,
|
||||
} from '../../src'
|
||||
import { makeRender } from '../_utils'
|
||||
import { compile, makeRender, runtimeDom, runtimeVapor } from '../_utils'
|
||||
import {
|
||||
type ShallowRef,
|
||||
currentInstance,
|
||||
|
@ -716,3 +717,227 @@ describe('api: template ref', () => {
|
|||
// expect(elRef1.value).toBe(elRef2.value)
|
||||
// })
|
||||
})
|
||||
|
||||
describe('interop: template ref', () => {
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
const triggerEvent = (type: string, el: Element) => {
|
||||
const event = new Event(type, { bubbles: true })
|
||||
el.dispatchEvent(event)
|
||||
}
|
||||
|
||||
delegateEvents('click')
|
||||
|
||||
async function testTemplateRefInterop(
|
||||
code: string,
|
||||
components: Record<string, { code: string; vapor: boolean }> = {},
|
||||
data: any = {},
|
||||
{ vapor = false } = {},
|
||||
) {
|
||||
const clientComponents: any = {}
|
||||
for (const key in components) {
|
||||
const comp = components[key]
|
||||
const code = comp.code
|
||||
const isVaporComp = !!comp.vapor
|
||||
clientComponents[key] = compile(code, data, clientComponents, {
|
||||
vapor: isVaporComp,
|
||||
})
|
||||
}
|
||||
|
||||
const clientComp = compile(code, data, clientComponents, {
|
||||
vapor,
|
||||
})
|
||||
|
||||
const app = (vapor ? runtimeVapor.createVaporApp : runtimeDom.createApp)(
|
||||
clientComp,
|
||||
)
|
||||
app.use(runtimeVapor.vaporInteropPlugin)
|
||||
|
||||
const container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
app.mount(container)
|
||||
return { container }
|
||||
}
|
||||
|
||||
test('vdom app: useTemplateRef on vapor child', async () => {
|
||||
const { container } = await testTemplateRefInterop(
|
||||
`<script setup>
|
||||
import { useTemplateRef } from 'vue'
|
||||
const data = _data; const components = _components;
|
||||
const elRef = useTemplateRef('el')
|
||||
function click() {
|
||||
elRef.value.change()
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<button class="btn" @click="click"></button>
|
||||
<components.VaporChild ref="el"/>
|
||||
</template>`,
|
||||
{
|
||||
VaporChild: {
|
||||
code: `
|
||||
<script vapor>
|
||||
import { ref } from 'vue'
|
||||
const msg = ref('foo')
|
||||
function change(){
|
||||
msg.value = 'bar'
|
||||
}
|
||||
defineExpose({ change })
|
||||
</script>
|
||||
<template><div>{{msg}}</div></template>
|
||||
`,
|
||||
vapor: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>foo</div>`,
|
||||
)
|
||||
|
||||
const btn = container.querySelector('.btn')
|
||||
triggerEvent('click', btn!)
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>bar</div>`,
|
||||
)
|
||||
})
|
||||
|
||||
test('vdom app: static ref on vapor child', async () => {
|
||||
const { container } = await testTemplateRefInterop(
|
||||
`<script setup>
|
||||
import { ref } from 'vue'
|
||||
const data = _data; const components = _components;
|
||||
const elRef = ref(null)
|
||||
function click() {
|
||||
elRef.value.change()
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<button class="btn" @click="click"></button>
|
||||
<components.VaporChild ref="elRef"/>
|
||||
</template>`,
|
||||
{
|
||||
VaporChild: {
|
||||
code: `
|
||||
<script vapor>
|
||||
import { ref } from 'vue'
|
||||
const msg = ref('foo')
|
||||
function change(){
|
||||
msg.value = 'bar'
|
||||
}
|
||||
defineExpose({ change })
|
||||
</script>
|
||||
<template><div>{{msg}}</div></template>
|
||||
`,
|
||||
vapor: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>foo</div>`,
|
||||
)
|
||||
|
||||
const btn = container.querySelector('.btn')
|
||||
triggerEvent('click', btn!)
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>bar</div>`,
|
||||
)
|
||||
})
|
||||
|
||||
test('vapor app: useTemplateRef on vdom child', async () => {
|
||||
const { container } = await testTemplateRefInterop(
|
||||
`<script vapor>
|
||||
import { useTemplateRef } from 'vue'
|
||||
const data = _data; const components = _components;
|
||||
const elRef = useTemplateRef('el')
|
||||
function click() {
|
||||
elRef.value.change()
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<button class="btn" @click="click"></button>
|
||||
<components.VDOMChild ref="el"/>
|
||||
</template>`,
|
||||
{
|
||||
VDOMChild: {
|
||||
code: `
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const msg = ref('foo')
|
||||
function change(){
|
||||
msg.value = 'bar'
|
||||
}
|
||||
defineExpose({ change })
|
||||
</script>
|
||||
<template><div>{{msg}}</div></template>
|
||||
`,
|
||||
vapor: false,
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
{ vapor: true },
|
||||
)
|
||||
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>foo</div>`,
|
||||
)
|
||||
|
||||
const btn = container.querySelector('.btn')
|
||||
triggerEvent('click', btn!)
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>bar</div>`,
|
||||
)
|
||||
})
|
||||
|
||||
test('vapor app: static ref on vdom child', async () => {
|
||||
const { container } = await testTemplateRefInterop(
|
||||
`<script vapor>
|
||||
import { ref } from 'vue'
|
||||
const data = _data; const components = _components;
|
||||
const elRef = ref(null)
|
||||
function click() {
|
||||
elRef.value.change()
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<button class="btn" @click="click"></button>
|
||||
<components.VDomChild ref="elRef"/>
|
||||
</template>`,
|
||||
{
|
||||
VDomChild: {
|
||||
code: `
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
const msg = ref('foo')
|
||||
function change(){
|
||||
msg.value = 'bar'
|
||||
}
|
||||
defineExpose({ change })
|
||||
</script>
|
||||
<template><div>{{msg}}</div></template>
|
||||
`,
|
||||
vapor: false,
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
{ vapor: true },
|
||||
)
|
||||
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>foo</div>`,
|
||||
)
|
||||
|
||||
const btn = container.querySelector('.btn')
|
||||
triggerEvent('click', btn!)
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toBe(
|
||||
`<button class="btn"></button><div>bar</div>`,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -30,7 +30,7 @@ import {
|
|||
unmountComponent,
|
||||
} from './component'
|
||||
import { type Block, VaporFragment, insert, remove } from './block'
|
||||
import { EMPTY_OBJ, extend, isFunction } from '@vue/shared'
|
||||
import { EMPTY_OBJ, extend, isFunction, isReservedProp } from '@vue/shared'
|
||||
import { type RawProps, rawPropsProxyHandlers } from './componentProps'
|
||||
import type { RawSlots, VaporSlot } from './componentSlots'
|
||||
import { renderEffect } from './renderEffect'
|
||||
|
@ -49,7 +49,15 @@ const vaporInteropImpl: Omit<
|
|||
const prev = currentInstance
|
||||
simpleSetCurrentInstance(parentComponent)
|
||||
|
||||
const propsRef = shallowRef(vnode.props)
|
||||
// filter out reserved props
|
||||
const props: VNode['props'] = {}
|
||||
for (const key in vnode.props) {
|
||||
if (!isReservedProp(key)) {
|
||||
props[key] = vnode.props[key]
|
||||
}
|
||||
}
|
||||
|
||||
const propsRef = shallowRef(props)
|
||||
const slotsRef = shallowRef(vnode.children)
|
||||
|
||||
// @ts-expect-error
|
||||
|
|
Loading…
Reference in New Issue