]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: add vapor transition e2e tests
authordaiwei <daiwei521@126.com>
Thu, 6 Mar 2025 09:40:52 +0000 (17:40 +0800)
committerdaiwei <daiwei521@126.com>
Thu, 6 Mar 2025 09:40:52 +0000 (17:40 +0800)
packages-private/vapor-e2e-test/__tests__/transition.spec.ts [new file with mode: 0644]
packages-private/vapor-e2e-test/index.html
packages-private/vapor-e2e-test/transition/App.vue [new file with mode: 0644]
packages-private/vapor-e2e-test/transition/components/VaporCompA.vue [new file with mode: 0644]
packages-private/vapor-e2e-test/transition/components/VaporCompB.vue [new file with mode: 0644]
packages-private/vapor-e2e-test/transition/index.html [new file with mode: 0644]
packages-private/vapor-e2e-test/transition/main.ts [new file with mode: 0644]
packages-private/vapor-e2e-test/transition/style.css [new file with mode: 0644]
packages-private/vapor-e2e-test/vite.config.ts

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 (file)
index 0000000..922ff0d
--- /dev/null
@@ -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(`<div>vapor compB</div>`)
+
+      // compB -> compA
+      await click(btnSelector)
+      expect(await html(containerSelector)).toBe(
+        `<div class="fade-leave-from fade-leave-active">vapor compB</div>`,
+      )
+
+      await nextFrame()
+      expect(await html(containerSelector)).toBe(
+        `<div class="fade-leave-active fade-leave-to">vapor compB</div>`,
+      )
+
+      await transitionFinish()
+      await nextFrame()
+      expect(await html(containerSelector)).toBe(
+        `<div class="fade-enter-active fade-enter-to">vapor compA</div>`,
+      )
+
+      await transitionFinish()
+      expect(await html(containerSelector)).toBe(
+        `<div class="">vapor compA</div>`,
+      )
+
+      // compA -> compB
+      await click(btnSelector)
+      expect(await html(containerSelector)).toBe(
+        `<div class="fade-leave-from fade-leave-active">vapor compA</div>`,
+      )
+
+      await nextFrame()
+      expect(await html(containerSelector)).toBe(
+        `<div class="fade-leave-active fade-leave-to">vapor compA</div>`,
+      )
+
+      await transitionFinish()
+      await nextFrame()
+      expect(await html(containerSelector)).toBe(
+        `<div class="fade-enter-active fade-enter-to">vapor compB</div>`,
+      )
+
+      await transitionFinish()
+      expect(await html(containerSelector)).toBe(
+        `<div class="">vapor compB</div>`,
+      )
+    },
+    E2E_TIMEOUT,
+  )
+
+  test.todo('should work with in-out mode', async () => {}, E2E_TIMEOUT)
+})
index 7dc205e5ab024878395e5fb22c09679be565c6a3..160e2125d336c8799012c778129d04ba5dbf223c 100644 (file)
@@ -1,2 +1,3 @@
 <a href="/interop/">VDOM / Vapor interop</a>
 <a href="/todomvc/">Vapor TodoMVC</a>
+<a href="/transition/">Vapor Transition</a>
diff --git a/packages-private/vapor-e2e-test/transition/App.vue b/packages-private/vapor-e2e-test/transition/App.vue
new file mode 100644 (file)
index 0000000..6d2ebd0
--- /dev/null
@@ -0,0 +1,47 @@
+<script vapor>
+import { ref, shallowRef } from 'vue'
+const show = ref(true)
+const toggle = ref(true)
+const count = ref(0)
+
+import VaporCompA from './components/VaporCompA.vue'
+import VaporCompB from './components/VaporCompB.vue'
+const activeComponent = shallowRef(VaporCompA)
+function toggleComponent() {
+  activeComponent.value = activeComponent.value === VaporCompA ? VaporCompB : VaporCompA
+}
+</script>
+
+<template>
+  <div class="vshow">
+    <button @click="show = !show">Show</button>
+    <Transition>
+      <h1 v-show="show">vShow</h1>
+    </Transition>
+  </div>
+  <div class="vif">
+    <button @click="toggle = !toggle">Toggle</button>
+    <Transition appear>
+      <h1 v-if="toggle">vIf</h1>
+    </Transition>
+  </div>
+  <div class="keyed">
+    <button @click="count++">inc</button>
+    <Transition>
+      <h1 style="position: absolute" :key="count">{{ count }}</h1>
+    </Transition>
+  </div>
+  <div class="out-in">
+    <button @click="toggleComponent">toggle component</button>
+    <div>
+      <Transition name="fade" mode="out-in">
+        <component :is="activeComponent"></component>
+      </Transition>
+    </div>
+  </div>
+</template>
+<style>
+.keyed {
+  height: 100px
+}
+</style>
\ 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 (file)
index 0000000..24c98ec
--- /dev/null
@@ -0,0 +1,6 @@
+<script vapor>
+const msg = 'vapor compB'
+</script>
+<template>
+    <div>{{ msg }}</div>
+</template>
\ 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 (file)
index 0000000..8064165
--- /dev/null
@@ -0,0 +1,6 @@
+<script vapor>
+const msg = 'vapor compA'
+</script>
+<template>
+    <div>{{ msg }}</div>
+</template>
\ 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 (file)
index 0000000..79052a0
--- /dev/null
@@ -0,0 +1,2 @@
+<script type="module" src="./main.ts"></script>
+<div id="app"></div>
diff --git a/packages-private/vapor-e2e-test/transition/main.ts b/packages-private/vapor-e2e-test/transition/main.ts
new file mode 100644 (file)
index 0000000..d02bb97
--- /dev/null
@@ -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 (file)
index 0000000..3f1cce3
--- /dev/null
@@ -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
index 1e29a4dbd13f89e6d657f6804ec87af653c62924..846620ad017840e0772226335def34401a031a7f 100644 (file)
@@ -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'),
       },
     },
   },