test(runtime-vapor): add vdomInterop tests (#13563)
ci / test (push) Waiting to run Details
ci / continuous-release (push) Waiting to run Details

This commit is contained in:
edison 2025-07-04 11:29:51 +08:00 committed by GitHub
parent bb4ae25793
commit 68fe37a323
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 114 additions and 49 deletions

View File

@ -1,5 +1,5 @@
import { createVaporApp } from '../src'
import type { App } from '@vue/runtime-dom'
import { createVaporApp, vaporInteropPlugin } from '../src'
import { type App, type Component, createApp } from '@vue/runtime-dom'
import type { VaporComponent, VaporComponentInstance } from '../src/component'
import type { RawProps } from '../src/componentProps'
@ -82,3 +82,56 @@ export function makeRender<C = VaporComponent>(
return define
}
export interface InteropRenderContext {
mount: (container?: string | ParentNode) => InteropRenderContext
render: (
props?: RawProps,
container?: string | ParentNode,
) => InteropRenderContext
host: HTMLElement
html: () => string
}
export function makeInteropRender(): (comp: Component) => InteropRenderContext {
let host: HTMLElement
beforeEach(() => {
host = document.createElement('div')
})
afterEach(() => {
host.remove()
})
function define(comp: Component) {
let app: App
function render(
props: RawProps | undefined = undefined,
container: string | ParentNode = host,
) {
app?.unmount()
app = createApp(comp, props)
app.use(vaporInteropPlugin)
return mount(container)
}
function mount(container: string | ParentNode = host) {
app.mount(container)
return res()
}
function html() {
return host.innerHTML
}
const res = () => ({
host,
mount,
render,
html,
})
return res()
}
return define
}

View File

@ -1,11 +1,4 @@
import {
type Ref,
createApp,
defineComponent,
h,
nextTick,
ref,
} from '@vue/runtime-dom'
import { type Ref, nextTick, ref } from '@vue/runtime-dom'
import {
createComponent,
createDynamicComponent,
@ -17,7 +10,6 @@ import {
setProp,
setStyle,
template,
vaporInteropPlugin,
} from '../src'
import { makeRender } from './_utils'
import { stringifyStyle } from '@vue/shared'
@ -407,42 +399,4 @@ describe('attribute fallthrough', () => {
const el = host.children[0]
expect(el.classList.length).toBe(0)
})
it('should not fallthrough emit handlers to vdom child', () => {
const VDomChild = defineComponent({
emits: ['click'],
setup(_, { emit }) {
return () => h('button', { onClick: () => emit('click') }, 'click me')
},
})
const fn = vi.fn()
const VaporChild = defineVaporComponent({
emits: ['click'],
setup() {
return createComponent(
VDomChild as any,
{ onClick: () => fn },
null,
true,
)
},
})
const App = {
setup() {
return () => h(VaporChild as any)
},
}
const root = document.createElement('div')
createApp(App).use(vaporInteropPlugin).mount(root)
expect(root.innerHTML).toBe('<button>click me</button>')
const button = root.querySelector('button')!
button.dispatchEvent(new Event('click'))
// fn should be called once
expect(fn).toHaveBeenCalledTimes(1)
})
})

View File

@ -0,0 +1,58 @@
import { defineComponent, h } from '@vue/runtime-dom'
import { makeInteropRender } from './_utils'
import { createComponent, defineVaporComponent } from '../src'
const define = makeInteropRender()
describe('vdomInterop', () => {
describe.todo('props', () => {})
describe.todo('emit', () => {})
describe.todo('slots', () => {})
describe.todo('provide', () => {})
describe.todo('inject', () => {})
describe.todo('template ref', () => {})
describe.todo('dynamic component', () => {})
describe('attribute fallthrough', () => {
it('should not fallthrough emit handlers to vdom child', () => {
const VDomChild = defineComponent({
emits: ['click'],
setup(_, { emit }) {
return () => h('button', { onClick: () => emit('click') }, 'click me')
},
})
const fn = vi.fn()
const VaporChild = defineVaporComponent({
emits: ['click'],
setup() {
return createComponent(
VDomChild as any,
{ onClick: () => fn },
null,
true,
)
},
})
const { host, html } = define({
setup() {
return () => h(VaporChild as any)
},
}).render()
expect(html()).toBe('<button>click me</button>')
const button = host.querySelector('button')!
button.dispatchEvent(new Event('click'))
// fn should be called once
expect(fn).toHaveBeenCalledTimes(1)
})
})
})