]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: e2e tests
authordaiwei <daiwei521@126.com>
Tue, 15 Apr 2025 06:16:07 +0000 (14:16 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 15 Apr 2025 06:16:07 +0000 (14:16 +0800)
packages-private/vapor-e2e-test/__tests__/vdomInterop.spec.ts
packages-private/vapor-e2e-test/interop/App.vue
packages-private/vapor-e2e-test/interop/components/SimpleVaporComp.vue [new file with mode: 0644]
packages/runtime-vapor/src/vdomInterop.ts

index 360f48085a14e7ae4f587d9a89ffeae216f582fc..94a4b4af24da27d76337eac37bf1047b9c546a48 100644 (file)
@@ -6,28 +6,31 @@ import {
 import connect from 'connect'
 import sirv from 'sirv'
 
-describe('vdom / vapor interop', () => {
-  const { page, click, text, enterValue } = setupPuppeteer()
-
-  let server: any
-  const port = '8193'
-  beforeAll(() => {
-    server = connect()
-      .use(sirv(path.resolve(import.meta.dirname, '../dist')))
-      .listen(port)
-    process.on('SIGTERM', () => server && server.close())
-  })
+const { page, click, html, value, text, enterValue } = setupPuppeteer()
+
+let server: any
+const port = '8193'
+beforeAll(() => {
+  server = connect()
+    .use(sirv(path.resolve(import.meta.dirname, '../dist')))
+    .listen(port)
+  process.on('SIGTERM', () => server && server.close())
+})
 
-  afterAll(() => {
-    server.close()
-  })
+afterAll(() => {
+  server.close()
+})
 
+beforeEach(async () => {
+  const baseUrl = `http://localhost:${port}/interop/`
+  await page().goto(baseUrl)
+  await page().waitForSelector('#app')
+})
+
+describe('vdom / vapor interop', () => {
   test(
     'should work',
     async () => {
-      const baseUrl = `http://localhost:${port}/interop/`
-      await page().goto(baseUrl)
-
       expect(await text('.vapor > h2')).toContain('Vapor component in VDOM')
 
       expect(await text('.vapor-prop')).toContain('hello')
@@ -81,4 +84,64 @@ describe('vdom / vapor interop', () => {
     },
     E2E_TIMEOUT,
   )
+
+  describe('keepalive', () => {
+    test(
+      'render vapor component',
+      async () => {
+        const testSelector = '.render-vapor-component'
+        const btnShow = `${testSelector} .btn-show`
+        const btnToggle = `${testSelector} .btn-toggle`
+        const container = `${testSelector} > div`
+        const inputSelector = `${testSelector} input`
+
+        let calls = await page().evaluate(() => {
+          return (window as any).getCalls()
+        })
+        expect(calls).toStrictEqual(['mounted', 'activated'])
+
+        expect(await html(container)).toBe('<input type="text">')
+        expect(await value(inputSelector)).toBe('vapor')
+
+        // change input value
+        await enterValue(inputSelector, 'changed')
+        expect(await value(inputSelector)).toBe('changed')
+
+        // deactivate
+        await click(btnToggle)
+        expect(await html(container)).toBe('<!---->')
+        calls = await page().evaluate(() => {
+          return (window as any).getCalls()
+        })
+        expect(calls).toStrictEqual(['deactivated'])
+
+        // activate
+        await click(btnToggle)
+        expect(await html(container)).toBe('<input type="text">')
+        expect(await value(inputSelector)).toBe('changed')
+        calls = await page().evaluate(() => {
+          return (window as any).getCalls()
+        })
+        expect(calls).toStrictEqual(['activated'])
+
+        // unmount keepalive
+        await click(btnShow)
+        expect(await html(container)).toBe('<!---->')
+        calls = await page().evaluate(() => {
+          return (window as any).getCalls()
+        })
+        expect(calls).toStrictEqual(['deactivated', 'unmounted'])
+
+        // mount keepalive
+        await click(btnShow)
+        expect(await html(container)).toBe('<input type="text">')
+        expect(await value(inputSelector)).toBe('vapor')
+        calls = await page().evaluate(() => {
+          return (window as any).getCalls()
+        })
+        expect(calls).toStrictEqual(['mounted', 'activated'])
+      },
+      E2E_TIMEOUT,
+    )
+  })
 })
index 772a6989dd74c90f2e1cb10fbfed734996cc44fe..cc117b954a45c6af8002205135e9a3b09a9e92d4 100644 (file)
@@ -1,9 +1,20 @@
 <script setup lang="ts">
 import { ref } from 'vue'
 import VaporComp from './VaporComp.vue'
+import SimpleVaporComp from './components/SimpleVaporComp.vue'
 
 const msg = ref('hello')
-const passSlot = ref(true)
+const passSlot = ref(true);
+
+(window as any).calls = [];
+(window as any).getCalls = () => {
+  const ret = (window as any).calls.slice();
+  (window as any).calls = []
+  return ret
+}
+
+const show = ref(true)
+const toggle = ref(true)
 </script>
 
 <template>
@@ -19,4 +30,16 @@ const passSlot = ref(true)
 
     <template #test v-if="passSlot">A test slot</template>
   </VaporComp>
+
+  <!-- keepalive -->
+  <div class="render-vapor-component">
+    <button class="btn-show" @click="show = !show">show</button>
+    <button class="btn-toggle" @click="toggle = !toggle">toggle</button>
+    <div>
+      <KeepAlive v-if="show">
+        <SimpleVaporComp v-if="toggle" />
+      </KeepAlive>
+    </div>
+  </div>
+  <!-- keepalive end -->
 </template>
diff --git a/packages-private/vapor-e2e-test/interop/components/SimpleVaporComp.vue b/packages-private/vapor-e2e-test/interop/components/SimpleVaporComp.vue
new file mode 100644 (file)
index 0000000..873fc97
--- /dev/null
@@ -0,0 +1,20 @@
+<script vapor>
+import { onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue'
+const msg = ref('vapor')
+
+onMounted(() => {
+    window.calls.push('mounted')
+})
+onActivated(() => {
+    window.calls.push('activated')
+})
+onDeactivated(() => {
+    window.calls.push('deactivated')
+})
+onUnmounted(() => {
+    window.calls.push('unmounted')
+})
+</script>
+<template>
+    <input type="text" v-model="msg" />
+</template>
index 0da6ebdbd21afe17b19c5fdd5cfd0c7aaf8c99f8..8ec4652ddda14930c6628487398123b8c307f136 100644 (file)
@@ -30,7 +30,13 @@ import {
   unmountComponent,
 } from './component'
 import { type Block, VaporFragment, insert, remove } from './block'
-import { EMPTY_OBJ, ShapeFlags, extend, isFunction } from '@vue/shared'
+import {
+  EMPTY_OBJ,
+  ShapeFlags,
+  extend,
+  isFunction,
+  isReservedProp,
+} from '@vue/shared'
 import { type RawProps, rawPropsProxyHandlers } from './componentProps'
 import type { RawSlots, VaporSlot } from './componentSlots'
 import { renderEffect } from './renderEffect'
@@ -54,7 +60,15 @@ const vaporInteropImpl: Omit<
     const prev = currentInstance
     simpleSetCurrentInstance(parentComponent)
 
-    const propsRef = shallowRef(vnode.props)
+    // filter out reserved props
+    const props: VNode['props'] = {}
+    for (const key in vnode.props) {
+      if (!isReservedProp(key)) {
+        props[key] = vnode.props[key]
+      }
+    }
+
+    const propsRef = shallowRef(props)
     const slotsRef = shallowRef(vnode.children)
 
     // @ts-expect-error