@@ -14,8 +14,7 @@ import {
|
||||
ComponentPublicInstance,
|
||||
Ref,
|
||||
cloneVNode,
|
||||
provide,
|
||||
withScopeId
|
||||
provide
|
||||
} from '@vue/runtime-test'
|
||||
import { KeepAliveProps } from '../../src/components/KeepAlive'
|
||||
|
||||
@@ -804,14 +803,13 @@ describe('KeepAlive', () => {
|
||||
test('should work with cloned root due to scopeId / fallthrough attrs', async () => {
|
||||
const viewRef = ref('one')
|
||||
const instanceRef = ref<any>(null)
|
||||
const withId = withScopeId('foo')
|
||||
const App = {
|
||||
__scopeId: 'foo',
|
||||
render: withId(() => {
|
||||
render: () => {
|
||||
return h(KeepAlive, null, {
|
||||
default: () => h(views[viewRef.value], { ref: instanceRef })
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
render(h(App), root)
|
||||
expect(serializeInner(root)).toBe(`<div foo>one</div>`)
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
Fragment,
|
||||
createCommentVNode
|
||||
} from '../../src'
|
||||
import { PatchFlags } from '@vue/shared/src'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
|
||||
describe('renderSlot', () => {
|
||||
it('should render slot', () => {
|
||||
@@ -37,7 +37,7 @@ describe('renderSlot', () => {
|
||||
return [createVNode('div', null, 'foo', PatchFlags.TEXT)]
|
||||
},
|
||||
// mock instance
|
||||
{} as any
|
||||
{ type: {} } as any
|
||||
)
|
||||
|
||||
// manual invocation should not track
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
import { withScopeId } from '../../src/helpers/scopeId'
|
||||
import { h, render, nodeOps, serializeInner } from '@vue/runtime-test'
|
||||
|
||||
describe('scopeId runtime support', () => {
|
||||
const withParentId = withScopeId('parent')
|
||||
const withChildId = withScopeId('child')
|
||||
|
||||
test('should attach scopeId', () => {
|
||||
const App = {
|
||||
__scopeId: 'parent',
|
||||
render: withParentId(() => {
|
||||
return h('div', [h('div')])
|
||||
})
|
||||
}
|
||||
const root = nodeOps.createElement('div')
|
||||
render(h(App), root)
|
||||
expect(serializeInner(root)).toBe(`<div parent><div parent></div></div>`)
|
||||
})
|
||||
|
||||
test('should attach scopeId to components in parent component', () => {
|
||||
const Child = {
|
||||
__scopeId: 'child',
|
||||
render: withChildId(() => {
|
||||
return h('div')
|
||||
})
|
||||
}
|
||||
const App = {
|
||||
__scopeId: 'parent',
|
||||
render: withParentId(() => {
|
||||
return h('div', [h(Child)])
|
||||
})
|
||||
}
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
render(h(App), root)
|
||||
expect(serializeInner(root)).toBe(
|
||||
`<div parent><div child parent></div></div>`
|
||||
)
|
||||
})
|
||||
|
||||
test('should work on slots', () => {
|
||||
const Child = {
|
||||
__scopeId: 'child',
|
||||
render: withChildId(function(this: any) {
|
||||
return h('div', this.$slots.default())
|
||||
})
|
||||
}
|
||||
const withChild2Id = withScopeId('child2')
|
||||
const Child2 = {
|
||||
__scopeId: 'child2',
|
||||
render: withChild2Id(() => h('span'))
|
||||
}
|
||||
const App = {
|
||||
__scopeId: 'parent',
|
||||
render: withParentId(() => {
|
||||
return h(
|
||||
Child,
|
||||
withParentId(() => {
|
||||
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(
|
||||
`<div child parent>` +
|
||||
`<div parent child-s></div>` +
|
||||
// component inside slot should have:
|
||||
// - scopeId from template context
|
||||
// - slotted scopeId from slot owner
|
||||
// - its own scopeId
|
||||
`<span child2 parent child-s></span>` +
|
||||
`</div>`
|
||||
)
|
||||
})
|
||||
|
||||
// #1988
|
||||
test('should inherit scopeId through nested HOCs with inheritAttrs: false', () => {
|
||||
const withParentId = withScopeId('parent')
|
||||
const App = {
|
||||
__scopeId: 'parent',
|
||||
render: withParentId(() => {
|
||||
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(`<div parent></div>`)
|
||||
})
|
||||
})
|
||||
178
packages/runtime-core/__tests__/scopeId.spec.ts
Normal file
178
packages/runtime-core/__tests__/scopeId.spec.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
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(`<div parent><div parent></div></div>`)
|
||||
})
|
||||
|
||||
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(
|
||||
`<div parent><div child parent></div></div>`
|
||||
)
|
||||
})
|
||||
|
||||
// :slotted basic
|
||||
test('should work on slots', () => {
|
||||
const Child = {
|
||||
__scopeId: 'child',
|
||||
render(this: any) {
|
||||
return h('div', renderSlot(this.$slots, 'default'))
|
||||
}
|
||||
}
|
||||
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(
|
||||
`<div child parent>` +
|
||||
`<div parent child-s></div>` +
|
||||
// component inside slot should have:
|
||||
// - scopeId from template context
|
||||
// - slotted scopeId from slot owner
|
||||
// - its own scopeId
|
||||
`<span child2 parent child-s></span>` +
|
||||
`</div>`
|
||||
)
|
||||
})
|
||||
|
||||
// #2892
|
||||
test(':slotted on forwarded slots', async () => {
|
||||
const Wrapper = {
|
||||
__scopeId: 'wrapper',
|
||||
render(this: any) {
|
||||
// <div class="wrapper"><slot/></div>
|
||||
return h('div', { class: 'wrapper' }, [
|
||||
renderSlot(this.$slots, 'default')
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
const Slotted = {
|
||||
__scopeId: 'slotted',
|
||||
render(this: any) {
|
||||
// <Wrapper><slot/></Wrapper>
|
||||
return h(Wrapper, null, {
|
||||
default: withCtx(() => [renderSlot(this.$slots, 'default')])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// simulate hoisted node
|
||||
setScopeId('root')
|
||||
const hoisted = h('div', 'hoisted')
|
||||
setScopeId(null)
|
||||
|
||||
const Root = {
|
||||
__scopeId: 'root',
|
||||
render(this: any) {
|
||||
// <Slotted><div>hoisted</div><div>{{ dynamic }}</div></Slotted>
|
||||
return h(Slotted, null, {
|
||||
default: withCtx(() => {
|
||||
return [hoisted, h('div', 'dynamic')]
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
render(h(Root), root)
|
||||
expect(serializeInner(root)).toBe(
|
||||
`<div class="wrapper" wrapper slotted root>` +
|
||||
`<div root wrapper-s slotted-s>hoisted</div>` +
|
||||
`<div root wrapper-s slotted-s>dynamic</div>` +
|
||||
`</div>`
|
||||
)
|
||||
|
||||
const Root2 = {
|
||||
__scopeId: 'root',
|
||||
render(this: any) {
|
||||
// <Slotted>
|
||||
// <Wrapper>
|
||||
// <div>hoisted</div><div>{{ dynamic }}</div>
|
||||
// </Wrapper>
|
||||
// </Slotted>
|
||||
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(
|
||||
`<div class="wrapper" wrapper slotted root>` +
|
||||
`<div class="wrapper" wrapper root wrapper-s slotted-s>` +
|
||||
`<div root wrapper-s>hoisted</div>` +
|
||||
`<div root wrapper-s>dynamic</div>` +
|
||||
`</div>` +
|
||||
`</div>`
|
||||
)
|
||||
})
|
||||
|
||||
// #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(`<div parent></div>`)
|
||||
})
|
||||
})
|
||||
@@ -14,7 +14,7 @@ import { Data } from '../src/component'
|
||||
import { ShapeFlags, PatchFlags } from '@vue/shared'
|
||||
import { h, reactive, isReactive, setBlockTracking } from '../src'
|
||||
import { createApp, nodeOps, serializeInner } from '@vue/runtime-test'
|
||||
import { setCurrentRenderingInstance } from '../src/componentRenderUtils'
|
||||
import { setCurrentRenderingInstance } from '../src/componentRenderContext'
|
||||
|
||||
describe('vnode', () => {
|
||||
test('create with just tag', () => {
|
||||
@@ -231,8 +231,8 @@ describe('vnode', () => {
|
||||
|
||||
// ref normalizes to [currentRenderingInstance, ref]
|
||||
test('cloneVNode ref normalization', () => {
|
||||
const mockInstance1 = {} as any
|
||||
const mockInstance2 = {} as any
|
||||
const mockInstance1 = { type: {} } as any
|
||||
const mockInstance2 = { type: {} } as any
|
||||
|
||||
setCurrentRenderingInstance(mockInstance1)
|
||||
const original = createVNode('div', { ref: 'foo' })
|
||||
@@ -272,8 +272,8 @@ describe('vnode', () => {
|
||||
})
|
||||
|
||||
test('cloneVNode ref merging', () => {
|
||||
const mockInstance1 = {} as any
|
||||
const mockInstance2 = {} as any
|
||||
const mockInstance1 = { type: {} } as any
|
||||
const mockInstance2 = { type: {} } as any
|
||||
|
||||
setCurrentRenderingInstance(mockInstance1)
|
||||
const original = createVNode('div', { ref: 'foo' })
|
||||
|
||||
Reference in New Issue
Block a user