--- /dev/null
+import { E2E_TIMEOUT, setupPuppeteer } from '../e2eUtils'
+import path from 'path'
+
+function nextFrame(cb: () => void) {
+ requestAnimationFrame(() => {
+ requestAnimationFrame(cb)
+ })
+}
+
+describe('e2e: Transition', () => {
+ const { page, html, click, classList } = setupPuppeteer()
+ const baseUrl = `file://${path.resolve(
+ __dirname,
+ '../../transition/index.html'
+ )}`
+ const duration = 50,
+ buffer = 10
+ const container = '#test'
+
+ test(
+ 'basic transition',
+ async () => {
+ await page().goto(baseUrl)
+ await page().waitFor('#app')
+ expect(await html(container)).toBe('<div class="test"></div>')
+
+ await click('button')
+ expect(await classList('#test div')).toStrictEqual([
+ 'test',
+ 'v-leave-active',
+ 'v-leave-from'
+ ])
+ await new Promise((resolve, reject) => {
+ nextFrame(async () => {
+ expect(await classList('#test div')).toStrictEqual([
+ 'test',
+ 'v-leave-active',
+ 'v-leave-to'
+ ])
+ setTimeout(async () => {
+ expect(await html('#test')).toBe('<!--v-if-->')
+ resolve()
+ }, duration + buffer)
+ })
+ })
+
+ await click('button')
+ expect(await classList('#test div')).toStrictEqual([
+ 'test',
+ 'v-enter-active',
+ 'v-enter-from'
+ ])
+ await new Promise((resolve, reject) => {
+ nextFrame(async () => {
+ expect(await classList('#test div')).toStrictEqual([
+ 'test',
+ 'v-enter-active',
+ 'v-enter-to'
+ ])
+ setTimeout(async () => {
+ expect(await html('#test')).toBe('<div class="test"></div>')
+ resolve()
+ }, duration + buffer)
+ })
+ })
+ },
+ E2E_TIMEOUT
+ )
+})
--- /dev/null
+<script src="../../dist/vue.global.js"></script>
+<div id="app"></div>
+<script>
+ Vue.createApp({
+ template: `
+ <div id="test"><transition><div v-if="toggle" class="test"></div></transition></div>
+ <button @click="click"></button>
+ `,
+ setup:() => {
+ const toggle = Vue.ref(true)
+ const click = () => toggle.value = !toggle.value
+ return { toggle, click }
+ }
+ }).mount('#app')
+</script>
+
+<style>
+ .test {
+ -webkit-transition: opacity 50ms ease;
+ transition: opacity 50ms ease;
+ }
+ .group-move {
+ -webkit-transition: -webkit-transform 50ms ease;
+ transition: transform 50ms ease;
+ }
+ .v-appear, .v-enter, .v-leave-active,
+ .test-appear, .test-enter, .test-leave-active,
+ .hello, .bye.active,
+ .changed-enter {
+ opacity: 0;
+ }
+ .test-anim-enter-active {
+ animation: test-enter 50ms;
+ -webkit-animation: test-enter 50ms;
+ }
+ .test-anim-leave-active {
+ animation: test-leave 50ms;
+ -webkit-animation: test-leave 50ms;
+ }
+ .test-anim-long-enter-active {
+ animation: test-enter 100ms;
+ -webkit-animation: test-enter 100ms;
+ }
+ .test-anim-long-leave-active {
+ animation: test-leave 100ms;
+ -webkit-animation: test-leave 100ms;
+ }
+ @keyframes test-enter {
+ from { opacity: 0 }
+ to { opacity: 1 }
+ }
+ @-webkit-keyframes test-enter {
+ from { opacity: 0 }
+ to { opacity: 1 }
+ }
+ @keyframes test-leave {
+ from { opacity: 1 }
+ to { opacity: 0 }
+ }
+ @-webkit-keyframes test-leave {
+ from { opacity: 1 }
+ to { opacity: 0 }
+ }
+</style>