wip: port tests and fix bugs

This commit is contained in:
daiwei 2025-03-12 22:36:38 +08:00
parent e7300a0bbb
commit af2eb2dbf5
4 changed files with 294 additions and 6 deletions

View File

@ -16,6 +16,7 @@ const {
html, html,
transitionStart, transitionStart,
waitForElement, waitForElement,
click,
} = setupPuppeteer() } = setupPuppeteer()
const duration = process.env.CI ? 200 : 50 const duration = process.env.CI ? 200 : 50
@ -42,6 +43,234 @@ describe('vapor transition', () => {
await page().waitForSelector('#app') await page().waitForSelector('#app')
}) })
describe('transition with v-if', () => {
test(
'basic transition',
async () => {
const btnSelector = '.if-basic > button'
const containerSelector = '.if-basic > div'
const childSelector = `${containerSelector} > div`
expect(await html(containerSelector)).toBe(
`<div class="test">content</div>`,
)
// leave
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'v-leave-from', 'v-leave-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'v-leave-active',
'v-leave-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe('')
// enter
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'v-enter-from', 'v-enter-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'v-enter-active',
'v-enter-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe(
'<div class="test">content</div>',
)
},
E2E_TIMEOUT,
)
test(
'named transition',
async () => {
const btnSelector = '.if-named > button'
const containerSelector = '.if-named > div'
const childSelector = `${containerSelector} > div`
expect(await html(containerSelector)).toBe(
'<div class="test">content</div>',
)
// leave
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'test-leave-from', 'test-leave-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'test-leave-active',
'test-leave-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe('')
// enter
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'test-enter-from', 'test-enter-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'test-enter-active',
'test-enter-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe(
'<div class="test">content</div>',
)
},
E2E_TIMEOUT,
)
test(
'custom transition classes',
async () => {
const btnSelector = '.if-custom-classes > button'
const containerSelector = '.if-custom-classes > div'
const childSelector = `${containerSelector} > div`
expect(await html(containerSelector)).toBe(
'<div class="test">content</div>',
)
// leave
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'bye-from', 'bye-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'bye-active',
'bye-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe('')
// enter
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'hello-from', 'hello-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'hello-active',
'hello-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe(
'<div class="test">content</div>',
)
},
E2E_TIMEOUT,
)
test(
'transition with dynamic name',
async () => {
const btnSelector = '.if-dynamic-name > button.toggle'
const btnChangeNameSelector = '.if-dynamic-name > button.change'
const containerSelector = '.if-dynamic-name > div'
const childSelector = `${containerSelector} > div`
expect(await html(containerSelector)).toBe(
'<div class="test">content</div>',
)
// leave
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'test-leave-from', 'test-leave-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'test-leave-active',
'test-leave-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe('')
// enter
await click(btnChangeNameSelector)
expect(
(await transitionStart(btnSelector, childSelector)).classNames,
).toStrictEqual(['test', 'changed-enter-from', 'changed-enter-active'])
await nextFrame()
expect(await classList(childSelector)).toStrictEqual([
'test',
'changed-enter-active',
'changed-enter-to',
])
await transitionFinish()
expect(await html(containerSelector)).toBe(
'<div class="test">content</div>',
)
},
E2E_TIMEOUT,
)
test.todo('transition events without appear', async () => {}, E2E_TIMEOUT)
test.todo('events with arguments', async () => {}, E2E_TIMEOUT)
test.todo('onEnterCancelled', async () => {}, E2E_TIMEOUT)
test.todo('transition on appear', async () => {}, E2E_TIMEOUT)
test.todo('transition events with appear', async () => {}, E2E_TIMEOUT)
test.todo('no transition detected', async () => {}, E2E_TIMEOUT)
test.todo('animations', async () => {}, E2E_TIMEOUT)
test.todo('explicit transition type', async () => {}, E2E_TIMEOUT)
test.todo('transition on SVG elements', async () => {}, E2E_TIMEOUT)
test.todo(
'custom transition higher-order component',
async () => {},
E2E_TIMEOUT,
)
test.todo(
'transition on child components with empty root node',
async () => {},
E2E_TIMEOUT,
)
test.todo(
'transition with v-if at component root-level',
async () => {},
E2E_TIMEOUT,
)
test.todo(
'wrapping transition + fallthrough attrs',
async () => {},
E2E_TIMEOUT,
)
test.todo(
'transition + fallthrough attrs (in-out mode)',
async () => {},
E2E_TIMEOUT,
)
})
describe('transition with v-show', () => {
test.todo('named transition with v-show', async () => {}, E2E_TIMEOUT)
test.todo('transition events with v-show', async () => {}, E2E_TIMEOUT)
test.todo('onLeaveCancelled (v-show only)', async () => {}, E2E_TIMEOUT)
test.todo('transition on appear with v-show', async () => {}, E2E_TIMEOUT)
test.todo(
'transition events should not call onEnter with v-show false',
async () => {},
E2E_TIMEOUT,
)
test.todo('transition on appear with v-show', async () => {}, E2E_TIMEOUT)
})
describe('explicit durations', () => {
test.todo('single value', async () => {}, E2E_TIMEOUT)
test.todo('enter with explicit durations', async () => {}, E2E_TIMEOUT)
test.todo('leave with explicit durations', async () => {}, E2E_TIMEOUT)
test.todo('separate enter and leave', async () => {}, E2E_TIMEOUT)
test.todo('warn invalid durations', async () => {}, E2E_TIMEOUT)
})
test( test(
'should work with v-show', 'should work with v-show',
async () => { async () => {

View File

@ -23,10 +23,53 @@ function toggleInteropComponent() {
interopComponent.value = interopComponent.value =
interopComponent.value === VaporCompA ? VDomComp : VaporCompA interopComponent.value === VaporCompA ? VDomComp : VaporCompA
} }
const name = ref('test')
</script> </script>
<template> <template>
<div class="transition-container"> <div class="transition-container">
<div class="if-basic">
<div>
<transition>
<div v-if="toggle" class="test">content</div>
</transition>
</div>
<button @click="toggle = !toggle">basic toggle</button>
</div>
<div class="if-named">
<div>
<transition name="test">
<div v-if="toggle" class="test">content</div>
</transition>
</div>
<button @click="toggle = !toggle">button</button>
</div>
<div class="if-custom-classes">
<div>
<transition
enter-from-class="hello-from"
enter-active-class="hello-active"
enter-to-class="hello-to"
leave-from-class="bye-from"
leave-active-class="bye-active"
leave-to-class="bye-to"
>
<div v-if="toggle" class="test">content</div>
</transition>
</div>
<button @click="toggle = !toggle">button</button>
</div>
<div class="if-dynamic-name">
<div>
<transition :name="name">
<div v-if="toggle" class="test">content</div>
</transition>
</div>
<button class="toggle" @click="toggle = !toggle">button</button>
<button class="change" @click="name = 'changed'">{{ name }}</button>
</div>
<div class="vshow"> <div class="vshow">
<button @click="show = !show">Show</button> <button @click="show = !show">Show</button>
<Transition> <Transition>

View File

@ -168,7 +168,7 @@ const BaseTransitionImpl: ComponentOptions = {
const rawProps = toRaw(props) const rawProps = toRaw(props)
const { mode } = rawProps const { mode } = rawProps
// check mode // check mode
__DEV__ && checkTransitionMode(mode) checkTransitionMode(mode)
if (state.isLeaving) { if (state.isLeaving) {
return emptyPlaceholder(child) return emptyPlaceholder(child)
@ -619,7 +619,13 @@ export function getTransitionRawChildren(
* dev-only * dev-only
*/ */
export function checkTransitionMode(mode: string | undefined): void { export function checkTransitionMode(mode: string | undefined): void {
if (mode && mode !== 'in-out' && mode !== 'out-in' && mode !== 'default') { if (
__DEV__ &&
mode &&
mode !== 'in-out' &&
mode !== 'out-in' &&
mode !== 'default'
) {
warn(`invalid <transition> mode: ${mode}`) warn(`invalid <transition> mode: ${mode}`)
} }
} }

View File

@ -23,6 +23,7 @@ import {
} from '../block' } from '../block'
import { type VaporComponentInstance, isVaporComponent } from '../component' import { type VaporComponentInstance, isVaporComponent } from '../component'
import { isArray } from '@vue/shared' import { isArray } from '@vue/shared'
import { renderEffect } from '../renderEffect'
const decorate = (t: typeof VaporTransition) => { const decorate = (t: typeof VaporTransition) => {
t.displayName = 'VaporTransition' t.displayName = 'VaporTransition'
@ -37,12 +38,21 @@ export const VaporTransition: FunctionalComponent<TransitionProps> =
if (!children) return if (!children) return
const { mode } = props const { mode } = props
__DEV__ && checkTransitionMode(mode) checkTransitionMode(mode)
applyTransitionEnterHooks(children, { let resolvedProps
renderEffect(() => {
resolvedProps = resolveTransitionProps(props)
if (isFragment(children) && children.$transition) {
children.$transition.props = resolvedProps
}
})
const hooks = {
state: useTransitionState(), state: useTransitionState(),
props: resolveTransitionProps(props), props: resolvedProps!,
} as VaporTransitionHooks) } as VaporTransitionHooks
applyTransitionEnterHooks(children, hooks)
return children return children
}) })