From 14a35b7b9848798ef16c20dd6fb3ffc5c588a9b9 Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Wed, 13 May 2020 22:44:54 +0800 Subject: [PATCH 1/6] test(Transition): more test transition --- .../__tests__/transition/Transition.spec.ts | 1331 ++++++++++++++++- .../{index.html => transition.html} | 15 +- 2 files changed, 1292 insertions(+), 54 deletions(-) rename packages/vue/examples/transition/{index.html => transition.html} (76%) diff --git a/packages/vue/examples/__tests__/transition/Transition.spec.ts b/packages/vue/examples/__tests__/transition/Transition.spec.ts index 650919d16d9..5ac85b3bcb9 100644 --- a/packages/vue/examples/__tests__/transition/Transition.spec.ts +++ b/packages/vue/examples/__tests__/transition/Transition.spec.ts @@ -1,17 +1,27 @@ import { E2E_TIMEOUT, setupPuppeteer } from '../e2eUtils' import path from 'path' +import { mockWarn } from '@vue/shared' +import { h, createApp, Transition } from 'vue' describe('e2e: Transition', () => { - const { page, html, classList } = setupPuppeteer() + mockWarn() + const { page, html, classList, isVisible } = setupPuppeteer() const baseUrl = `file://${path.resolve( __dirname, - '../../transition/index.html' + '../../transition/transition.html' )}` - const container = '#test' - const duration = 50 const buffer = 10 + + const classWhenTransitionStart = () => + page().evaluate(() => { + document.querySelector('button')!.click() + return Promise.resolve().then(() => { + return document.querySelector('#container div')!.className.split(/\s+/g) + }) + }) + const transitionFinish = () => new Promise(r => { setTimeout(r, duration + buffer) @@ -27,59 +37,1300 @@ describe('e2e: Transition', () => { }) } - test( - 'basic transition', - async () => { - await page().goto(baseUrl) - await page().waitFor('#app') - expect(await html(container)).toBe('
content
') + beforeEach(async () => { + await page().goto(baseUrl) + await page().waitFor('#app') + }) - const leaveStartClasses = await page().evaluate(() => { - document.querySelector('button')!.click() - return Promise.resolve().then(() => { - return document.querySelector('#test div')!.className.split(/\s+/g) + describe('transition with v-if', () => { + test( + 'basic transition', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
content
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') }) - }) + expect(await html('#container')).toBe('
content
') - expect(leaveStartClasses).toStrictEqual([ - 'test', - 'v-leave-active', - 'v-leave-from' - ]) + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'v-leave-active', + 'v-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'v-leave-active', + 'v-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') - await nextFrame() - expect(await classList('#test div')).toStrictEqual([ - 'test', - 'v-leave-active', - 'v-leave-to' - ]) + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'v-enter-active', + 'v-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'v-enter-active', + 'v-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) - await transitionFinish() - expect(await html('#test')).toBe('') + test( + 'named transition', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
content
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'custom transition classes', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+
content
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'bye-active', + 'bye-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'bye-active', + 'bye-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'hello-active', + 'hello-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'hello-active', + 'hello-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'transition with dynamic name', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
content
+ + + `, + setup: () => { + const name = ref('test') + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + const changeName = () => { + name.value = 'changed' + click() + } + return { toggle, click, name, changeName } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + const leaveClass = await page().evaluate(() => { + ;(document.querySelector('#toggleBtn') as any).click() + return Promise.resolve().then(() => { + return document.querySelector('.test')!.className.split(/\s+/g) + }) + }) + expect(leaveClass).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + const enterClass = await page().evaluate(() => { + ;(document.querySelector('#changeNameBtn') as any).click() + return Promise.resolve().then(() => { + return document.querySelector('.test')!.className.split(/\s+/g) + }) + }) + expect(enterClass).toStrictEqual([ + 'test', + 'changed-enter-active', + 'changed-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'changed-enter-active', + 'changed-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'transition events without appear', + async () => { + const beforeLeaveSpy = jest.fn() + const onLeaveSpy = jest.fn() + const afterLeaveSpy = jest.fn() + const beforeEnterSpy = jest.fn() + const onEnterSpy = jest.fn() + const afterEnterSpy = jest.fn() - const enterStartClasses = await page().evaluate(() => { - document.querySelector('button')!.click() - return Promise.resolve().then(() => { - return document.querySelector('#test div')!.className.split(/\s+/g) + await page().exposeFunction('onLeaveSpy', onLeaveSpy) + await page().exposeFunction('onEnterSpy', onEnterSpy) + await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy) + await page().exposeFunction('beforeEnterSpy', beforeEnterSpy) + await page().exposeFunction('afterLeaveSpy', afterLeaveSpy) + await page().exposeFunction('afterEnterSpy', afterEnterSpy) + + await page().evaluate(() => { + const { + beforeEnterSpy, + onEnterSpy, + afterEnterSpy, + beforeLeaveSpy, + onLeaveSpy, + afterLeaveSpy + } = window as any + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { + toggle, + click, + beforeEnterSpy, + onEnterSpy, + afterEnterSpy, + beforeLeaveSpy, + onLeaveSpy, + afterLeaveSpy + } + } + }).mount('#app') }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + // todo test event with arguments. Note: not get dom, get object. '{}' + expect(beforeLeaveSpy).toBeCalled() + expect(onLeaveSpy).not.toBeCalled() + expect(afterLeaveSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + expect(beforeLeaveSpy).toBeCalled() + expect(afterLeaveSpy).not.toBeCalled() + await transitionFinish() + expect(await html('#container')).toBe('') + expect(afterLeaveSpy).toBeCalled() + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + expect(beforeEnterSpy).toBeCalled() + expect(onEnterSpy).not.toBeCalled() + expect(afterEnterSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + expect(onEnterSpy).toBeCalled() + expect(afterEnterSpy).not.toBeCalled() + await transitionFinish() + expect(await html('#container')).toBe('
content
') + expect(afterEnterSpy).toBeCalled() + }, + E2E_TIMEOUT + ) + + test('onEnterCancelled', async () => { + const enterCancelledSpy = jest.fn() + + await page().exposeFunction('enterCancelledSpy', enterCancelledSpy) + + await page().evaluate(() => { + const { enterCancelledSpy } = window as any + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(false) + const click = () => (toggle.value = !toggle.value) + return { + toggle, + click, + enterCancelledSpy + } + } + }).mount('#app') }) + expect(await html('#container')).toBe('') - expect(enterStartClasses).toStrictEqual([ + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ 'test', - 'v-enter-active', - 'v-enter-from' + 'test-enter-active', + 'test-enter-from' ]) - await nextFrame() - expect(await classList('#test div')).toStrictEqual([ + expect(await classList('.test')).toStrictEqual([ 'test', - 'v-enter-active', - 'v-enter-to' + 'test-enter-active', + 'test-enter-to' ]) + // cancel (leave) + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + // fixme + expect(enterCancelledSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) await transitionFinish() - expect(await html('#test')).toBe('
content
') + expect(await html('#container')).toBe('') + }) + + test( + 'transition on appear', + async () => { + await page().evaluate(async () => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + // appear + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'transition events with appear', + async () => { + const onLeaveSpy = jest.fn() + const onEnterSpy = jest.fn() + const onAppearSpy = jest.fn() + const beforeLeaveSpy = jest.fn() + const beforeEnterSpy = jest.fn() + const beforeAppearSpy = jest.fn() + const afterLeaveSpy = jest.fn() + const afterEnterSpy = jest.fn() + const afterAppearSpy = jest.fn() + + await page().exposeFunction('onLeaveSpy', onLeaveSpy) + await page().exposeFunction('onEnterSpy', onEnterSpy) + await page().exposeFunction('onAppearSpy', onAppearSpy) + await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy) + await page().exposeFunction('beforeEnterSpy', beforeEnterSpy) + await page().exposeFunction('beforeAppearSpy', beforeAppearSpy) + await page().exposeFunction('afterLeaveSpy', afterLeaveSpy) + await page().exposeFunction('afterEnterSpy', afterEnterSpy) + await page().exposeFunction('afterAppearSpy', afterAppearSpy) + + await page().evaluate(async () => { + const { + beforeAppearSpy, + onAppearSpy, + afterAppearSpy, + beforeEnterSpy, + onEnterSpy, + afterEnterSpy, + beforeLeaveSpy, + onLeaveSpy, + afterLeaveSpy + } = window as any + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { + toggle, + click, + beforeAppearSpy, + onAppearSpy, + afterAppearSpy, + beforeEnterSpy, + onEnterSpy, + afterEnterSpy, + beforeLeaveSpy, + onLeaveSpy, + afterLeaveSpy + } + } + }).mount('#app') + }) + // appear fixme spy called + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-from' + ]) + expect(beforeAppearSpy).not.toBeCalled() + expect(onAppearSpy).not.toBeCalled() + expect(afterAppearSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-to' + ]) + expect(onAppearSpy).not.toBeCalled() + expect(afterAppearSpy).not.toBeCalled() + await transitionFinish() + expect(await html('#container')).toBe('
content
') + expect(afterAppearSpy).not.toBeCalled() + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + expect(beforeLeaveSpy).toBeCalled() + expect(onLeaveSpy).not.toBeCalled() + expect(afterLeaveSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + expect(onLeaveSpy).toBeCalled() + expect(afterLeaveSpy).not.toBeCalled() + await transitionFinish() + expect(await html('#container')).toBe('') + expect(afterLeaveSpy).toBeCalled() + + // enter fixme spy called + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + expect(beforeEnterSpy).toBeCalled() + expect(onEnterSpy).toBeCalled() + expect(afterEnterSpy).toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + expect(onEnterSpy).toBeCalled() + expect(afterEnterSpy).toBeCalled() + await transitionFinish() + expect(await html('#container')).toBe('
content
') + expect(afterEnterSpy).toBeCalled() + }, + E2E_TIMEOUT + ) + + // fixme + test( + 'css: false', + async () => { + const onLeaveSpy = jest.fn() + const onEnterSpy = jest.fn() + + await page().exposeFunction('onLeaveSpy', onLeaveSpy) + await page().exposeFunction('onEnterSpy', onEnterSpy) + + await page().evaluate(() => { + const { onLeaveSpy, onEnterSpy } = window as any + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click, onLeaveSpy, onEnterSpy } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + await classWhenTransitionStart() + expect(onLeaveSpy).toBeCalled() + expect(await html('#container')).toBe( + '
content
' + ) + // enter + await classWhenTransitionStart() + expect(onEnterSpy).toBeCalled() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'no transition detected', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'noop-leave-active', + 'noop-leave-from' + ]) + await nextFrame() + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'noop-enter-active', + 'noop-enter-from' + ]) + await nextFrame() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'animations', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
content
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-anim-leave-active', + 'test-anim-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-anim-leave-active', + 'test-anim-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-anim-enter-active', + 'test-anim-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-anim-enter-active', + 'test-anim-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'explicit transition type', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
content
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-anim-long-leave-active', + 'test-anim-long-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-anim-long-leave-active', + 'test-anim-long-leave-to' + ]) + await new Promise(r => { + setTimeout(r, duration + 5) + }) + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-anim-long-leave-active', + 'test-anim-long-leave-to' + ]) + await new Promise(r => { + setTimeout(r, duration + 5) + }) + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-anim-long-enter-active', + 'test-anim-long-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-anim-long-enter-active', + 'test-anim-long-enter-to' + ]) + await new Promise(r => { + setTimeout(r, duration + 5) + }) + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-anim-long-enter-active', + 'test-anim-long-enter-to' + ]) + await new Promise(r => { + setTimeout(r, duration + 5) + }) + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + + test( + 'transition on SVG elements', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` + + + + + + + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe( + '' + ) + + const svgTransitionStart = () => + page().evaluate(() => { + document.querySelector('button')!.click() + return Promise.resolve().then(() => { + return document + .querySelector('.test')! + .getAttribute('class')! + .split(/\s+/g) + }) + }) + + // leave + expect(await svgTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + expect(await svgTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe( + '' + ) + }, + E2E_TIMEOUT + ) + + test( + 'custom transition higher-order component', + async () => { + await page().evaluate(() => { + const { createApp, ref, h, Transition } = (window as any).Vue + createApp({ + template: ` +
content
+ + `, + components: { + 'my-transition': (props: any, { slots }: any) => { + return h(Transition, { name: 'test' }, slots) + } + }, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('') + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + }, + E2E_TIMEOUT + ) + }) + + describe('transition with v-show', () => { + test( + 'named transition with v-show', + async () => { + await page().evaluate(() => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + expect(await isVisible('.test')).toBe(true) + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + await transitionFinish() + expect(await isVisible('.test')).toBe(false) + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe( + '
content
' + ) + }, + E2E_TIMEOUT + ) + + test( + 'transition events with v-show', + async () => { + const beforeLeaveSpy = jest.fn() + const onLeaveSpy = jest.fn() + const afterLeaveSpy = jest.fn() + const beforeEnterSpy = jest.fn() + const onEnterSpy = jest.fn() + const afterEnterSpy = jest.fn() + + await page().exposeFunction('onLeaveSpy', onLeaveSpy) + await page().exposeFunction('onEnterSpy', onEnterSpy) + await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy) + await page().exposeFunction('beforeEnterSpy', beforeEnterSpy) + await page().exposeFunction('afterLeaveSpy', afterLeaveSpy) + await page().exposeFunction('afterEnterSpy', afterEnterSpy) + + await page().evaluate(() => { + const { + beforeEnterSpy, + onEnterSpy, + afterEnterSpy, + beforeLeaveSpy, + onLeaveSpy, + afterLeaveSpy + } = window as any + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { + toggle, + click, + beforeEnterSpy, + onEnterSpy, + afterEnterSpy, + beforeLeaveSpy, + onLeaveSpy, + afterLeaveSpy + } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + expect(beforeLeaveSpy).toBeCalled() + expect(onLeaveSpy).not.toBeCalled() + expect(afterLeaveSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + expect(beforeLeaveSpy).toBeCalled() + expect(afterLeaveSpy).not.toBeCalled() + await transitionFinish() + expect(await isVisible('.test')).toBe(false) + expect(afterLeaveSpy).toBeCalled() + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + expect(beforeEnterSpy).toBeCalled() + expect(onEnterSpy).not.toBeCalled() + expect(afterEnterSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + expect(onEnterSpy).toBeCalled() + expect(afterEnterSpy).not.toBeCalled() + await transitionFinish() + expect(await html('#container')).toBe( + '
content
' + ) + expect(afterEnterSpy).toBeCalled() + }, + E2E_TIMEOUT + ) + + test( + 'onLeaveCancelled (v-show only)', + async () => { + const onLeaveCancelledSpy = jest.fn() + + await page().exposeFunction('onLeaveCancelledSpy', onLeaveCancelledSpy) + await page().evaluate(() => { + const { onLeaveCancelledSpy } = window as any + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click, onLeaveCancelledSpy } + } + }).mount('#app') + }) + expect(await html('#container')).toBe('
content
') + expect(await isVisible('.test')).toBe(true) + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + + // cancel (enter) + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + // fixme + expect(onLeaveCancelledSpy).not.toBeCalled() + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe( + '
content
' + ) + }, + E2E_TIMEOUT + ) + + test( + 'transition on appear with v-show', + async () => { + await page().evaluate(async () => { + const { createApp, ref } = (window as any).Vue + createApp({ + template: ` +
+ +
content
+
+
+ + `, + setup: () => { + const toggle = ref(true) + const click = () => (toggle.value = !toggle.value) + return { toggle, click } + } + }).mount('#app') + }) + // appear + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-appear-active', + 'test-appear-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe('
content
') + + // leave + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-leave-active', + 'test-leave-to' + ]) + await transitionFinish() + expect(await isVisible('.test')).toBe(false) + + // enter + expect(await classWhenTransitionStart()).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-from' + ]) + await nextFrame() + expect(await classList('.test')).toStrictEqual([ + 'test', + 'test-enter-active', + 'test-enter-to' + ]) + await transitionFinish() + expect(await html('#container')).toBe( + '
content
' + ) + }, + E2E_TIMEOUT + ) + }) + + test( + 'warn when used on multiple elements', + async () => { + createApp({ + render() { + return h(Transition, null, { + default: () => [h('div'), h('div')] + }) + } + }).mount(document.createElement('div')) + expect( + ' can only be used on a single element or component' + ).toHaveBeenWarned() }, E2E_TIMEOUT ) + + test.todo('explicit durations -') + test.todo('transition on child components with empty root node') }) diff --git a/packages/vue/examples/transition/index.html b/packages/vue/examples/transition/transition.html similarity index 76% rename from packages/vue/examples/transition/index.html rename to packages/vue/examples/transition/transition.html index af66e19df85..2a794234103 100644 --- a/packages/vue/examples/transition/index.html +++ b/packages/vue/examples/transition/transition.html @@ -1,19 +1,6 @@ -
- +