From b65db59169fbe5efe559f168640d4bf2ffafbdaf Mon Sep 17 00:00:00 2001 From: daiwei Date: Thu, 6 Mar 2025 17:40:52 +0800 Subject: [PATCH] wip: add vapor transition e2e tests --- .../__tests__/transition.spec.ts | 238 ++++++++++++++++++ packages-private/vapor-e2e-test/index.html | 1 + .../vapor-e2e-test/transition/App.vue | 47 ++++ .../transition/components/VaporCompA.vue | 6 + .../transition/components/VaporCompB.vue | 6 + .../vapor-e2e-test/transition/index.html | 2 + .../vapor-e2e-test/transition/main.ts | 5 + .../vapor-e2e-test/transition/style.css | 19 ++ .../vapor-e2e-test/vite.config.ts | 1 + 9 files changed, 325 insertions(+) create mode 100644 packages-private/vapor-e2e-test/__tests__/transition.spec.ts create mode 100644 packages-private/vapor-e2e-test/transition/App.vue create mode 100644 packages-private/vapor-e2e-test/transition/components/VaporCompA.vue create mode 100644 packages-private/vapor-e2e-test/transition/components/VaporCompB.vue create mode 100644 packages-private/vapor-e2e-test/transition/index.html create mode 100644 packages-private/vapor-e2e-test/transition/main.ts create mode 100644 packages-private/vapor-e2e-test/transition/style.css diff --git a/packages-private/vapor-e2e-test/__tests__/transition.spec.ts b/packages-private/vapor-e2e-test/__tests__/transition.spec.ts new file mode 100644 index 000000000..922ff0d0e --- /dev/null +++ b/packages-private/vapor-e2e-test/__tests__/transition.spec.ts @@ -0,0 +1,238 @@ +import path from 'node:path' +import { + E2E_TIMEOUT, + setupPuppeteer, +} from '../../../packages/vue/__tests__/e2e/e2eUtils' +import connect from 'connect' +import sirv from 'sirv' +const { + page, + click, + classList, + text, + nextFrame, + timeout, + isVisible, + count, + html, +} = setupPuppeteer() + +const duration = process.env.CI ? 200 : 50 +const buffer = process.env.CI ? 50 : 20 +const transitionFinish = (time = duration) => timeout(time + buffer) + +describe('vapor transition', () => { + let server: any + const port = '8195' + beforeAll(() => { + server = connect() + .use(sirv(path.resolve(import.meta.dirname, '../dist'))) + .listen(port) + process.on('SIGTERM', () => server && server.close()) + }) + + afterAll(() => { + server.close() + }) + + beforeEach(async () => { + const baseUrl = `http://localhost:${port}/transition/` + await page().goto(baseUrl) + await page().waitForSelector('#app') + }) + + const classWhenTransitionStart = async ( + btnSelector: string, + containerSelector: string, + ) => { + return page().evaluate( + ([btnSel, containerSel]) => { + ;(document.querySelector(btnSel) as HTMLElement)!.click() + return Promise.resolve().then(() => { + return document.querySelector(containerSel)!.className.split(/\s+/g) + }) + }, + [btnSelector, containerSelector], + ) + } + + test( + 'should work with v-show', + async () => { + const btnSelector = '.vshow > button' + const containerSelector = '.vshow > h1' + + expect(await text(containerSelector)).toContain('vShow') + + // leave + expect( + await classWhenTransitionStart(btnSelector, containerSelector), + ).toStrictEqual(['v-leave-from', 'v-leave-active']) + + await nextFrame() + expect(await classList(containerSelector)).toStrictEqual([ + 'v-leave-active', + 'v-leave-to', + ]) + + await transitionFinish() + expect(await isVisible(containerSelector)).toBe(false) + + // enter + expect( + await classWhenTransitionStart(btnSelector, containerSelector), + ).toStrictEqual(['v-enter-from', 'v-enter-active']) + + await nextFrame() + expect(await classList(containerSelector)).toStrictEqual([ + 'v-enter-active', + 'v-enter-to', + ]) + + await transitionFinish() + expect(await isVisible(containerSelector)).toBe(true) + }, + E2E_TIMEOUT, + ) + + test( + 'should work with v-if + appear', + async () => { + const btnSelector = '.vif > button' + const containerSelector = '.vif > h1' + + // appear + expect(await classList(containerSelector)).toStrictEqual([ + 'v-enter-from', + 'v-enter-active', + ]) + expect(await text(containerSelector)).toContain('vIf') + await transitionFinish() + + // leave + expect( + await classWhenTransitionStart(btnSelector, containerSelector), + ).toStrictEqual(['v-leave-from', 'v-leave-active']) + + await nextFrame() + expect(await classList(containerSelector)).toStrictEqual([ + 'v-leave-active', + 'v-leave-to', + ]) + + await transitionFinish() + expect(await count(containerSelector)).toBe(0) + + // enter + expect( + await classWhenTransitionStart(btnSelector, containerSelector), + ).toStrictEqual(['v-enter-from', 'v-enter-active']) + + await nextFrame() + expect(await classList(containerSelector)).toStrictEqual([ + 'v-enter-active', + 'v-enter-to', + ]) + + await transitionFinish() + expect(await isVisible(containerSelector)).toBe(true) + }, + E2E_TIMEOUT, + ) + + test( + 'should work with keyed element', + async () => { + const btnSelector = '.keyed > button' + const containerSelector = '.keyed > h1' + + expect(await text(containerSelector)).toContain('0') + + // change key + expect( + await classWhenTransitionStart(btnSelector, containerSelector), + ).toStrictEqual(['v-leave-from', 'v-leave-active']) + + await nextFrame() + expect(await classList(containerSelector)).toStrictEqual([ + 'v-leave-active', + 'v-leave-to', + ]) + + await transitionFinish() + expect(await text(containerSelector)).toContain('1') + + // change key again + expect( + await classWhenTransitionStart(btnSelector, containerSelector), + ).toStrictEqual(['v-leave-from', 'v-leave-active']) + + await nextFrame() + expect(await classList(containerSelector)).toStrictEqual([ + 'v-leave-active', + 'v-leave-to', + ]) + + await transitionFinish() + expect(await text(containerSelector)).toContain('2') + }, + E2E_TIMEOUT, + ) + + test( + 'should work with out-in mode', + async () => { + const btnSelector = '.out-in > button' + const containerSelector = '.out-in > div' + + expect(await html(containerSelector)).toBe(`
vapor compB
`) + + // compB -> compA + await click(btnSelector) + expect(await html(containerSelector)).toBe( + `
vapor compB
`, + ) + + await nextFrame() + expect(await html(containerSelector)).toBe( + `
vapor compB
`, + ) + + await transitionFinish() + await nextFrame() + expect(await html(containerSelector)).toBe( + `
vapor compA
`, + ) + + await transitionFinish() + expect(await html(containerSelector)).toBe( + `
vapor compA
`, + ) + + // compA -> compB + await click(btnSelector) + expect(await html(containerSelector)).toBe( + `
vapor compA
`, + ) + + await nextFrame() + expect(await html(containerSelector)).toBe( + `
vapor compA
`, + ) + + await transitionFinish() + await nextFrame() + expect(await html(containerSelector)).toBe( + `
vapor compB
`, + ) + + await transitionFinish() + expect(await html(containerSelector)).toBe( + `
vapor compB
`, + ) + }, + E2E_TIMEOUT, + ) + + test.todo('should work with in-out mode', async () => {}, E2E_TIMEOUT) +}) diff --git a/packages-private/vapor-e2e-test/index.html b/packages-private/vapor-e2e-test/index.html index 7dc205e5a..160e2125d 100644 --- a/packages-private/vapor-e2e-test/index.html +++ b/packages-private/vapor-e2e-test/index.html @@ -1,2 +1,3 @@ VDOM / Vapor interop Vapor TodoMVC +Vapor Transition diff --git a/packages-private/vapor-e2e-test/transition/App.vue b/packages-private/vapor-e2e-test/transition/App.vue new file mode 100644 index 000000000..6d2ebd050 --- /dev/null +++ b/packages-private/vapor-e2e-test/transition/App.vue @@ -0,0 +1,47 @@ + + + + \ No newline at end of file diff --git a/packages-private/vapor-e2e-test/transition/components/VaporCompA.vue b/packages-private/vapor-e2e-test/transition/components/VaporCompA.vue new file mode 100644 index 000000000..24c98ecb6 --- /dev/null +++ b/packages-private/vapor-e2e-test/transition/components/VaporCompA.vue @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/packages-private/vapor-e2e-test/transition/components/VaporCompB.vue b/packages-private/vapor-e2e-test/transition/components/VaporCompB.vue new file mode 100644 index 000000000..8064165f3 --- /dev/null +++ b/packages-private/vapor-e2e-test/transition/components/VaporCompB.vue @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/packages-private/vapor-e2e-test/transition/index.html b/packages-private/vapor-e2e-test/transition/index.html new file mode 100644 index 000000000..79052a023 --- /dev/null +++ b/packages-private/vapor-e2e-test/transition/index.html @@ -0,0 +1,2 @@ + +
diff --git a/packages-private/vapor-e2e-test/transition/main.ts b/packages-private/vapor-e2e-test/transition/main.ts new file mode 100644 index 000000000..d02bb9790 --- /dev/null +++ b/packages-private/vapor-e2e-test/transition/main.ts @@ -0,0 +1,5 @@ +import { createVaporApp } from 'vue' +import App from './App.vue' +import './style.css' + +createVaporApp(App).mount('#app') diff --git a/packages-private/vapor-e2e-test/transition/style.css b/packages-private/vapor-e2e-test/transition/style.css new file mode 100644 index 000000000..3f1cce3dc --- /dev/null +++ b/packages-private/vapor-e2e-test/transition/style.css @@ -0,0 +1,19 @@ +.v-enter-active, +.v-leave-active { + transition: opacity 50ms ease; +} + +.v-enter-from, +.v-leave-to { + opacity: 0; +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 50ms ease; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} \ No newline at end of file diff --git a/packages-private/vapor-e2e-test/vite.config.ts b/packages-private/vapor-e2e-test/vite.config.ts index 1e29a4dbd..846620ad0 100644 --- a/packages-private/vapor-e2e-test/vite.config.ts +++ b/packages-private/vapor-e2e-test/vite.config.ts @@ -14,6 +14,7 @@ export default defineConfig({ input: { interop: resolve(import.meta.dirname, 'interop/index.html'), todomvc: resolve(import.meta.dirname, 'todomvc/index.html'), + transition: resolve(import.meta.dirname, 'transition/index.html'), }, }, },