| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- // using DOM renderer because this case is mostly DOM-specific
- import {
- createVNode as h,
- render,
- nextTick,
- mergeProps,
- ref,
- onUpdated
- } from '@vue/runtime-dom'
- describe('attribute fallthrough', () => {
- it('everything should be in props when component has no declared props', async () => {
- const click = jest.fn()
- const childUpdated = jest.fn()
- const Hello = {
- setup() {
- const count = ref(0)
- function inc() {
- count.value++
- click()
- }
- return () =>
- h(Child, {
- foo: 1,
- id: 'test',
- class: 'c' + count.value,
- style: { color: count.value ? 'red' : 'green' },
- onClick: inc
- })
- }
- }
- const Child = {
- setup(props: any) {
- onUpdated(childUpdated)
- return () =>
- h(
- 'div',
- mergeProps(
- {
- class: 'c2',
- style: { fontWeight: 'bold' }
- },
- props
- ),
- props.foo
- )
- }
- }
- const root = document.createElement('div')
- document.body.appendChild(root)
- render(h(Hello), root)
- const node = root.children[0] as HTMLElement
- expect(node.getAttribute('id')).toBe('test')
- expect(node.getAttribute('foo')).toBe('1')
- expect(node.getAttribute('class')).toBe('c2 c0')
- expect(node.style.color).toBe('green')
- expect(node.style.fontWeight).toBe('bold')
- node.dispatchEvent(new CustomEvent('click'))
- expect(click).toHaveBeenCalled()
- await nextTick()
- expect(childUpdated).toHaveBeenCalled()
- expect(node.getAttribute('id')).toBe('test')
- expect(node.getAttribute('foo')).toBe('1')
- expect(node.getAttribute('class')).toBe('c2 c1')
- expect(node.style.color).toBe('red')
- expect(node.style.fontWeight).toBe('bold')
- })
- // it('should separate in attrs when component has declared props', async () => {
- // const click = jest.fn()
- // const childUpdated = jest.fn()
- // class Hello extends Component {
- // count = 0
- // inc() {
- // this.count++
- // click()
- // }
- // render() {
- // return h(Child, {
- // foo: 123,
- // id: 'test',
- // class: 'c' + this.count,
- // style: { color: this.count ? 'red' : 'green' },
- // onClick: this.inc
- // })
- // }
- // }
- // class Child extends Component<{ [key: string]: any; foo: number }> {
- // static props = {
- // foo: Number
- // }
- // updated() {
- // childUpdated()
- // }
- // render() {
- // return cloneVNode(
- // h(
- // 'div',
- // {
- // class: 'c2',
- // style: { fontWeight: 'bold' }
- // },
- // this.$props.foo
- // ),
- // this.$attrs
- // )
- // }
- // }
- // const root = document.createElement('div')
- // document.body.appendChild(root)
- // await render(h(Hello), root)
- // const node = root.children[0] as HTMLElement
- // // with declared props, any parent attr that isn't a prop falls through
- // expect(node.getAttribute('id')).toBe('test')
- // expect(node.getAttribute('class')).toBe('c2 c0')
- // expect(node.style.color).toBe('green')
- // expect(node.style.fontWeight).toBe('bold')
- // node.dispatchEvent(new CustomEvent('click'))
- // expect(click).toHaveBeenCalled()
- // // ...while declared ones remain props
- // expect(node.hasAttribute('foo')).toBe(false)
- // await nextTick()
- // expect(childUpdated).toHaveBeenCalled()
- // expect(node.getAttribute('id')).toBe('test')
- // expect(node.getAttribute('class')).toBe('c2 c1')
- // expect(node.style.color).toBe('red')
- // expect(node.style.fontWeight).toBe('bold')
- // expect(node.hasAttribute('foo')).toBe(false)
- // })
- // it('should fallthrough on multi-nested components', async () => {
- // const click = jest.fn()
- // const childUpdated = jest.fn()
- // const grandChildUpdated = jest.fn()
- // class Hello extends Component {
- // count = 0
- // inc() {
- // this.count++
- // click()
- // }
- // render() {
- // return h(Child, {
- // foo: 1,
- // id: 'test',
- // class: 'c' + this.count,
- // style: { color: this.count ? 'red' : 'green' },
- // onClick: this.inc
- // })
- // }
- // }
- // class Child extends Component<{ [key: string]: any; foo: number }> {
- // updated() {
- // childUpdated()
- // }
- // render() {
- // return h(GrandChild, this.$props)
- // }
- // }
- // class GrandChild extends Component<{ [key: string]: any; foo: number }> {
- // static props = {
- // foo: Number
- // }
- // updated() {
- // grandChildUpdated()
- // }
- // render(props: any) {
- // return cloneVNode(
- // h(
- // 'div',
- // {
- // class: 'c2',
- // style: { fontWeight: 'bold' }
- // },
- // props.foo
- // ),
- // this.$attrs
- // )
- // }
- // }
- // const root = document.createElement('div')
- // document.body.appendChild(root)
- // await render(h(Hello), root)
- // const node = root.children[0] as HTMLElement
- // // with declared props, any parent attr that isn't a prop falls through
- // expect(node.getAttribute('id')).toBe('test')
- // expect(node.getAttribute('class')).toBe('c2 c0')
- // expect(node.style.color).toBe('green')
- // expect(node.style.fontWeight).toBe('bold')
- // node.dispatchEvent(new CustomEvent('click'))
- // expect(click).toHaveBeenCalled()
- // // ...while declared ones remain props
- // expect(node.hasAttribute('foo')).toBe(false)
- // await nextTick()
- // expect(childUpdated).toHaveBeenCalled()
- // expect(grandChildUpdated).toHaveBeenCalled()
- // expect(node.getAttribute('id')).toBe('test')
- // expect(node.getAttribute('class')).toBe('c2 c1')
- // expect(node.style.color).toBe('red')
- // expect(node.style.fontWeight).toBe('bold')
- // expect(node.hasAttribute('foo')).toBe(false)
- // })
- })
|