import {
h,
render,
nodeOps,
serializeInner,
renderSlot
} from '@vue/runtime-test'
import { setScopeId, withCtx } from '../src/componentRenderContext'
describe('scopeId runtime support', () => {
test('should attach scopeId', () => {
const App = {
__scopeId: 'parent',
render: () => h('div', [h('div')])
}
const root = nodeOps.createElement('div')
render(h(App), root)
expect(serializeInner(root)).toBe(`
`)
})
test('should attach scopeId to components in parent component', () => {
const Child = {
__scopeId: 'child',
render: () => h('div')
}
const App = {
__scopeId: 'parent',
render: () => h('div', [h(Child)])
}
const root = nodeOps.createElement('div')
render(h(App), root)
expect(serializeInner(root)).toBe(
``
)
})
// :slotted basic
test('should work on slots', () => {
const Child = {
__scopeId: 'child',
render(this: any) {
return h('div', renderSlot(this.$slots, 'default', {}, undefined, true))
}
}
const Child2 = {
__scopeId: 'child2',
render: () => h('span')
}
const App = {
__scopeId: 'parent',
render: () => {
return h(
Child,
withCtx(() => {
return [h('div'), h(Child2)]
})
)
}
}
const root = nodeOps.createElement('div')
render(h(App), root)
// slot content should have:
// - scopeId from parent
// - slotted scopeId (with `-s` postfix) from child (the tree owner)
expect(serializeInner(root)).toBe(
`` +
`
` +
// component inside slot should have:
// - scopeId from template context
// - slotted scopeId from slot owner
// - its own scopeId
`
` +
`
`
)
})
// #2892
test(':slotted on forwarded slots', async () => {
const Wrapper = {
__scopeId: 'wrapper',
render(this: any) {
//
return h('div', { class: 'wrapper' }, [
renderSlot(this.$slots, 'default')
])
}
}
const Slotted = {
__scopeId: 'slotted',
render(this: any) {
//
return h(Wrapper, null, {
default: withCtx(() => [
renderSlot(this.$slots, 'default', {}, undefined, true)
])
})
}
}
// simulate hoisted node
setScopeId('root')
const hoisted = h('div', 'hoisted')
setScopeId(null)
const Root = {
__scopeId: 'root',
render(this: any) {
// hoisted
{{ dynamic }}
return h(Slotted, null, {
default: withCtx(() => {
return [hoisted, h('div', 'dynamic')]
})
})
}
}
const root = nodeOps.createElement('div')
render(h(Root), root)
expect(serializeInner(root)).toBe(
`` +
`
hoisted
` +
`
dynamic
` +
`
`
)
const Root2 = {
__scopeId: 'root',
render(this: any) {
//
//
// hoisted
{{ dynamic }}
//
//
return h(Slotted, null, {
default: withCtx(() => [
h(Wrapper, null, {
default: withCtx(() => [hoisted, h('div', 'dynamic')])
})
])
})
}
}
const root2 = nodeOps.createElement('div')
render(h(Root2), root2)
expect(serializeInner(root2)).toBe(
`` +
`
` +
`
hoisted
` +
`
dynamic
` +
`
` +
`
`
)
})
// #1988
test('should inherit scopeId through nested HOCs with inheritAttrs: false', () => {
const App = {
__scopeId: 'parent',
render: () => {
return h(Child)
}
}
function Child() {
return h(Child2, { class: 'foo' })
}
function Child2() {
return h('div')
}
Child2.inheritAttrs = false
const root = nodeOps.createElement('div')
render(h(App), root)
expect(serializeInner(root)).toBe(``)
})
})