| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615 |
- import { createApp, h } from '@vue/runtime-dom'
- import {
- createComponent,
- createDynamicComponent,
- createSlot,
- defineVaporComponent,
- setInsertionState,
- template,
- vaporInteropPlugin,
- withVaporCtx,
- } from '../src'
- import { makeRender } from './_utils'
- const define = makeRender()
- describe('scopeId', () => {
- test('should attach scopeId to child component', () => {
- const Child = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- return template('<div child></div>', true)()
- },
- })
- const { html } = define({
- __scopeId: 'parent',
- setup() {
- return createComponent(Child)
- },
- }).render()
- expect(html()).toBe(`<div child="" parent=""></div>`)
- })
- test('should attach scopeId to child component with insertion state', () => {
- const Child = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- return template('<div child></div>', true)()
- },
- })
- const { html } = define({
- __scopeId: 'parent',
- setup() {
- const t0 = template('<div parent></div>', true)
- const n1 = t0() as any
- setInsertionState(n1)
- createComponent(Child)
- return n1
- },
- }).render()
- expect(html()).toBe(`<div parent=""><div child="" parent=""></div></div>`)
- })
- test('should attach scopeId to nested child component', () => {
- const Child = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- return template('<div child></div>', true)()
- },
- })
- const Parent = defineVaporComponent({
- __scopeId: 'parent',
- setup() {
- return createComponent(Child)
- },
- })
- const { html } = define({
- __scopeId: 'app',
- setup() {
- return createComponent(Parent)
- },
- }).render()
- expect(html()).toBe(`<div child="" parent="" app=""></div>`)
- })
- test('should not attach scopeId to nested multiple root components', () => {
- const Child = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- return template('<div child></div>', true)()
- },
- })
- const Parent = defineVaporComponent({
- __scopeId: 'parent',
- setup() {
- const n0 = template('<div parent></div>')()
- const n1 = createComponent(Child)
- return [n0, n1]
- },
- })
- const { html } = define({
- __scopeId: 'app',
- setup() {
- return createComponent(Parent)
- },
- }).render()
- expect(html()).toBe(`<div parent=""></div><div child="" parent=""></div>`)
- })
- test('should attach scopeId to nested child component with insertion state', () => {
- const Child = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- return template('<div child></div>', true)()
- },
- })
- const Parent = defineVaporComponent({
- __scopeId: 'parent',
- setup() {
- return createComponent(Child)
- },
- })
- const { html } = define({
- __scopeId: 'app',
- setup() {
- const t0 = template('<div app></div>', true)
- const n1 = t0() as any
- setInsertionState(n1)
- createComponent(Parent)
- return n1
- },
- }).render()
- expect(html()).toBe(
- `<div app=""><div child="" parent="" app=""></div></div>`,
- )
- })
- test('should attach scopeId to dynamic component', () => {
- const { html } = define({
- __scopeId: 'parent',
- setup() {
- return createDynamicComponent(() => 'button')
- },
- }).render()
- expect(html()).toBe(`<button parent=""></button><!--dynamic-component-->`)
- })
- test('should attach scopeId to dynamic component with insertion state', () => {
- const { html } = define({
- __scopeId: 'parent',
- setup() {
- const t0 = template('<div parent></div>', true)
- const n1 = t0() as any
- setInsertionState(n1)
- createDynamicComponent(() => 'button')
- return n1
- },
- }).render()
- expect(html()).toBe(
- `<div parent=""><button parent=""></button><!--dynamic-component--></div>`,
- )
- })
- test('should attach scopeId to nested dynamic component', () => {
- const Comp = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- return createDynamicComponent(() => 'button', null, null, true)
- },
- })
- const { html } = define({
- __scopeId: 'parent',
- setup() {
- return createComponent(Comp, null, null, true)
- },
- }).render()
- expect(html()).toBe(
- `<button child="" parent=""></button><!--dynamic-component-->`,
- )
- })
- test('should attach scopeId to nested dynamic component with insertion state', () => {
- const Comp = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- return createDynamicComponent(() => 'button', null, null, true)
- },
- })
- const { html } = define({
- __scopeId: 'parent',
- setup() {
- const t0 = template('<div parent></div>', true)
- const n1 = t0() as any
- setInsertionState(n1)
- createComponent(Comp, null, null, true)
- return n1
- },
- }).render()
- expect(html()).toBe(
- `<div parent=""><button child="" parent=""></button><!--dynamic-component--></div>`,
- )
- })
- test.todo('should attach scopeId to suspense content', async () => {})
- // :slotted basic
- test('should work on slots', () => {
- const Child = defineVaporComponent({
- __scopeId: 'child',
- setup() {
- const n1 = template('<div child></div>', true)() as any
- setInsertionState(n1)
- createSlot('default', null)
- return n1
- },
- })
- const Child2 = defineVaporComponent({
- __scopeId: 'child2',
- setup() {
- return template('<span child2></span>', true)()
- },
- })
- const { html } = define({
- __scopeId: 'parent',
- setup() {
- const n2 = createComponent(
- Child,
- null,
- {
- default: withVaporCtx(() => {
- const n0 = template('<div parent></div>')()
- const n1 = createComponent(Child2)
- return [n0, n1]
- }),
- },
- true,
- )
- return n2
- },
- }).render()
- // slot content should have:
- // - scopeId from parent
- // - slotted scopeId (with `-s` postfix) from child (the tree owner)
- expect(html()).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="" child-s="" parent=""></span>` +
- `<!--slot-->` +
- `</div>`,
- )
- })
- test(':slotted on forwarded slots', async () => {
- const Wrapper = defineVaporComponent({
- __scopeId: 'wrapper',
- setup() {
- // <div><slot/></div>
- const n1 = template('<div wrapper></div>', true)() as any
- setInsertionState(n1)
- createSlot('default', null, undefined, true /* noSlotted */)
- return n1
- },
- })
- const Slotted = defineVaporComponent({
- __scopeId: 'slotted',
- setup() {
- // <Wrapper><slot/></Wrapper>
- const n1 = createComponent(
- Wrapper,
- null,
- {
- default: withVaporCtx(() => {
- const n0 = createSlot('default', null)
- return n0
- }),
- },
- true,
- )
- return n1
- },
- })
- const { html } = define({
- __scopeId: 'root',
- setup() {
- // <Slotted><div></div></Slotted>
- const n2 = createComponent(
- Slotted,
- null,
- {
- default: () => {
- return template('<div root></div>')()
- },
- },
- true,
- )
- return n2
- },
- }).render()
- expect(html()).toBe(
- `<div wrapper="" slotted="" root="">` +
- `<div root="" slotted-s=""></div>` +
- `<!--slot--><!--slot-->` +
- `</div>`,
- )
- })
- })
- describe('vdom interop', () => {
- test('vdom parent > vapor child', () => {
- const VaporChild = defineVaporComponent({
- __scopeId: 'vapor-child',
- setup() {
- return template('<button vapor-child></button>', true)()
- },
- })
- const VdomParent = {
- __scopeId: 'vdom-parent',
- setup() {
- return () => h(VaporChild as any)
- },
- }
- const App = {
- setup() {
- return () => h(VdomParent)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<button vapor-child="" vdom-parent=""></button>`,
- )
- })
- test('vdom parent > vapor child > vdom child', () => {
- const VdomChild = {
- __scopeId: 'vdom-child',
- setup() {
- return () => h('button')
- },
- }
- const VaporChild = defineVaporComponent({
- __scopeId: 'vapor-child',
- setup() {
- return createComponent(VdomChild as any, null, null, true)
- },
- })
- const VdomParent = {
- __scopeId: 'vdom-parent',
- setup() {
- return () => h(VaporChild as any)
- },
- }
- const App = {
- setup() {
- return () => h(VdomParent)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<button vdom-child="" vapor-child="" vdom-parent=""></button>`,
- )
- })
- test('vdom parent > vapor child > vapor child > vdom child', () => {
- const VdomChild = {
- __scopeId: 'vdom-child',
- setup() {
- return () => h('button')
- },
- }
- const NestedVaporChild = defineVaporComponent({
- __scopeId: 'nested-vapor-child',
- setup() {
- return createComponent(VdomChild as any, null, null, true)
- },
- })
- const VaporChild = defineVaporComponent({
- __scopeId: 'vapor-child',
- setup() {
- return createComponent(NestedVaporChild as any, null, null, true)
- },
- })
- const VdomParent = {
- __scopeId: 'vdom-parent',
- setup() {
- return () => h(VaporChild as any)
- },
- }
- const App = {
- setup() {
- return () => h(VdomParent)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<button vdom-child="" nested-vapor-child="" vapor-child="" vdom-parent=""></button>`,
- )
- })
- test('vdom parent > vapor dynamic child', () => {
- const VaporChild = defineVaporComponent({
- __scopeId: 'vapor-child',
- setup() {
- return createDynamicComponent(() => 'button', null, null, true)
- },
- })
- const VdomParent = {
- __scopeId: 'vdom-parent',
- setup() {
- return () => h(VaporChild as any)
- },
- }
- const App = {
- setup() {
- return () => h(VdomParent)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<button vapor-child="" vdom-parent=""></button><!--dynamic-component-->`,
- )
- })
- test('vapor parent > vdom child', () => {
- const VdomChild = {
- __scopeId: 'vdom-child',
- setup() {
- return () => h('button')
- },
- }
- const VaporParent = defineVaporComponent({
- __scopeId: 'vapor-parent',
- setup() {
- return createComponent(VdomChild as any, null, null, true)
- },
- })
- const App = {
- setup() {
- return () => h(VaporParent as any)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<button vdom-child="" vapor-parent=""></button>`,
- )
- })
- test('vapor parent > vdom child > vapor child', () => {
- const VaporChild = defineVaporComponent({
- __scopeId: 'vapor-child',
- setup() {
- return template('<button vapor-child></button>', true)()
- },
- })
- const VdomChild = {
- __scopeId: 'vdom-child',
- setup() {
- return () => h(VaporChild as any)
- },
- }
- const VaporParent = defineVaporComponent({
- __scopeId: 'vapor-parent',
- setup() {
- return createComponent(VdomChild as any, null, null, true)
- },
- })
- const App = {
- setup() {
- return () => h(VaporParent as any)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<button vapor-child="" vdom-child="" vapor-parent=""></button>`,
- )
- })
- test('vapor parent > vdom child > vdom child > vapor child', () => {
- const VaporChild = defineVaporComponent({
- __scopeId: 'vapor-child',
- setup() {
- return template('<button vapor-child></button>', true)()
- },
- })
- const VdomChild = {
- __scopeId: 'vdom-child',
- setup() {
- return () => h(VaporChild as any)
- },
- }
- const VdomParent = {
- __scopeId: 'vdom-parent',
- setup() {
- return () => h(VdomChild as any)
- },
- }
- const VaporParent = defineVaporComponent({
- __scopeId: 'vapor-parent',
- setup() {
- return createComponent(VdomParent as any, null, null, true)
- },
- })
- const App = {
- setup() {
- return () => h(VaporParent as any)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<button vapor-child="" vdom-child="" vdom-parent="" vapor-parent=""></button>`,
- )
- })
- test('vapor parent > vapor slot > vdom child', () => {
- const VaporSlot = defineVaporComponent({
- __scopeId: 'vapor-slot',
- setup() {
- const n1 = template('<div vapor-slot></div>', true)() as any
- setInsertionState(n1)
- createSlot('default', null)
- return n1
- },
- })
- const VdomChild = {
- __scopeId: 'vdom-child',
- setup() {
- return () => h('span')
- },
- }
- const VaporParent = defineVaporComponent({
- __scopeId: 'vapor-parent',
- setup() {
- const n2 = createComponent(
- VaporSlot,
- null,
- {
- default: withVaporCtx(() => {
- const n0 = template('<div vapor-parent></div>')()
- const n1 = createComponent(VdomChild)
- return [n0, n1]
- }),
- },
- true,
- )
- return n2
- },
- })
- const App = {
- setup() {
- return () => h(VaporParent as any)
- },
- }
- const root = document.createElement('div')
- createApp(App).use(vaporInteropPlugin).mount(root)
- expect(root.innerHTML).toBe(
- `<div vapor-slot="" vapor-parent="">` +
- `<div vapor-parent="" vapor-slot-s=""></div>` +
- `<span vdom-child="" vapor-parent="" vapor-slot-s=""></span>` +
- `<!--slot-->` +
- `</div>`,
- )
- })
- })
|