Skip to content

Commit

Permalink
fix tests and implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
pikax committed Oct 12, 2023
1 parent c1ac6d0 commit 9bbab23
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 9 deletions.
122 changes: 114 additions & 8 deletions packages/runtime-core/__tests__/components/Suspense.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1530,7 +1530,7 @@ describe('Suspense', () => {
})

// #5844
test('Suspense + Transition', async () => {
test('Suspense + Transition HTML DOM', async () => {
const InnerA = defineComponent({
setup: () => {
const el = ref<HTMLDivElement | null>(null)
Expand Down Expand Up @@ -1577,7 +1577,8 @@ describe('Suspense', () => {
Transition,
{
name: 'page',
mode: 'out-in'
mode: 'out-in',
duration: 1
},
{
default: () => [
Expand All @@ -1601,15 +1602,120 @@ describe('Suspense', () => {
const root = document.createElement('div')
try {
document.body.appendChild(root)
renderDOM(h(Comp), document.body)
outerToggle.value = true
await nextTick()
renderDOM(h(Comp), root)
expect(document.body.innerHTML).toContain('innerA')

outerToggle.value = true
// give some time for the transition to finish
await new Promise(r => setTimeout(r, 100))
expect(document.body.innerHTML).toContain('innerB')
outerToggle.value = false
// delay it more to error from happening on the CI
await new Promise(r => setTimeout(r, 10))
// give some time for the transition to finish
await new Promise(r => setTimeout(r, 100))
expect(document.body.innerHTML).toContain('innerA')

outerToggle.value = true

// give some time for the transition to finish
await new Promise(r => setTimeout(r, 100))
expect(document.body.innerHTML).toContain('innerB')
} finally {
document.body.innerHTML = ''
document.body.removeChild(root)
}
})

// #5844
test('Suspense + Transition', async () => {
const expectInnerA = '<div id="innerA">innerA</div>'
const expectInnerB = '<div id="innerB">innerB</div>'

const InnerA = defineComponent({
setup: () => {
const el = ref<HTMLDivElement | null>(null)
onMounted(() => {
expect(el.value).toBeTruthy()
expect(serializeInner(root)).toBe(expectInnerA)
})
return () =>
h(
'div',
{
ref: el,
id: 'innerA'
},
'innerA'
)
}
})

const InnerB = defineComponent({
setup: () => {
const el = ref<HTMLDivElement | null>(null)
onMounted(() => {
expect(el.value).toBeTruthy()
console.log('inner b', serializeInner(root))
expect(serializeInner(root)).toBe(expectInnerB)
})
return () =>
h(
'div',
{
ref: el,
id: 'innerB'
},
'innerB'
)
}
})
const outerToggle = ref(false)

const Comp = defineComponent({
setup() {
return () =>
h(
Transition,
{
name: 'page',
mode: 'out-in',
duration: 1
},
{
default: () => [
h(Suspense, null, {
default: [
outerToggle.value
? h(InnerB, {
key: 1
})
: h(InnerA, {
key: 2
})
]
})
]
}
)
}
})

const root = nodeOps.createElement('div')
render(h(Comp), root)
expect(serializeInner(root)).toBe(expectInnerA)

outerToggle.value = true
// give some time for the transition to finish
await new Promise(r => setTimeout(r, 100))
expect(serializeInner(root)).toContain('innerB')
outerToggle.value = false
// give some time for the transition to finish
await new Promise(r => setTimeout(r, 100))
expect(serializeInner(root)).toContain('innerA')

outerToggle.value = true

// give some time for the transition to finish
await new Promise(r => setTimeout(r, 100))
expect(serializeInner(root)).toContain('innerB')
// }
})
})
14 changes: 14 additions & 0 deletions packages/runtime-core/src/components/BaseTransition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,20 @@ export function getTransitionRawChildren(
getTransitionRawChildren(child.children as VNode[], keepComment, key)
)
}
// #5844 suspense children should be able to transition
else if (child.shapeFlag & ShapeFlags.SUSPENSE) {
ret = ret.concat(
getTransitionRawChildren(
Array.isArray(child.children)
? (child.children as VNode[])
: typeof child.children === 'object'
? (child.children?.default as VNode[])
: [],
keepComment,
key
)
)
}
// comment placeholders should be skipped, e.g. v-if
else if (keepComment || child.type !== Comment) {
ret.push(key != null ? cloneVNode(child, { key }) : child)
Expand Down
10 changes: 9 additions & 1 deletion packages/runtime-test/src/nodeOps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export interface TestElement {
children: TestNode[]
props: Record<string, any>
eventListeners: Record<string, Function | Function[]> | null
classList: {
add: (c: string) => void
remove: (c: string) => void
}
}

export interface TestText {
Expand Down Expand Up @@ -79,7 +83,11 @@ function createElement(tag: string): TestElement {
children: [],
props: {},
parentNode: null,
eventListeners: null
eventListeners: null,
classList: {
add(c: string) {},
remove(c: string) {}
}
}
logNodeOp({
type: NodeOpTypes.CREATE,
Expand Down

0 comments on commit 9bbab23

Please sign in to comment.