|
|
@@ -1,8 +1,14 @@
|
|
|
import {
|
|
|
+ KeepAlive,
|
|
|
createVNode,
|
|
|
defineComponent,
|
|
|
h,
|
|
|
nextTick,
|
|
|
+ onActivated,
|
|
|
+ onBeforeMount,
|
|
|
+ onDeactivated,
|
|
|
+ onMounted,
|
|
|
+ onUnmounted,
|
|
|
ref,
|
|
|
renderSlot,
|
|
|
toDisplayString,
|
|
|
@@ -14,6 +20,7 @@ import {
|
|
|
applyVShow,
|
|
|
child,
|
|
|
createComponent,
|
|
|
+ defineVaporAsyncComponent,
|
|
|
defineVaporComponent,
|
|
|
renderEffect,
|
|
|
setText,
|
|
|
@@ -275,4 +282,140 @@ describe('vdomInterop', () => {
|
|
|
expect(fn).toHaveBeenCalledTimes(1)
|
|
|
})
|
|
|
})
|
|
|
+
|
|
|
+ describe('async component', () => {
|
|
|
+ const duration = 5
|
|
|
+ test('render vapor async component', async () => {
|
|
|
+ const VdomChild = {
|
|
|
+ setup() {
|
|
|
+ return () => h('div', 'foo')
|
|
|
+ },
|
|
|
+ }
|
|
|
+ const VaporAsyncChild = defineVaporAsyncComponent({
|
|
|
+ loader: () => {
|
|
|
+ return new Promise(r => {
|
|
|
+ setTimeout(() => {
|
|
|
+ r(VdomChild as any)
|
|
|
+ }, duration)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ loadingComponent: () => h('span', 'loading...'),
|
|
|
+ })
|
|
|
+
|
|
|
+ const { html } = define({
|
|
|
+ setup() {
|
|
|
+ return () => h(VaporAsyncChild as any)
|
|
|
+ },
|
|
|
+ }).render()
|
|
|
+
|
|
|
+ expect(html()).toBe('<span>loading...</span><!--async component-->')
|
|
|
+
|
|
|
+ await new Promise(r => setTimeout(r, duration))
|
|
|
+ await nextTick()
|
|
|
+ expect(html()).toBe('<div>foo</div><!--async component-->')
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ describe('keepalive', () => {
|
|
|
+ function assertHookCalls(
|
|
|
+ hooks: {
|
|
|
+ beforeMount: any
|
|
|
+ mounted: any
|
|
|
+ activated: any
|
|
|
+ deactivated: any
|
|
|
+ unmounted: any
|
|
|
+ },
|
|
|
+ callCounts: number[],
|
|
|
+ ) {
|
|
|
+ expect([
|
|
|
+ hooks.beforeMount.mock.calls.length,
|
|
|
+ hooks.mounted.mock.calls.length,
|
|
|
+ hooks.activated.mock.calls.length,
|
|
|
+ hooks.deactivated.mock.calls.length,
|
|
|
+ hooks.unmounted.mock.calls.length,
|
|
|
+ ]).toEqual(callCounts)
|
|
|
+ }
|
|
|
+
|
|
|
+ let hooks: any
|
|
|
+ beforeEach(() => {
|
|
|
+ hooks = {
|
|
|
+ beforeMount: vi.fn(),
|
|
|
+ mounted: vi.fn(),
|
|
|
+ activated: vi.fn(),
|
|
|
+ deactivated: vi.fn(),
|
|
|
+ unmounted: vi.fn(),
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ test('render vapor component', async () => {
|
|
|
+ const VaporChild = defineVaporComponent({
|
|
|
+ setup() {
|
|
|
+ const msg = ref('vapor')
|
|
|
+ onBeforeMount(() => hooks.beforeMount())
|
|
|
+ onMounted(() => hooks.mounted())
|
|
|
+ onActivated(() => hooks.activated())
|
|
|
+ onDeactivated(() => hooks.deactivated())
|
|
|
+ onUnmounted(() => hooks.unmounted())
|
|
|
+
|
|
|
+ const n0 = template('<input type="text">', true)() as any
|
|
|
+ applyTextModel(
|
|
|
+ n0,
|
|
|
+ () => msg.value,
|
|
|
+ _value => (msg.value = _value),
|
|
|
+ )
|
|
|
+ return n0
|
|
|
+ },
|
|
|
+ })
|
|
|
+
|
|
|
+ const show = ref(true)
|
|
|
+ const toggle = ref(true)
|
|
|
+ const { html, host } = define({
|
|
|
+ setup() {
|
|
|
+ return () =>
|
|
|
+ show.value
|
|
|
+ ? h(KeepAlive, null, {
|
|
|
+ default: () => (toggle.value ? h(VaporChild as any) : null),
|
|
|
+ })
|
|
|
+ : null
|
|
|
+ },
|
|
|
+ }).render()
|
|
|
+
|
|
|
+ expect(html()).toBe('<input type="text">')
|
|
|
+ let inputEl = host.firstChild as HTMLInputElement
|
|
|
+ expect(inputEl.value).toBe('vapor')
|
|
|
+ assertHookCalls(hooks, [1, 1, 1, 0, 0])
|
|
|
+
|
|
|
+ // change input value
|
|
|
+ inputEl.value = 'changed'
|
|
|
+ inputEl.dispatchEvent(new Event('input'))
|
|
|
+ await nextTick()
|
|
|
+
|
|
|
+ // deactivate
|
|
|
+ toggle.value = false
|
|
|
+ await nextTick()
|
|
|
+ expect(html()).toBe('<!---->')
|
|
|
+ assertHookCalls(hooks, [1, 1, 1, 1, 0])
|
|
|
+
|
|
|
+ // activate
|
|
|
+ toggle.value = true
|
|
|
+ await nextTick()
|
|
|
+ expect(html()).toBe('<input type="text">')
|
|
|
+ inputEl = host.firstChild as HTMLInputElement
|
|
|
+ expect(inputEl.value).toBe('changed')
|
|
|
+ assertHookCalls(hooks, [1, 1, 2, 1, 0])
|
|
|
+
|
|
|
+ // unmount keepalive
|
|
|
+ show.value = false
|
|
|
+ await nextTick()
|
|
|
+ expect(html()).toBe('<!---->')
|
|
|
+ assertHookCalls(hooks, [1, 1, 2, 2, 1])
|
|
|
+
|
|
|
+ // mount keepalive
|
|
|
+ show.value = true
|
|
|
+ await nextTick()
|
|
|
+ inputEl = host.firstChild as HTMLInputElement
|
|
|
+ expect(inputEl.value).toBe('vapor')
|
|
|
+ assertHookCalls(hooks, [2, 2, 3, 2, 1])
|
|
|
+ })
|
|
|
+ })
|
|
|
})
|