test: port tests

This commit is contained in:
daiwei 2025-04-09 21:47:00 +08:00
parent 1c5d833a76
commit a103715cfb
2 changed files with 238 additions and 9 deletions

View File

@ -7,7 +7,7 @@ import {
onUnmounted,
ref,
} from 'vue'
import type { VaporComponent } from '../../src/component'
import type { LooseRawProps, VaporComponent } from '../../src/component'
import { makeRender } from '../_utils'
import { VaporKeepAliveImpl as VaporKeepAlive } from '../../src/components/KeepAlive'
import {
@ -70,6 +70,13 @@ describe('VaporKeepAlive', () => {
return n0
},
})
oneTestHooks = {
beforeMount: vi.fn(),
mounted: vi.fn(),
activated: vi.fn(),
deactivated: vi.fn(),
unmounted: vi.fn(),
}
oneTest = defineVaporComponent({
name: 'oneTest',
setup() {
@ -469,4 +476,215 @@ describe('VaporKeepAlive', () => {
assertHookCalls(oneHooks, [1, 1, 4, 3, 0])
assertHookCalls(twoHooks, [1, 1, 4, 4, 0]) // should remain inactive
})
async function assertNameMatch(props: LooseRawProps) {
const outerRef = ref(true)
const viewRef = ref('one')
const { html } = define({
setup() {
return createIf(
() => outerRef.value,
() =>
createComponent(VaporKeepAlive, props, {
default: () => createDynamicComponent(() => views[viewRef.value]),
}),
)
},
}).render()
expect(html()).toBe(`<div>one</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 1, 0, 0])
assertHookCalls(twoHooks, [0, 0, 0, 0, 0])
viewRef.value = 'two'
await nextTick()
expect(html()).toBe(`<div>two</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 1, 1, 0])
assertHookCalls(twoHooks, [1, 1, 0, 0, 0])
viewRef.value = 'one'
await nextTick()
expect(html()).toBe(`<div>one</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 2, 1, 0])
assertHookCalls(twoHooks, [1, 1, 0, 0, 1])
viewRef.value = 'two'
await nextTick()
expect(html()).toBe(`<div>two</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 2, 2, 0])
assertHookCalls(twoHooks, [2, 2, 0, 0, 1])
// teardown
outerRef.value = false
await nextTick()
expect(html()).toBe(`<!--if-->`)
assertHookCalls(oneHooks, [1, 1, 2, 2, 1])
assertHookCalls(twoHooks, [2, 2, 0, 0, 2])
}
async function assertNameMatchWithFlag(props: LooseRawProps) {
const outerRef = ref(true)
const viewRef = ref('one')
const { html } = define({
setup() {
return createIf(
() => outerRef.value,
() =>
createComponent(VaporKeepAlive, props, {
default: () => createDynamicComponent(() => views[viewRef.value]),
}),
)
},
}).render()
expect(html()).toBe(`<div>one</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 1, 0, 0])
assertHookCalls(oneTestHooks, [0, 0, 0, 0, 0])
assertHookCalls(twoHooks, [0, 0, 0, 0, 0])
viewRef.value = 'oneTest'
await nextTick()
expect(html()).toBe(`<div>oneTest</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 1, 1, 0])
assertHookCalls(oneTestHooks, [1, 1, 1, 0, 0])
assertHookCalls(twoHooks, [0, 0, 0, 0, 0])
viewRef.value = 'two'
await nextTick()
expect(html()).toBe(`<div>two</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 1, 1, 0])
assertHookCalls(oneTestHooks, [1, 1, 1, 1, 0])
assertHookCalls(twoHooks, [1, 1, 0, 0, 0])
viewRef.value = 'one'
await nextTick()
expect(html()).toBe(`<div>one</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 2, 1, 0])
assertHookCalls(oneTestHooks, [1, 1, 1, 1, 0])
assertHookCalls(twoHooks, [1, 1, 0, 0, 1])
viewRef.value = 'oneTest'
await nextTick()
expect(html()).toBe(`<div>oneTest</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 2, 2, 0])
assertHookCalls(oneTestHooks, [1, 1, 2, 1, 0])
assertHookCalls(twoHooks, [1, 1, 0, 0, 1])
viewRef.value = 'two'
await nextTick()
expect(html()).toBe(`<div>two</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 2, 2, 0])
assertHookCalls(oneTestHooks, [1, 1, 2, 2, 0])
assertHookCalls(twoHooks, [2, 2, 0, 0, 1])
// teardown
outerRef.value = false
await nextTick()
expect(html()).toBe(`<!--if-->`)
assertHookCalls(oneHooks, [1, 1, 2, 2, 1])
assertHookCalls(oneTestHooks, [1, 1, 2, 2, 1])
assertHookCalls(twoHooks, [2, 2, 0, 0, 2])
}
async function assertNameMatchWithFlagExclude(props: LooseRawProps) {
const outerRef = ref(true)
const viewRef = ref('one')
const { html } = define({
setup() {
return createIf(
() => outerRef.value,
() =>
createComponent(VaporKeepAlive, props, {
default: () => createDynamicComponent(() => views[viewRef.value]),
}),
)
},
}).render()
expect(html()).toBe(`<div>one</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 0, 0, 0])
assertHookCalls(oneTestHooks, [0, 0, 0, 0, 0])
assertHookCalls(twoHooks, [0, 0, 0, 0, 0])
viewRef.value = 'oneTest'
await nextTick()
expect(html()).toBe(`<div>oneTest</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 0, 0, 1])
assertHookCalls(oneTestHooks, [1, 1, 0, 0, 0])
assertHookCalls(twoHooks, [0, 0, 0, 0, 0])
viewRef.value = 'two'
await nextTick()
expect(html()).toBe(`<div>two</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [1, 1, 0, 0, 1])
assertHookCalls(oneTestHooks, [1, 1, 0, 0, 1])
assertHookCalls(twoHooks, [1, 1, 1, 0, 0])
viewRef.value = 'one'
await nextTick()
expect(html()).toBe(`<div>one</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [2, 2, 0, 0, 1])
assertHookCalls(oneTestHooks, [1, 1, 0, 0, 1])
assertHookCalls(twoHooks, [1, 1, 1, 1, 0])
viewRef.value = 'oneTest'
await nextTick()
expect(html()).toBe(`<div>oneTest</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [2, 2, 0, 0, 2])
assertHookCalls(oneTestHooks, [2, 2, 0, 0, 1])
assertHookCalls(twoHooks, [1, 1, 1, 1, 0])
viewRef.value = 'two'
await nextTick()
expect(html()).toBe(`<div>two</div><!--dynamic-component--><!--if-->`)
assertHookCalls(oneHooks, [2, 2, 0, 0, 2])
assertHookCalls(oneTestHooks, [2, 2, 0, 0, 2])
assertHookCalls(twoHooks, [1, 1, 2, 1, 0])
// teardown
outerRef.value = false
await nextTick()
expect(html()).toBe(`<!--if-->`)
assertHookCalls(oneHooks, [2, 2, 0, 0, 2])
assertHookCalls(oneTestHooks, [2, 2, 0, 0, 2])
assertHookCalls(twoHooks, [1, 1, 2, 2, 1])
}
describe('props', () => {
test('include (string)', async () => {
await assertNameMatch({ include: () => 'one' })
})
test('include (regex)', async () => {
await assertNameMatch({ include: () => /^one$/ })
})
test('include (regex with g flag)', async () => {
await assertNameMatchWithFlag({ include: () => /one/g })
})
test('include (array)', async () => {
await assertNameMatch({ include: () => ['one'] })
})
test('exclude (string)', async () => {
await assertNameMatch({ exclude: () => 'two' })
})
test('exclude (regex)', async () => {
await assertNameMatch({ exclude: () => /^two$/ })
})
test('exclude (regex with a flag)', async () => {
await assertNameMatchWithFlagExclude({ exclude: () => /one/g })
})
test('exclude (array)', async () => {
await assertNameMatch({ exclude: () => ['two'] })
})
test('include + exclude', async () => {
await assertNameMatch({ include: () => 'one,two', exclude: () => 'two' })
})
})
})

View File

@ -64,13 +64,21 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
const { include, exclude, max } = props
function shouldCache(instance: VaporComponentInstance) {
const name = getComponentName(instance.type)
return !(
(include && (!name || !matches(include, name))) ||
(exclude && name && matches(exclude, name))
)
}
function cacheBlock() {
// TODO suspense
const currentBlock = keepAliveInstance.block!
if (!isValidBlock(currentBlock)) return
const block = getInnerBlock(currentBlock)!
if (!block) return
if (!block || !shouldCache(block)) return
const key = block.type
if (cache.has(key)) {
@ -111,13 +119,16 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
instance.shapeFlag! |= ShapeFlags.COMPONENT_KEPT_ALIVE
}
const name = getComponentName(instance.type)
if (
!(
(include && (!name || !matches(include, name))) ||
(exclude && name && matches(exclude, name))
)
) {
// const name = getComponentName(instance.type)
// if (
// !(
// (include && (!name || !matches(include, name))) ||
// (exclude && name && matches(exclude, name))
// )
// ) {
// instance.shapeFlag! |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
// }
if (shouldCache(instance)) {
instance.shapeFlag! |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
}
}