4 <title>Test attributeChanged callback is called if custom element attribute value is set</title>
5 <meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
6 <meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
7 <meta name="assert" content="attributeChanged callback ... must be enqueued whenever custom element's attribute is added, changed or removed.">
8 <link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
9 <script src="../../../../../resources/testharness.js"></script>
10 <script src="../../../../../resources/testharnessreport.js"></script>
11 <script src="../../testcommon.js"></script>
12 <link rel="stylesheet" href="../../../../../resources/testharness.css">
18 var doc = newHTMLDocument();
19 var proto = newHTMLElementPrototype();
20 var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
22 var customElement = new GeneratedConstructor();
23 customElement.setAttribute('class', 'someClass');
24 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
25 'Callback attributeChanged should be called');
26 }, 'Test attributeChanged callback is called if attribute value is set by method ' +
27 'setAttribute(). The custom element is created via constructor.');
31 var doc = newHTMLDocument();
32 var proto = newHTMLElementPrototype();
33 var GeneratedConstructor = doc.registerElement('x-b', {prototype: proto});
35 var customElement = new GeneratedConstructor();
36 customElement.setAttribute('class', 'someClass');
37 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
38 'Unexpected callback attributeChanged arguments');
39 }, 'Test attributeChanged callback arguments if attribute value is set by method ' +
40 'setAttribute(). The custom element is created via constructor.');
44 var doc = newHTMLDocument();
45 var proto = newHTMLElementPrototype();
46 var GeneratedConstructor = doc.registerElement('x-c', {prototype: proto});
48 var customElement = new GeneratedConstructor();
49 customElement.classList.add('someClass');
50 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
51 'Callback attributeChanged should be called');
52 }, 'Test attributeChanged callback is called if attribute value is set by method ' +
53 'classList.add(). The custom element is created via constructor.');
57 var doc = newHTMLDocument();
58 var proto = newHTMLElementPrototype();
59 var GeneratedConstructor = doc.registerElement('x-d', {prototype: proto});
61 var customElement = new GeneratedConstructor();
62 customElement.classList.add('someClass');
63 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
64 'Unexpected callback attributeChanged arguments');
65 }, 'Test attributeChanged callback arguments if attribute value is set by method ' +
66 'classList.add(). The custom element is created via constructor.');
70 var doc = newHTMLDocument();
71 var proto = newHTMLElementPrototype();
72 var GeneratedConstructor = doc.registerElement('x-e', {prototype: proto});
74 var customElement = new GeneratedConstructor();
75 customElement.classList.toggle('someClass');
76 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
77 'Callback attributeChanged should be called');
78 }, 'Test attributeChanged callback is called if attribute value is set by method ' +
79 'classList.toggle(). The custom element is created via constructor.');
83 var doc = newHTMLDocument();
84 var proto = newHTMLElementPrototype();
85 var GeneratedConstructor = doc.registerElement('x-f', {prototype: proto});
87 var customElement = new GeneratedConstructor();
88 customElement.classList.toggle('someClass');
89 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
90 'Unexpected callback attributeChanged arguments');
91 }, 'Test attributeChanged callback arguments if attribute value is set by method ' +
92 'classList.toggle(). The custom element is created via constructor.');
96 var doc = newHTMLDocument();
97 var proto = newHTMLElementPrototype();
98 var GeneratedConstructor = doc.registerElement('x-g', {prototype: proto});
100 var customElement = new GeneratedConstructor();
101 customElement.className = 'someClass';
102 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
103 'Callback attributeChanged should be called');
104 }, 'Test attributeChanged callback is called if attribute value is set as property. ' +
105 'The custom element is created via constructor.');
109 var doc = newHTMLDocument();
110 var proto = newHTMLElementPrototype();
111 var GeneratedConstructor = doc.registerElement('x-h', {prototype: proto});
113 var customElement = new GeneratedConstructor();
114 customElement.className = 'someClass';
115 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
116 'Unexpected callback attributeChanged arguments');
117 }, 'Test attributeChanged callback arguments if attribute value is set as property. '+
118 'The custom element is created via constructor.');
122 var doc = newHTMLDocument();
123 var proto = newHTMLElementPrototype();
124 doc.registerElement('x-i', {prototype: proto});
126 doc.body.innerHTML = '<x-i id="x-i" class="theClass"></x-i>';
127 assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
128 'Callback attributeChanged should not be called');
129 }, 'Test attributeChanged callback is not called if attribute value is specified in HTML. '+
130 'The custom element is created via innerHTML property.');
134 var doc = newHTMLDocument();
135 var proto = newHTMLElementPrototype();
136 doc.registerElement('x-j', {prototype: proto});
138 doc.body.innerHTML = '<x-j id="x-j" class="theClass"></x-j>';
139 var customElement = doc.querySelector('#x-j');
140 customElement.setAttribute('class', 'someClass');
141 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
142 'Callback attributeChanged should be called');
143 }, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
144 'The custom element is created via innerHTML property.');
148 var doc = newHTMLDocument();
149 var proto = newHTMLElementPrototype();
150 doc.registerElement('x-k', {prototype: proto});
152 doc.body.innerHTML = '<x-k id="x-k"></x-k>';
153 var customElement = doc.querySelector('#x-k');
154 customElement.setAttribute('class', 'someClass');
155 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
156 'Unexpected callback attributeChanged arguments');
157 }, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
158 'The custom element is created via innerHTML property.');
162 var doc = newHTMLDocument();
164 doc.body.innerHTML = '<x-l id="x-l"></x-l>';
165 var customElement = doc.querySelector('#x-l');
166 // this call shouldn't invoke or enqueue the callback
167 customElement.setAttribute('class', 'someClass');
169 var proto = newHTMLElementPrototype();
170 doc.registerElement('x-l', {prototype: proto});
171 assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
172 'Callback attributeChanged should not be called');
174 customElement.setAttribute('class', 'someClass2');
175 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
176 'Callback attributeChanged should be called');
177 }, 'Test attributeChanged callback is not called if attribute value of unresolved element '+
178 'is set by method setAttribute().');
182 var doc = newHTMLDocument();
183 HTML5_ELEMENTS.forEach(function(element) {
184 var obj = doc.createElement(element);
185 var proto = newCustomElementPrototype(obj.constructor.prototype);
186 var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
191 var customElement = new GeneratedConstructor();
192 customElement.setAttribute('class', 'someClass');
193 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
194 'Callback attributeChanged should be called');
196 }, 'Test attributeChanged callback of the custom element that extends some HTML element. ' +
197 'Test that the callback is called');
201 var doc = newHTMLDocument();
202 HTML5_ELEMENTS.forEach(function(element) {
203 var obj = doc.createElement(element);
204 var proto = newCustomElementPrototype(obj.constructor.prototype);
205 var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1-1', {
210 var customElement = new GeneratedConstructor();
211 customElement.classList.add('someClass');
212 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
213 'Callback attributeChanged should be called');
215 }, 'Test attributeChanged callback is called if attribute is set by method classList.add(). '+
216 'The custom element extends some HTML element.');
220 var doc = newHTMLDocument();
221 HTML5_ELEMENTS.forEach(function(element) {
222 var obj = doc.createElement(element);
223 var proto = newCustomElementPrototype(obj.constructor.prototype);
224 var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-2', {
229 var customElement = new GeneratedConstructor();
230 customElement.setAttribute('class', 'someClass');
231 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
232 'Unexpected callback attributeChanged arguments');
234 }, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
235 'The custom element extends some HTML element.');
238 testInIFrame('../../resources/x-element.html', function(doc) {
239 var proto = newHTMLElementPrototype();
240 doc.registerElement('x-element', {prototype: proto});
242 var customElement = doc.querySelector('#x-element');
243 customElement.setAttribute('class', 'someClass');
244 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
245 'Callback attributeChanged should be called');
246 }, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
247 'The document has browsing context.');
250 testInIFrame('../../resources/x-element.html', function(doc) {
251 var proto = newHTMLElementPrototype();
252 doc.registerElement('x-element', {prototype: proto});
254 var customElement = doc.querySelector('#x-element');
255 customElement.setAttribute('class', 'someClass');
256 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
257 'Unexpected callback attributeChanged arguments');
258 }, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
259 'The document has browsing context.');
262 testInIFrame('../../resources/x-element.html', function(doc) {
263 var proto = newHTMLElementPrototype();
264 doc.registerElement('x-element', {prototype: proto});
266 var customElement = doc.querySelector('#x-element');
267 customElement.classList.add('someClass');
268 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
269 'Callback attributeChanged should be called');
270 }, 'Test attributeChanged callback is called if attribute value is set by method classList.add(). '+
271 'The document has browsing context.');
274 testInIFrame('../../resources/x-element.html', function(doc) {
275 var proto = newHTMLElementPrototype();
276 doc.registerElement('x-element', {prototype: proto});
278 var customElement = doc.querySelector('#x-element');
279 customElement.classList.add('someClass');
280 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
281 'Unexpected callback attributeChanged arguments');
282 }, 'Test attributeChanged callback arguments if attribute value is set by method classList.add(). '+
283 'The document has browsing context.');
286 testInIFrame('../../resources/x-element.html', function(doc) {
287 var customElement = doc.querySelector('#x-element');
288 // this call shouldn't invoke or enqueue the callback
289 customElement.setAttribute('name', 'someName');
291 var proto = newHTMLElementPrototype();
292 doc.registerElement('x-element', {prototype: proto});
293 assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
294 'Callback attributeChanged should not be called');
296 customElement.setAttribute('class', 'someClass');
297 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
298 'Callback attributeChanged should be called');
299 }, 'Test attributeChanged callback is not called if attribute value of unresolved element '+
300 'is set by method setAttribute(). The document has browsing context.');
303 testInIFrame('../../resources/x-element.html', function(doc) {
304 HTML5_ELEMENTS.forEach(function(element) {
305 var obj = doc.createElement(element);
306 var proto = newCustomElementPrototype(obj.constructor.prototype);
307 var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
312 var customElement = new GeneratedConstructor();
313 customElement.setAttribute('class', 'someClass');
314 assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
315 'Callback attributeChanged should be called');
317 }, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
318 'The document has browsing context. The custom element extends some HTML element.');
321 testInIFrame('../../resources/x-element.html', function(doc) {
322 HTML5_ELEMENTS.forEach(function(element) {
323 var obj = doc.createElement(element);
324 var proto = newCustomElementPrototype(obj.constructor.prototype);
325 var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-2', {
330 var customElement = new GeneratedConstructor();
331 customElement.setAttribute('class', 'someClass');
332 assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
333 'Unexpected callback attributeChanged arguments');
335 }, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
336 'The document has browsing context. The custom element extends some HTML element.');