]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: e2e tests
authordaiwei <daiwei521@126.com>
Tue, 15 Apr 2025 03:41:34 +0000 (11:41 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 15 Apr 2025 03:41:34 +0000 (11:41 +0800)
packages-private/vapor-e2e-test/__tests__/keepalive.spec.ts [new file with mode: 0644]
packages-private/vapor-e2e-test/index.html
packages-private/vapor-e2e-test/keepalive/App.vue [new file with mode: 0644]
packages-private/vapor-e2e-test/keepalive/components/VdomComp.vue [new file with mode: 0644]
packages-private/vapor-e2e-test/keepalive/index.html [new file with mode: 0644]
packages-private/vapor-e2e-test/keepalive/main.ts [new file with mode: 0644]
packages-private/vapor-e2e-test/package.json
packages-private/vapor-e2e-test/vite.config.ts
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/components/KeepAlive.ts

diff --git a/packages-private/vapor-e2e-test/__tests__/keepalive.spec.ts b/packages-private/vapor-e2e-test/__tests__/keepalive.spec.ts
new file mode 100644 (file)
index 0000000..7f98a1f
--- /dev/null
@@ -0,0 +1,87 @@
+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, html, click, value, enterValue } = setupPuppeteer()
+
+describe('vapor keepalive', () => {
+  let server: any
+  const port = '8196'
+  beforeAll(() => {
+    server = connect()
+      .use(sirv(path.resolve(import.meta.dirname, '../dist')))
+      .listen(port)
+    process.on('SIGTERM', () => server && server.close())
+  })
+
+  beforeEach(async () => {
+    const baseUrl = `http://localhost:${port}/keepalive/`
+    await page().goto(baseUrl)
+    await page().waitForSelector('#app')
+  })
+
+  afterAll(() => {
+    server.close()
+  })
+
+  test(
+    'render vdom component',
+    async () => {
+      const testSelector = '.render-vdom-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('vdom')
+
+      // 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('vdom')
+      calls = await page().evaluate(() => {
+        return (window as any).getCalls()
+      })
+      expect(calls).toStrictEqual(['mounted', 'activated'])
+    },
+    E2E_TIMEOUT,
+  )
+})
index 7dc205e5ab024878395e5fb22c09679be565c6a3..29ec129cafeaea50d224b31cf0a8d098ec3ebe1f 100644 (file)
@@ -1,2 +1,3 @@
 <a href="/interop/">VDOM / Vapor interop</a>
 <a href="/todomvc/">Vapor TodoMVC</a>
+<a href="/keepalive/">Vapor KeepAlive</a>
diff --git a/packages-private/vapor-e2e-test/keepalive/App.vue b/packages-private/vapor-e2e-test/keepalive/App.vue
new file mode 100644 (file)
index 0000000..b7c088f
--- /dev/null
@@ -0,0 +1,26 @@
+<script vapor>
+import { ref } from 'vue'
+import VdomComp from './components/VdomComp.vue';
+
+window.calls = []
+window.getCalls = () => {
+  const ret = window.calls.slice()
+  window.calls = []
+  return ret
+}
+
+const show = ref(true)
+const toggle = ref(true)
+</script>
+
+<template>
+  <div class="render-vdom-component">
+    <button class="btn-show" @click="show = !show">show</button>
+    <button class="btn-toggle" @click="toggle = !toggle">toggle</button>
+    <div>
+      <KeepAlive v-if="show">
+        <VdomComp v-if="toggle"></VdomComp>
+      </KeepAlive>
+    </div>
+  </div>
+</template>
diff --git a/packages-private/vapor-e2e-test/keepalive/components/VdomComp.vue b/packages-private/vapor-e2e-test/keepalive/components/VdomComp.vue
new file mode 100644 (file)
index 0000000..ca173c5
--- /dev/null
@@ -0,0 +1,20 @@
+<script setup>
+import { onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue'
+const msg = ref('vdom')
+
+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>
\ No newline at end of file
diff --git a/packages-private/vapor-e2e-test/keepalive/index.html b/packages-private/vapor-e2e-test/keepalive/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/keepalive/main.ts b/packages-private/vapor-e2e-test/keepalive/main.ts
new file mode 100644 (file)
index 0000000..bc6b491
--- /dev/null
@@ -0,0 +1,4 @@
+import { createVaporApp, vaporInteropPlugin } from 'vue'
+import App from './App.vue'
+
+createVaporApp(App).use(vaporInteropPlugin).mount('#app')
index 66ea0457ec9aa74c33524c12f75a6d5cb4521185..d5d358f3cf1a08859f8c19e8d7f7c32e9df442b9 100644 (file)
@@ -5,7 +5,7 @@
   "type": "module",
   "scripts": {
     "dev": "vite dev",
-    "build": "vite build"
+    "build": "vite build && vite preview"
   },
   "devDependencies": {
     "@types/connect": "^3.4.38",
index 1e29a4dbd13f89e6d657f6804ec87af653c62924..34cbd79985d09b87802569dc9fdaca833f258e88 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'),
+        keepalive: resolve(import.meta.dirname, 'keepalive/index.html'),
       },
     },
   },
index f1e526106fe4c7849c103ddaf270deb19b0ab4a2..e66d82b5c6b7930b36e910d3a9a7297059beaa4c 100644 (file)
@@ -174,9 +174,9 @@ export function createComponent(
     )
     // TODO: problem is `frag.insert` will be called multiple times
     // if used in v-if
-    if (!isHydrating && _insertionParent) {
-      insert(frag, _insertionParent, _insertionAnchor)
-    }
+    // if (!isHydrating && _insertionParent) {
+    //   insert(frag, _insertionParent, _insertionAnchor)
+    // }
     return frag
   }
 
index 3c097f6696d15e456a554696ddd985b76f372fad..8ccc6d5538e0769c1ec0c7e0987ea782fd1f93e1 100644 (file)
@@ -66,9 +66,9 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
     const storageContainer = createElement('div')
     let current: VaporComponentInstance | VaporFragment | undefined
 
-    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
-      ;(keepAliveInstance as any).__v_cache = cache
-    }
+    // if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
+    //   ;(keepAliveInstance as any).__v_cache = cache
+    // }
 
     function shouldCache(instance: VaporComponentInstance) {
       const { include, exclude } = props
@@ -120,12 +120,16 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
         if (current) {
           const innerComp = getInnerComponent(current)!
           if (innerComp.type === cached.type) {
-            const da = cached.da
+            const instance = cached.vapor
+              ? cached
+              : // vdom interop
+                (cached as any).component
+            const da = instance.da
             da && queuePostFlushCb(da)
             return
           }
         }
-        remove(cached, storageContainer)
+        remove(item, storageContainer)
       })
     })