@@ -15,7 +15,7 @@ import { mockWarn } from '@vue/shared'
15
15
describe ( 'attribute fallthrough' , ( ) => {
16
16
mockWarn ( )
17
17
18
- it ( 'should allow whitelisted attrs to fallthrough' , async ( ) => {
18
+ it ( 'should allow attrs to fallthrough' , async ( ) => {
19
19
const click = jest . fn ( )
20
20
const childUpdated = jest . fn ( )
21
21
@@ -30,12 +30,12 @@ describe('attribute fallthrough', () => {
30
30
31
31
return ( ) =>
32
32
h ( Child , {
33
- foo : 1 ,
33
+ foo : count . value + 1 ,
34
34
id : 'test' ,
35
35
class : 'c' + count . value ,
36
36
style : { color : count . value ? 'red' : 'green' } ,
37
37
onClick : inc ,
38
- 'data-id' : 1
38
+ 'data-id' : count . value + 1
39
39
} )
40
40
}
41
41
}
@@ -47,7 +47,6 @@ describe('attribute fallthrough', () => {
47
47
h (
48
48
'div' ,
49
49
{
50
- id : props . id , // id is not whitelisted
51
50
class : 'c2' ,
52
51
style : { fontWeight : 'bold' }
53
52
} ,
@@ -62,15 +61,130 @@ describe('attribute fallthrough', () => {
62
61
63
62
const node = root . children [ 0 ] as HTMLElement
64
63
65
- expect ( node . getAttribute ( 'id' ) ) . toBe ( 'test' ) // id is not whitelisted, but explicitly bound
66
- expect ( node . getAttribute ( 'foo' ) ) . toBe ( null ) // foo is not whitelisted
64
+ expect ( node . getAttribute ( 'id' ) ) . toBe ( 'test' )
65
+ expect ( node . getAttribute ( 'foo' ) ) . toBe ( '1' )
67
66
expect ( node . getAttribute ( 'class' ) ) . toBe ( 'c2 c0' )
68
67
expect ( node . style . color ) . toBe ( 'green' )
69
68
expect ( node . style . fontWeight ) . toBe ( 'bold' )
70
69
expect ( node . dataset . id ) . toBe ( '1' )
71
70
node . dispatchEvent ( new CustomEvent ( 'click' ) )
72
71
expect ( click ) . toHaveBeenCalled ( )
73
72
73
+ await nextTick ( )
74
+ expect ( childUpdated ) . toHaveBeenCalled ( )
75
+ expect ( node . getAttribute ( 'id' ) ) . toBe ( 'test' )
76
+ expect ( node . getAttribute ( 'foo' ) ) . toBe ( '2' )
77
+ expect ( node . getAttribute ( 'class' ) ) . toBe ( 'c2 c1' )
78
+ expect ( node . style . color ) . toBe ( 'red' )
79
+ expect ( node . style . fontWeight ) . toBe ( 'bold' )
80
+ expect ( node . dataset . id ) . toBe ( '2' )
81
+ } )
82
+
83
+ it ( 'should only allow whitelisted fallthrough on functional component with optional props' , async ( ) => {
84
+ const click = jest . fn ( )
85
+ const childUpdated = jest . fn ( )
86
+
87
+ const count = ref ( 0 )
88
+
89
+ function inc ( ) {
90
+ count . value ++
91
+ click ( )
92
+ }
93
+
94
+ const Hello = ( ) =>
95
+ h ( Child , {
96
+ foo : count . value + 1 ,
97
+ id : 'test' ,
98
+ class : 'c' + count . value ,
99
+ style : { color : count . value ? 'red' : 'green' } ,
100
+ onClick : inc
101
+ } )
102
+
103
+ const Child = ( props : any ) => {
104
+ childUpdated ( )
105
+ return h (
106
+ 'div' ,
107
+ {
108
+ class : 'c2' ,
109
+ style : { fontWeight : 'bold' }
110
+ } ,
111
+ props . foo
112
+ )
113
+ }
114
+
115
+ const root = document . createElement ( 'div' )
116
+ document . body . appendChild ( root )
117
+ render ( h ( Hello ) , root )
118
+
119
+ const node = root . children [ 0 ] as HTMLElement
120
+
121
+ // not whitelisted
122
+ expect ( node . getAttribute ( 'id' ) ) . toBe ( null )
123
+ expect ( node . getAttribute ( 'foo' ) ) . toBe ( null )
124
+
125
+ // whitelisted: style, class, event listeners
126
+ expect ( node . getAttribute ( 'class' ) ) . toBe ( 'c2 c0' )
127
+ expect ( node . style . color ) . toBe ( 'green' )
128
+ expect ( node . style . fontWeight ) . toBe ( 'bold' )
129
+ node . dispatchEvent ( new CustomEvent ( 'click' ) )
130
+ expect ( click ) . toHaveBeenCalled ( )
131
+
132
+ await nextTick ( )
133
+ expect ( childUpdated ) . toHaveBeenCalled ( )
134
+ expect ( node . getAttribute ( 'id' ) ) . toBe ( null )
135
+ expect ( node . getAttribute ( 'foo' ) ) . toBe ( null )
136
+ expect ( node . getAttribute ( 'class' ) ) . toBe ( 'c2 c1' )
137
+ expect ( node . style . color ) . toBe ( 'red' )
138
+ expect ( node . style . fontWeight ) . toBe ( 'bold' )
139
+ } )
140
+
141
+ it ( 'should allow all attrs on functional component with declared props' , async ( ) => {
142
+ const click = jest . fn ( )
143
+ const childUpdated = jest . fn ( )
144
+
145
+ const count = ref ( 0 )
146
+
147
+ function inc ( ) {
148
+ count . value ++
149
+ click ( )
150
+ }
151
+
152
+ const Hello = ( ) =>
153
+ h ( Child , {
154
+ foo : count . value + 1 ,
155
+ id : 'test' ,
156
+ class : 'c' + count . value ,
157
+ style : { color : count . value ? 'red' : 'green' } ,
158
+ onClick : inc
159
+ } )
160
+
161
+ const Child = ( props : { foo : number } ) => {
162
+ childUpdated ( )
163
+ return h (
164
+ 'div' ,
165
+ {
166
+ class : 'c2' ,
167
+ style : { fontWeight : 'bold' }
168
+ } ,
169
+ props . foo
170
+ )
171
+ }
172
+ Child . props = [ 'foo' ]
173
+
174
+ const root = document . createElement ( 'div' )
175
+ document . body . appendChild ( root )
176
+ render ( h ( Hello ) , root )
177
+
178
+ const node = root . children [ 0 ] as HTMLElement
179
+
180
+ expect ( node . getAttribute ( 'id' ) ) . toBe ( 'test' )
181
+ expect ( node . getAttribute ( 'foo' ) ) . toBe ( null ) // declared as prop
182
+ expect ( node . getAttribute ( 'class' ) ) . toBe ( 'c2 c0' )
183
+ expect ( node . style . color ) . toBe ( 'green' )
184
+ expect ( node . style . fontWeight ) . toBe ( 'bold' )
185
+ node . dispatchEvent ( new CustomEvent ( 'click' ) )
186
+ expect ( click ) . toHaveBeenCalled ( )
187
+
74
188
await nextTick ( )
75
189
expect ( childUpdated ) . toHaveBeenCalled ( )
76
190
expect ( node . getAttribute ( 'id' ) ) . toBe ( 'test' )
0 commit comments