Skip to content

Commit fa01278

Browse files
committed
test: add more tests
1 parent 4438967 commit fa01278

File tree

1 file changed

+142
-156
lines changed

1 file changed

+142
-156
lines changed

packages/runtime-vapor/__tests__/componentAttrs.spec.ts

Lines changed: 142 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
renderEffect,
1717
setClass,
1818
setDynamicProps,
19+
setInsertionState,
1920
setProp,
2021
setStyle,
2122
template,
@@ -98,12 +99,12 @@ describe('attribute fallthrough', () => {
9899
return n0
99100
})
100101

101-
const { host: root } = define(Hello).render()
102-
expect(root.innerHTML).toBe(
102+
const { host } = define(Hello).render()
103+
expect(host.innerHTML).toBe(
103104
'<div class="c2 c0" style="font-weight: bold; color: green;">1</div>',
104105
)
105106

106-
const node = root.children[0] as HTMLElement
107+
const node = host.children[0] as HTMLElement
107108

108109
// not whitelisted
109110
expect(node.getAttribute('id')).toBe(null)
@@ -128,7 +129,6 @@ describe('attribute fallthrough', () => {
128129
it('should allow all attrs on functional component with declared props', async () => {
129130
const click = vi.fn()
130131
const childUpdated = vi.fn()
131-
132132
const count = ref(0)
133133

134134
function inc() {
@@ -157,8 +157,8 @@ describe('attribute fallthrough', () => {
157157

158158
Child.props = ['foo']
159159

160-
const { host: root } = define(Hello).render()
161-
const node = root.children[0] as HTMLElement
160+
const { host } = define(Hello).render()
161+
const node = host.children[0] as HTMLElement
162162

163163
expect(node.getAttribute('id')).toBe('test')
164164
expect(node.getAttribute('foo')).toBe(null) // declared as prop
@@ -232,12 +232,12 @@ describe('attribute fallthrough', () => {
232232
},
233233
})
234234

235-
const { host: root } = define(Hello).render()
236-
expect(root.innerHTML).toBe(
235+
const { host } = define(Hello).render()
236+
expect(host.innerHTML).toBe(
237237
'<div class="c2 c0" style="font-weight: bold; color: green;" id="test">1</div>',
238238
)
239239

240-
const node = root.children[0] as HTMLElement
240+
const node = host.children[0] as HTMLElement
241241

242242
// with declared props, any parent attr that isn't a prop falls through
243243
expect(node.getAttribute('id')).toBe('test')
@@ -343,20 +343,20 @@ describe('attribute fallthrough', () => {
343343
},
344344
}
345345

346-
const root = document.createElement('div')
346+
const target = document.createElement('div')
347347
const Child = defineVaporComponent({
348348
render() {
349349
return createComponent(
350350
VaporTeleport,
351-
{ to: () => root },
351+
{ to: () => target },
352352
{
353353
default: () => template('<div></div>')(),
354354
},
355355
)
356356
},
357357
})
358358

359-
document.body.appendChild(root)
359+
document.body.appendChild(target)
360360
define(Parent).render()
361361

362362
expect(`Extraneous non-props attributes (class)`).toHaveBeenWarned()
@@ -473,8 +473,6 @@ describe('attribute fallthrough', () => {
473473
return [n0, n1]
474474
})
475475

476-
const root = document.createElement('div')
477-
document.body.appendChild(root)
478476
const { html } = define(Parent).render()
479477

480478
expect(`Extraneous non-props attributes`).not.toHaveBeenWarned()
@@ -534,8 +532,8 @@ describe('attribute fallthrough', () => {
534532
},
535533
})
536534

537-
const { host: root } = define(App).render()
538-
const node = root.children[0] as HTMLElement
535+
const { host } = define(App).render()
536+
const node = host.children[0] as HTMLElement
539537
node.click()
540538
expect(onClick).toHaveBeenCalledTimes(1)
541539
expect(onClick).toHaveBeenCalledWith('custom')
@@ -562,8 +560,8 @@ describe('attribute fallthrough', () => {
562560
},
563561
})
564562

565-
const { host: root } = define(App).render()
566-
const node = root.children[0] as HTMLElement
563+
const { host } = define(App).render()
564+
const node = host.children[0] as HTMLElement
567565
node.click()
568566
expect(onClick).toHaveBeenCalledTimes(1)
569567
expect(onClick).toHaveBeenCalledWith('custom')
@@ -591,151 +589,139 @@ describe('attribute fallthrough', () => {
591589
},
592590
})
593591

594-
const { host: root } = define(Hello).render()
592+
const { host } = define(Hello).render()
595593

596-
expect(root.innerHTML).toBe(
594+
expect(host.innerHTML).toBe(
597595
`<!--hello--><button class="foo"></button><!--world-->`,
598596
)
599-
const button = root.children[0] as HTMLElement
597+
const button = host.children[0] as HTMLElement
600598
button.dispatchEvent(new CustomEvent('click'))
601599
expect(click).toHaveBeenCalled()
602600
})
603601

604-
// it('should support fallthrough for nested dev root fragments', async () => {
605-
// const toggle = ref(false)
606-
607-
// const Child = {
608-
// setup() {
609-
// return () => (
610-
// openBlock(),
611-
// createElementBlock(
612-
// Fragment,
613-
// null,
614-
// [
615-
// createCommentVNode(' comment A '),
616-
// toggle.value
617-
// ? (openBlock(), createElementBlock('span', { key: 0 }, 'Foo'))
618-
// : (openBlock(),
619-
// createElementBlock(
620-
// Fragment,
621-
// { key: 1 },
622-
// [
623-
// createCommentVNode(' comment B '),
624-
// createElementVNode('div', null, 'Bar'),
625-
// ],
626-
// PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,
627-
// )),
628-
// ],
629-
// PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,
630-
// )
631-
// )
632-
// },
633-
// }
634-
635-
// const Root = {
636-
// setup() {
637-
// return () => (openBlock(), createBlock(Child, { class: 'red' }))
638-
// },
639-
// }
640-
641-
// const root = document.createElement('div')
642-
// document.body.appendChild(root)
643-
// render(h(Root), root)
644-
645-
// expect(root.innerHTML).toBe(
646-
// `<!-- comment A --><!-- comment B --><div class="red">Bar</div>`,
647-
// )
648-
649-
// toggle.value = true
650-
// await nextTick()
651-
// expect(root.innerHTML).toBe(
652-
// `<!-- comment A --><span class=\"red\">Foo</span>`,
653-
// )
654-
// })
655-
656-
// // #1989
657-
// it('should not fallthrough v-model listeners with corresponding declared prop', () => {
658-
// let textFoo = ''
659-
// let textBar = ''
660-
// const click = vi.fn()
661-
662-
// const App = defineVaporComponent({
663-
// setup() {
664-
// return () =>
665-
// h(Child, {
666-
// modelValue: textFoo,
667-
// 'onUpdate:modelValue': (val: string) => {
668-
// textFoo = val
669-
// },
670-
// })
671-
// },
672-
// })
673-
674-
// const Child = defineVaporComponent({
675-
// props: ['modelValue'],
676-
// setup(_props, { emit }) {
677-
// return () =>
678-
// h(GrandChild, {
679-
// modelValue: textBar,
680-
// 'onUpdate:modelValue': (val: string) => {
681-
// textBar = val
682-
// emit('update:modelValue', 'from Child')
683-
// },
684-
// })
685-
// },
686-
// })
687-
688-
// const GrandChild = defineVaporComponent({
689-
// props: ['modelValue'],
690-
// setup(_props, { emit }) {
691-
// return () =>
692-
// h('button', {
693-
// onClick() {
694-
// click()
695-
// emit('update:modelValue', 'from GrandChild')
696-
// },
697-
// })
698-
// },
699-
// })
700-
701-
// const root = document.createElement('div')
702-
// document.body.appendChild(root)
703-
// render(h(App), root)
704-
705-
// const node = root.children[0] as HTMLElement
706-
707-
// node.dispatchEvent(new CustomEvent('click'))
708-
// expect(click).toHaveBeenCalled()
709-
// expect(textBar).toBe('from GrandChild')
710-
// expect(textFoo).toBe('from Child')
711-
// })
712-
713-
// // covers uncaught regression #10710
714-
// it('should track this.$attrs access in slots', async () => {
715-
// const GrandChild = {
716-
// template: `<slot/>`,
717-
// }
718-
// const Child = {
719-
// components: { GrandChild },
720-
// template: `<div><GrandChild>{{ $attrs.foo }}</GrandChild></div>`,
721-
// }
722-
723-
// const obj = ref(1)
724-
// const App = {
725-
// render() {
726-
// return h(Child, { foo: obj.value })
727-
// },
728-
// }
729-
730-
// const root = document.createElement('div')
731-
// createApp(App).mount(root)
732-
733-
// expect(root.innerHTML).toBe('<div foo="1">1</div>')
734-
735-
// obj.value = 2
736-
// await nextTick()
737-
// expect(root.innerHTML).toBe('<div foo="2">2</div>')
738-
// })
602+
it('should support fallthrough for nested element + comments', async () => {
603+
const toggle = ref(false)
604+
const Child = defineVaporComponent({
605+
setup() {
606+
const n0 = template('<!-- comment A -->')() as any
607+
const n1 = createIf(
608+
() => toggle.value,
609+
() => template('<span>Foo</span>')(),
610+
() => {
611+
const n2 = template('<!-- comment B -->')() as any
612+
const n3 = template('<div>Bar</div>')() as any
613+
return [n2, n3]
614+
},
615+
)
616+
return [n0, n1]
617+
},
618+
})
619+
620+
const Root = defineVaporComponent({
621+
setup() {
622+
return createComponent(Child, { class: () => 'red' })
623+
},
624+
})
625+
626+
const { host } = define(Root).render()
627+
628+
expect(host.innerHTML).toBe(
629+
`<!-- comment A --><!-- comment B --><div class="red">Bar</div><!--if-->`,
630+
)
631+
632+
toggle.value = true
633+
await nextTick()
634+
expect(host.innerHTML).toBe(
635+
`<!-- comment A --><span class=\"red\">Foo</span><!--if-->`,
636+
)
637+
})
638+
639+
it('should not fallthrough v-model listeners with corresponding declared prop', () => {
640+
let textFoo = ''
641+
let textBar = ''
642+
const click = vi.fn()
643+
644+
const App = defineVaporComponent({
645+
render() {
646+
return createComponent(Child, {
647+
modelValue: () => textFoo,
648+
'onUpdate:modelValue': () => (val: string) => {
649+
textFoo = val
650+
},
651+
})
652+
},
653+
})
654+
655+
const Child = defineVaporComponent({
656+
props: ['modelValue'],
657+
setup(_props, { emit }) {
658+
return createComponent(GrandChild, {
659+
modelValue: () => textBar,
660+
'onUpdate:modelValue': () => (val: string) => {
661+
textBar = val
662+
emit('update:modelValue', 'from Child')
663+
},
664+
})
665+
},
666+
})
667+
668+
const GrandChild = defineVaporComponent({
669+
props: ['modelValue'],
670+
setup(_props, { emit }) {
671+
const n0 = template('<button></button>')() as any
672+
n0.$evtclick = () => {
673+
click()
674+
emit('update:modelValue', 'from GrandChild')
675+
}
676+
return n0
677+
},
678+
})
679+
680+
const { host } = define(App).render()
681+
const node = host.children[0] as HTMLElement
682+
node.click()
683+
expect(click).toHaveBeenCalled()
684+
expect(textBar).toBe('from GrandChild')
685+
expect(textFoo).toBe('from Child')
686+
})
687+
688+
it('should track this.$attrs access in slots', async () => {
689+
const GrandChild = defineVaporComponent({
690+
render() {
691+
return createSlot('default')
692+
},
693+
})
694+
const Child = defineVaporComponent({
695+
// @ts-expect-error
696+
components: { GrandChild },
697+
render(_ctx, $props, $emit, $attrs, $slots) {
698+
const n0 = template('<div></div>')() as any
699+
setInsertionState(n0)
700+
createComponent(GrandChild, null, {
701+
default: () => {
702+
const n1 = template(' ')()
703+
renderEffect(() => setElementText(n1, $attrs.foo))
704+
return n1
705+
},
706+
})
707+
return n0
708+
},
709+
})
710+
711+
const obj = ref(1)
712+
const App = defineVaporComponent({
713+
render() {
714+
return createComponent(Child, { foo: () => obj.value })
715+
},
716+
})
717+
718+
const { html } = define(App).render()
719+
expect(html()).toBe('<div foo="1">1<!--slot--></div>')
720+
721+
obj.value = 2
722+
await nextTick()
723+
expect(html()).toBe('<div foo="2">2<!--slot--></div>')
724+
})
739725

740726
it('should allow attrs to fallthrough on component with comment at root', async () => {
741727
const t0 = template('<!--comment-->')

0 commit comments

Comments
 (0)