|
|
@@ -15,7 +15,7 @@ import { mockWarn } from '@vue/shared'
|
|
|
describe('attribute fallthrough', () => {
|
|
|
mockWarn()
|
|
|
|
|
|
- it('should allow whitelisted attrs to fallthrough', async () => {
|
|
|
+ it('should allow attrs to fallthrough', async () => {
|
|
|
const click = jest.fn()
|
|
|
const childUpdated = jest.fn()
|
|
|
|
|
|
@@ -30,12 +30,12 @@ describe('attribute fallthrough', () => {
|
|
|
|
|
|
return () =>
|
|
|
h(Child, {
|
|
|
- foo: 1,
|
|
|
+ foo: count.value + 1,
|
|
|
id: 'test',
|
|
|
class: 'c' + count.value,
|
|
|
style: { color: count.value ? 'red' : 'green' },
|
|
|
onClick: inc,
|
|
|
- 'data-id': 1
|
|
|
+ 'data-id': count.value + 1
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
@@ -47,7 +47,6 @@ describe('attribute fallthrough', () => {
|
|
|
h(
|
|
|
'div',
|
|
|
{
|
|
|
- id: props.id, // id is not whitelisted
|
|
|
class: 'c2',
|
|
|
style: { fontWeight: 'bold' }
|
|
|
},
|
|
|
@@ -62,8 +61,8 @@ describe('attribute fallthrough', () => {
|
|
|
|
|
|
const node = root.children[0] as HTMLElement
|
|
|
|
|
|
- expect(node.getAttribute('id')).toBe('test') // id is not whitelisted, but explicitly bound
|
|
|
- expect(node.getAttribute('foo')).toBe(null) // foo is not whitelisted
|
|
|
+ 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')
|
|
|
@@ -71,6 +70,121 @@ describe('attribute fallthrough', () => {
|
|
|
node.dispatchEvent(new CustomEvent('click'))
|
|
|
expect(click).toHaveBeenCalled()
|
|
|
|
|
|
+ await nextTick()
|
|
|
+ expect(childUpdated).toHaveBeenCalled()
|
|
|
+ expect(node.getAttribute('id')).toBe('test')
|
|
|
+ expect(node.getAttribute('foo')).toBe('2')
|
|
|
+ expect(node.getAttribute('class')).toBe('c2 c1')
|
|
|
+ expect(node.style.color).toBe('red')
|
|
|
+ expect(node.style.fontWeight).toBe('bold')
|
|
|
+ expect(node.dataset.id).toBe('2')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should only allow whitelisted fallthrough on functional component with optional props', async () => {
|
|
|
+ const click = jest.fn()
|
|
|
+ const childUpdated = jest.fn()
|
|
|
+
|
|
|
+ const count = ref(0)
|
|
|
+
|
|
|
+ function inc() {
|
|
|
+ count.value++
|
|
|
+ click()
|
|
|
+ }
|
|
|
+
|
|
|
+ const Hello = () =>
|
|
|
+ h(Child, {
|
|
|
+ foo: count.value + 1,
|
|
|
+ id: 'test',
|
|
|
+ class: 'c' + count.value,
|
|
|
+ style: { color: count.value ? 'red' : 'green' },
|
|
|
+ onClick: inc
|
|
|
+ })
|
|
|
+
|
|
|
+ const Child = (props: any) => {
|
|
|
+ childUpdated()
|
|
|
+ return h(
|
|
|
+ 'div',
|
|
|
+ {
|
|
|
+ class: 'c2',
|
|
|
+ style: { fontWeight: 'bold' }
|
|
|
+ },
|
|
|
+ props.foo
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ const root = document.createElement('div')
|
|
|
+ document.body.appendChild(root)
|
|
|
+ render(h(Hello), root)
|
|
|
+
|
|
|
+ const node = root.children[0] as HTMLElement
|
|
|
+
|
|
|
+ // not whitelisted
|
|
|
+ expect(node.getAttribute('id')).toBe(null)
|
|
|
+ expect(node.getAttribute('foo')).toBe(null)
|
|
|
+
|
|
|
+ // whitelisted: style, class, event listeners
|
|
|
+ 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(null)
|
|
|
+ expect(node.getAttribute('foo')).toBe(null)
|
|
|
+ expect(node.getAttribute('class')).toBe('c2 c1')
|
|
|
+ expect(node.style.color).toBe('red')
|
|
|
+ expect(node.style.fontWeight).toBe('bold')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should allow all attrs on functional component with declared props', async () => {
|
|
|
+ const click = jest.fn()
|
|
|
+ const childUpdated = jest.fn()
|
|
|
+
|
|
|
+ const count = ref(0)
|
|
|
+
|
|
|
+ function inc() {
|
|
|
+ count.value++
|
|
|
+ click()
|
|
|
+ }
|
|
|
+
|
|
|
+ const Hello = () =>
|
|
|
+ h(Child, {
|
|
|
+ foo: count.value + 1,
|
|
|
+ id: 'test',
|
|
|
+ class: 'c' + count.value,
|
|
|
+ style: { color: count.value ? 'red' : 'green' },
|
|
|
+ onClick: inc
|
|
|
+ })
|
|
|
+
|
|
|
+ const Child = (props: { foo: number }) => {
|
|
|
+ childUpdated()
|
|
|
+ return h(
|
|
|
+ 'div',
|
|
|
+ {
|
|
|
+ class: 'c2',
|
|
|
+ style: { fontWeight: 'bold' }
|
|
|
+ },
|
|
|
+ props.foo
|
|
|
+ )
|
|
|
+ }
|
|
|
+ Child.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(null) // declared as prop
|
|
|
+ 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')
|