Skip to content

Commit d184928

Browse files
committed
wip: add interop tests
1 parent d5d8ada commit d184928

File tree

10 files changed

+265
-53
lines changed

10 files changed

+265
-53
lines changed

packages-private/vapor-e2e-test/__tests__/transition.spec.ts

+12-39
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@ import {
55
} from '../../../packages/vue/__tests__/e2e/e2eUtils'
66
import connect from 'connect'
77
import sirv from 'sirv'
8-
const { page, classList, text, nextFrame, timeout, isVisible, count, html } =
9-
setupPuppeteer()
8+
const {
9+
page,
10+
classList,
11+
text,
12+
nextFrame,
13+
timeout,
14+
isVisible,
15+
count,
16+
html,
17+
transitionStart,
18+
waitForElement,
19+
} = setupPuppeteer()
1020

1121
const duration = process.env.CI ? 200 : 50
1222
const buffer = process.env.CI ? 50 : 20
@@ -32,43 +42,6 @@ describe('vapor transition', () => {
3242
await page().waitForSelector('#app')
3343
})
3444

35-
const transitionStart = (btnSelector: string, containerSelector: string) =>
36-
page().evaluate(
37-
([btnSel, containerSel]) => {
38-
;(document.querySelector(btnSel) as HTMLElement)!.click()
39-
return Promise.resolve().then(() => {
40-
const container = document.querySelector(containerSel)!
41-
return {
42-
classNames: container.className.split(/\s+/g),
43-
innerHTML: container.innerHTML,
44-
}
45-
})
46-
},
47-
[btnSelector, containerSelector],
48-
)
49-
50-
const waitForElement = (
51-
selector: string,
52-
text: string,
53-
classNames: string[], // if empty, check for no classes
54-
timeout = 2000,
55-
) =>
56-
page().waitForFunction(
57-
(sel, expectedText, expectedClasses) => {
58-
const el = document.querySelector(sel)
59-
const hasClasses =
60-
expectedClasses.length === 0
61-
? el?.classList.length === 0
62-
: expectedClasses.every(c => el?.classList.contains(c))
63-
const hasText = el?.textContent?.includes(expectedText)
64-
return !!el && hasClasses && hasText
65-
},
66-
{ timeout },
67-
selector,
68-
text,
69-
classNames,
70-
)
71-
7245
test(
7346
'should work with v-show',
7447
async () => {

packages-private/vapor-e2e-test/__tests__/vdomInterop.spec.ts

+138-5
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,23 @@ import {
55
} from '../../../packages/vue/__tests__/e2e/e2eUtils'
66
import connect from 'connect'
77
import sirv from 'sirv'
8+
const {
9+
page,
10+
click,
11+
text,
12+
enterValue,
13+
html,
14+
transitionStart,
15+
waitForElement,
16+
nextFrame,
17+
timeout,
18+
} = setupPuppeteer()
19+
20+
const duration = process.env.CI ? 200 : 50
21+
const buffer = process.env.CI ? 50 : 20
22+
const transitionFinish = (time = duration) => timeout(time + buffer)
823

924
describe('vdom / vapor interop', () => {
10-
const { page, click, text, enterValue } = setupPuppeteer()
11-
1225
let server: any
1326
const port = '8193'
1427
beforeAll(() => {
@@ -22,12 +35,15 @@ describe('vdom / vapor interop', () => {
2235
server.close()
2336
})
2437

38+
beforeEach(async () => {
39+
const baseUrl = `http://localhost:${port}/interop/`
40+
await page().goto(baseUrl)
41+
await page().waitForSelector('#app')
42+
})
43+
2544
test(
2645
'should work',
2746
async () => {
28-
const baseUrl = `http://localhost:${port}/interop/`
29-
await page().goto(baseUrl)
30-
3147
expect(await text('.vapor > h2')).toContain('Vapor component in VDOM')
3248

3349
expect(await text('.vapor-prop')).toContain('hello')
@@ -81,4 +97,121 @@ describe('vdom / vapor interop', () => {
8197
},
8298
E2E_TIMEOUT,
8399
)
100+
101+
describe('vdom transition', () => {
102+
test(
103+
'render vapor component',
104+
async () => {
105+
const btnSelector = '.trans-vapor > button'
106+
const containerSelector = '.trans-vapor > div'
107+
108+
expect(await html(containerSelector)).toBe(
109+
`<div key="0">vapor compA</div>`,
110+
)
111+
112+
// comp leave
113+
expect(
114+
(await transitionStart(btnSelector, containerSelector)).innerHTML,
115+
).toBe(
116+
`<div key="0" class="v-leave-from v-leave-active">vapor compA</div><!---->`,
117+
)
118+
119+
await nextFrame()
120+
expect(await html(containerSelector)).toBe(
121+
`<div key="0" class="v-leave-active v-leave-to">vapor compA</div><!---->`,
122+
)
123+
124+
await transitionFinish()
125+
expect(await html(containerSelector)).toBe(`<!---->`)
126+
127+
// comp enter
128+
expect(
129+
(await transitionStart(btnSelector, containerSelector)).innerHTML,
130+
).toBe(
131+
`<div key="0" class="v-enter-from v-enter-active">vapor compA</div>`,
132+
)
133+
134+
await nextFrame()
135+
expect(await html(containerSelector)).toBe(
136+
`<div key="0" class="v-enter-active v-enter-to">vapor compA</div>`,
137+
)
138+
139+
await transitionFinish()
140+
expect(await html(containerSelector)).toBe(
141+
`<div key="0" class="">vapor compA</div>`,
142+
)
143+
},
144+
E2E_TIMEOUT,
145+
)
146+
147+
test(
148+
'switch between vdom/vapor component (out-in mode)',
149+
async () => {
150+
const btnSelector = '.trans-vdom-vapor-out-in > button'
151+
const containerSelector = '.trans-vdom-vapor-out-in > div'
152+
const childSelector = `${containerSelector} > div`
153+
154+
expect(await html(containerSelector)).toBe(`<div>vdom comp</div>`)
155+
156+
// switch to vapor comp
157+
// vdom comp leave
158+
expect(
159+
(await transitionStart(btnSelector, containerSelector)).innerHTML,
160+
).toBe(
161+
`<div class="fade-leave-from fade-leave-active">vdom comp</div><!---->`,
162+
)
163+
164+
await nextFrame()
165+
expect(await html(containerSelector)).toBe(
166+
`<div class="fade-leave-active fade-leave-to">vdom comp</div><!---->`,
167+
)
168+
169+
// vapor comp enter
170+
await waitForElement(childSelector, 'vapor compA', [
171+
'fade-enter-from',
172+
'fade-enter-active',
173+
])
174+
175+
await nextFrame()
176+
expect(await html(containerSelector)).toBe(
177+
`<div class="fade-enter-active fade-enter-to">vapor compA</div>`,
178+
)
179+
180+
await transitionFinish()
181+
expect(await html(containerSelector)).toBe(
182+
`<div class="">vapor compA</div>`,
183+
)
184+
185+
// switch to vdom comp
186+
// vapor comp leave
187+
expect(
188+
(await transitionStart(btnSelector, containerSelector)).innerHTML,
189+
).toBe(
190+
`<div class="fade-leave-from fade-leave-active">vapor compA</div><!---->`,
191+
)
192+
193+
await nextFrame()
194+
expect(await html(containerSelector)).toBe(
195+
`<div class="fade-leave-active fade-leave-to">vapor compA</div><!---->`,
196+
)
197+
198+
// vdom comp enter
199+
await waitForElement(childSelector, 'vdom comp', [
200+
'fade-enter-from',
201+
'fade-enter-active',
202+
])
203+
204+
await nextFrame()
205+
expect(await html(containerSelector)).toBe(
206+
`<div class="fade-enter-active fade-enter-to">vdom comp</div>`,
207+
)
208+
209+
await transitionFinish()
210+
expect(await html(containerSelector)).toBe(
211+
`<div class="">vdom comp</div>`,
212+
)
213+
},
214+
E2E_TIMEOUT,
215+
)
216+
})
84217
})

packages-private/vapor-e2e-test/interop/App.vue

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
<script setup lang="ts">
2-
import { ref } from 'vue'
2+
import { ref, shallowRef } from 'vue'
33
import VaporComp from './VaporComp.vue'
4+
import VaporCompA from '../transition/components/VaporCompA.vue'
5+
import VdomComp from '../transition/components/VdomComp.vue'
46
57
const msg = ref('hello')
68
const passSlot = ref(true)
9+
10+
const toggleVapor = ref(true)
11+
const interopComponent = shallowRef(VdomComp)
12+
function toggleInteropComponent() {
13+
interopComponent.value =
14+
interopComponent.value === VaporCompA ? VdomComp : VaporCompA
15+
}
716
</script>
817

918
<template>
@@ -19,4 +28,28 @@ const passSlot = ref(true)
1928

2029
<template #test v-if="passSlot">A test slot</template>
2130
</VaporComp>
31+
32+
<!-- transition interop -->
33+
<div>
34+
<div class="trans-vapor">
35+
<button @click="toggleVapor = !toggleVapor">
36+
toggle vapor component
37+
</button>
38+
<div>
39+
<Transition>
40+
<VaporCompA v-if="toggleVapor" />
41+
</Transition>
42+
</div>
43+
</div>
44+
<div class="trans-vdom-vapor-out-in">
45+
<button @click="toggleInteropComponent">
46+
switch between vdom/vapor component out-in mode
47+
</button>
48+
<div>
49+
<Transition name="fade" mode="out-in">
50+
<component :is="interopComponent"></component>
51+
</Transition>
52+
</div>
53+
</div>
54+
</div>
2255
</template>
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createApp, vaporInteropPlugin } from 'vue'
22
import App from './App.vue'
3+
import '../transition/style.css'
34

45
createApp(App).use(vaporInteropPlugin).mount('#app')

packages-private/vapor-e2e-test/transition/components/VaporCompA.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script vapor>
1+
<script setup vapor lang="ts">
22
const msg = 'vapor compA'
33
</script>
44
<template>

packages-private/vapor-e2e-test/transition/components/VaporCompB.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script vapor>
1+
<script setup vapor lang="ts">
22
const msg = 'vapor compB'
33
</script>
44
<template>

packages-private/vapor-e2e-test/transition/components/VdomComp.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script setup>
1+
<script setup lang="ts">
22
const msg = 'vdom comp'
33
</script>
44
<template>

packages/runtime-vapor/src/components/Transition.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
type VaporTransitionHooks,
2121
isFragment,
2222
} from '../block'
23-
import { isVaporComponent } from '../component'
23+
import { type VaporComponentInstance, isVaporComponent } from '../component'
2424

2525
const decorate = (t: typeof VaporTransition) => {
2626
t.displayName = 'VaporTransition'
@@ -244,3 +244,13 @@ export function findTransitionBlock(block: Block): TransitionBlock | undefined {
244244

245245
return child
246246
}
247+
248+
export function setTransitionToInstance(
249+
block: VaporComponentInstance,
250+
hooks: VaporTransitionHooks,
251+
): void {
252+
const child = findTransitionBlock(block.block)
253+
if (!child) return
254+
255+
setTransitionHooks(child, hooks)
256+
}

packages/runtime-vapor/src/vdomInterop.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
ensureRenderer,
1616
onScopeDispose,
1717
renderSlot,
18-
setTransitionHooks,
18+
setTransitionHooks as setVNodeTransitionHooks,
1919
shallowRef,
2020
simpleSetCurrentInstance,
2121
} from '@vue/runtime-dom'
@@ -28,13 +28,20 @@ import {
2828
mountComponent,
2929
unmountComponent,
3030
} from './component'
31-
import { type Block, VaporFragment, insert, remove } from './block'
31+
import {
32+
type Block,
33+
VaporFragment,
34+
type VaporTransitionHooks,
35+
insert,
36+
remove,
37+
} from './block'
3238
import { EMPTY_OBJ, extend, isFunction } from '@vue/shared'
3339
import { type RawProps, rawPropsProxyHandlers } from './componentProps'
3440
import type { RawSlots, VaporSlot } from './componentSlots'
3541
import { renderEffect } from './renderEffect'
3642
import { createTextNode } from './dom/node'
3743
import { optimizePropertyLookup } from './dom/prop'
44+
import { setTransitionToInstance } from './components/Transition'
3845

3946
// mounting vapor components and slots in vdom
4047
const vaporInteropImpl: Omit<
@@ -62,6 +69,12 @@ const vaporInteropImpl: Omit<
6269
))
6370
instance.rawPropsRef = propsRef
6471
instance.rawSlotsRef = slotsRef
72+
if (vnode.transition) {
73+
setTransitionToInstance(
74+
instance,
75+
vnode.transition as VaporTransitionHooks,
76+
)
77+
}
6578
mountComponent(instance, container, selfAnchor)
6679
simpleSetCurrentInstance(prev)
6780
return instance
@@ -174,15 +187,15 @@ function createVDOMComponent(
174187
let isMounted = false
175188
const parentInstance = currentInstance as VaporComponentInstance
176189
const unmount = (parentNode?: ParentNode, transition?: TransitionHooks) => {
177-
if (transition) setTransitionHooks(vnode, transition)
190+
if (transition) setVNodeTransitionHooks(vnode, transition)
178191
internals.umt(vnode.component!, null, !!parentNode)
179192
}
180193

181194
frag.insert = (parentNode, anchor, transition) => {
182195
const prev = currentInstance
183196
simpleSetCurrentInstance(parentInstance)
184197
if (!isMounted) {
185-
if (transition) setTransitionHooks(vnode, transition)
198+
if (transition) setVNodeTransitionHooks(vnode, transition)
186199
internals.mt(
187200
vnode,
188201
parentNode,

0 commit comments

Comments
 (0)