mirror of https://github.com/vuejs/core.git
test: port tests
This commit is contained in:
parent
e8320b713b
commit
032f46f23c
|
@ -5,7 +5,9 @@ import {
|
||||||
onDeactivated,
|
onDeactivated,
|
||||||
onMounted,
|
onMounted,
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
|
reactive,
|
||||||
ref,
|
ref,
|
||||||
|
shallowRef,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import type { LooseRawProps, VaporComponent } from '../../src/component'
|
import type { LooseRawProps, VaporComponent } from '../../src/component'
|
||||||
import { makeRender } from '../_utils'
|
import { makeRender } from '../_utils'
|
||||||
|
@ -1037,4 +1039,151 @@ describe('VaporKeepAlive', () => {
|
||||||
expect(html()).toBe(`<div>1</div><!--if-->`)
|
expect(html()).toBe(`<div>1</div><!--if-->`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test.todo('should work with async component', async () => {})
|
||||||
|
|
||||||
|
test('handle error in async onActivated', async () => {
|
||||||
|
const err = new Error('foo')
|
||||||
|
const handler = vi.fn()
|
||||||
|
const Child = defineVaporComponent({
|
||||||
|
setup() {
|
||||||
|
onActivated(async () => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
|
||||||
|
return template(`<span></span`)()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { app } = define({
|
||||||
|
setup() {
|
||||||
|
return createComponent(VaporKeepAlive, null, {
|
||||||
|
default: () => createComponent(Child),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}).create()
|
||||||
|
|
||||||
|
app.config.errorHandler = handler
|
||||||
|
app.mount(document.createElement('div'))
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
|
expect(handler).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should avoid unmount later included components', async () => {
|
||||||
|
const unmountedA = vi.fn()
|
||||||
|
const mountedA = vi.fn()
|
||||||
|
const activatedA = vi.fn()
|
||||||
|
const deactivatedA = vi.fn()
|
||||||
|
const unmountedB = vi.fn()
|
||||||
|
const mountedB = vi.fn()
|
||||||
|
|
||||||
|
const A = defineVaporComponent({
|
||||||
|
name: 'A',
|
||||||
|
setup() {
|
||||||
|
onMounted(mountedA)
|
||||||
|
onUnmounted(unmountedA)
|
||||||
|
onActivated(activatedA)
|
||||||
|
onDeactivated(deactivatedA)
|
||||||
|
return template(`<div>A</div>`)()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const B = defineVaporComponent({
|
||||||
|
name: 'B',
|
||||||
|
setup() {
|
||||||
|
onMounted(mountedB)
|
||||||
|
onUnmounted(unmountedB)
|
||||||
|
return template(`<div>B</div>`)()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const include = reactive<string[]>([])
|
||||||
|
const current = shallowRef(A)
|
||||||
|
const { html } = define({
|
||||||
|
setup() {
|
||||||
|
return createComponent(
|
||||||
|
VaporKeepAlive,
|
||||||
|
{ include: () => include },
|
||||||
|
{
|
||||||
|
default: () => createDynamicComponent(() => current.value),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}).render()
|
||||||
|
|
||||||
|
expect(html()).toBe(`<div>A</div><!--dynamic-component-->`)
|
||||||
|
expect(mountedA).toHaveBeenCalledTimes(1)
|
||||||
|
expect(unmountedA).toHaveBeenCalledTimes(0)
|
||||||
|
expect(activatedA).toHaveBeenCalledTimes(0)
|
||||||
|
expect(deactivatedA).toHaveBeenCalledTimes(0)
|
||||||
|
expect(mountedB).toHaveBeenCalledTimes(0)
|
||||||
|
expect(unmountedB).toHaveBeenCalledTimes(0)
|
||||||
|
|
||||||
|
include.push('A') // cache A
|
||||||
|
await nextTick()
|
||||||
|
current.value = B // toggle to B
|
||||||
|
await nextTick()
|
||||||
|
expect(html()).toBe(`<div>B</div><!--dynamic-component-->`)
|
||||||
|
expect(mountedA).toHaveBeenCalledTimes(1)
|
||||||
|
expect(unmountedA).toHaveBeenCalledTimes(0)
|
||||||
|
expect(activatedA).toHaveBeenCalledTimes(0)
|
||||||
|
expect(deactivatedA).toHaveBeenCalledTimes(1)
|
||||||
|
expect(mountedB).toHaveBeenCalledTimes(1)
|
||||||
|
expect(unmountedB).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('remove component from include then switching child', async () => {
|
||||||
|
const About = defineVaporComponent({
|
||||||
|
name: 'About',
|
||||||
|
setup() {
|
||||||
|
return template(`<h1>About</h1>`)()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const mountedHome = vi.fn()
|
||||||
|
const unmountedHome = vi.fn()
|
||||||
|
const activatedHome = vi.fn()
|
||||||
|
const deactivatedHome = vi.fn()
|
||||||
|
|
||||||
|
const Home = defineVaporComponent({
|
||||||
|
name: 'Home',
|
||||||
|
setup() {
|
||||||
|
onMounted(mountedHome)
|
||||||
|
onUnmounted(unmountedHome)
|
||||||
|
onDeactivated(deactivatedHome)
|
||||||
|
onActivated(activatedHome)
|
||||||
|
return template(`<h1>Home</h1>`)()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const activeViewName = ref('Home')
|
||||||
|
const cacheList = reactive(['Home'])
|
||||||
|
|
||||||
|
define({
|
||||||
|
setup() {
|
||||||
|
return createComponent(
|
||||||
|
VaporKeepAlive,
|
||||||
|
{ include: () => cacheList },
|
||||||
|
{
|
||||||
|
default: () => {
|
||||||
|
return createIf(
|
||||||
|
() => activeViewName.value === 'Home',
|
||||||
|
() => createComponent(Home),
|
||||||
|
() => createComponent(About),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}).render()
|
||||||
|
|
||||||
|
expect(mountedHome).toHaveBeenCalledTimes(1)
|
||||||
|
expect(activatedHome).toHaveBeenCalledTimes(1)
|
||||||
|
cacheList.splice(0, 1)
|
||||||
|
await nextTick()
|
||||||
|
activeViewName.value = 'About'
|
||||||
|
await nextTick()
|
||||||
|
expect(deactivatedHome).toHaveBeenCalledTimes(0)
|
||||||
|
expect(unmountedHome).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,7 +12,13 @@ import {
|
||||||
warn,
|
warn,
|
||||||
watch,
|
watch,
|
||||||
} from '@vue/runtime-dom'
|
} from '@vue/runtime-dom'
|
||||||
import { type Block, insert, isFragment, isValidBlock } from '../block'
|
import {
|
||||||
|
type Block,
|
||||||
|
DynamicFragment,
|
||||||
|
insert,
|
||||||
|
isFragment,
|
||||||
|
isValidBlock,
|
||||||
|
} from '../block'
|
||||||
import {
|
import {
|
||||||
type ObjectVaporComponent,
|
type ObjectVaporComponent,
|
||||||
type VaporComponent,
|
type VaporComponent,
|
||||||
|
@ -153,7 +159,7 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const children = slots.default()
|
let children = slots.default()
|
||||||
if (isArray(children) && children.length > 1) {
|
if (isArray(children) && children.length > 1) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
warn(`KeepAlive should contain exactly one component child.`)
|
warn(`KeepAlive should contain exactly one component child.`)
|
||||||
|
@ -161,6 +167,13 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
|
||||||
return children
|
return children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wrap children in dynamic fragment
|
||||||
|
if (!isFragment(children)) {
|
||||||
|
const frag = new DynamicFragment()
|
||||||
|
frag.update(() => children)
|
||||||
|
children = frag
|
||||||
|
}
|
||||||
|
|
||||||
function pruneCache(filter: (name: string) => boolean) {
|
function pruneCache(filter: (name: string) => boolean) {
|
||||||
cache.forEach((instance, key) => {
|
cache.forEach((instance, key) => {
|
||||||
const name = getComponentName(instance.type)
|
const name = getComponentName(instance.type)
|
||||||
|
@ -197,16 +210,6 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const VaporKeepAlive = VaporKeepAliveImpl as any as {
|
|
||||||
__isKeepAlive: true
|
|
||||||
new (): {
|
|
||||||
$props: KeepAliveProps
|
|
||||||
$slots: {
|
|
||||||
default(): Block
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getInnerBlock(block: Block): VaporComponentInstance | undefined {
|
function getInnerBlock(block: Block): VaporComponentInstance | undefined {
|
||||||
if (isVaporComponent(block)) {
|
if (isVaporComponent(block)) {
|
||||||
return block
|
return block
|
||||||
|
|
|
@ -3,7 +3,7 @@ export { createVaporApp, createVaporSSRApp } from './apiCreateApp'
|
||||||
export { defineVaporComponent } from './apiDefineComponent'
|
export { defineVaporComponent } from './apiDefineComponent'
|
||||||
export { vaporInteropPlugin } from './vdomInterop'
|
export { vaporInteropPlugin } from './vdomInterop'
|
||||||
export type { VaporDirective } from './directives/custom'
|
export type { VaporDirective } from './directives/custom'
|
||||||
export { VaporKeepAlive } from './components/KeepAlive'
|
export { VaporKeepAliveImpl as VaporKeepAlive } from './components/KeepAlive'
|
||||||
|
|
||||||
// compiler-use only
|
// compiler-use only
|
||||||
export { insert, prepend, remove, isFragment, VaporFragment } from './block'
|
export { insert, prepend, remove, isFragment, VaporFragment } from './block'
|
||||||
|
|
Loading…
Reference in New Issue