OLD | NEW |
| (Empty) |
1 <html> | |
2 <link rel="import" href="../resources/chai.html" /> | |
3 <link rel="import" href="../resources/mocha.html" /> | |
4 <script> | |
5 describe('MutationObserver.observe on attributes', function() { | |
6 it('should handle basic aspects of attribute observation', function(done) { | |
7 var div; | |
8 var observer; | |
9 var mutations; | |
10 | |
11 function start() { | |
12 div = document.createElement('div'); | |
13 div.setAttribute('bar', 'foo'); | |
14 | |
15 observer = new MutationObserver(function(records) { | |
16 mutations = records; | |
17 }); | |
18 | |
19 observer.observe(div, { attributes: true, characterData: true }); | |
20 div.setAttribute('foo', 'bar'); | |
21 div.removeAttribute('bar'); | |
22 setTimeout(checkDisconnectAndMutate, 0); | |
23 } | |
24 | |
25 function checkDisconnectAndMutate() { | |
26 // ...can attribute changes be observed at all | |
27 | |
28 assert.equal(mutations.length, 2); | |
29 assert.equal(mutations[0].type, "attributes"); | |
30 assert.equal(mutations[0].attributeName, "foo"); | |
31 assert.equal(mutations[1].type, "attributes"); | |
32 assert.equal(mutations[1].attributeName, "bar"); | |
33 | |
34 mutations = null; | |
35 observer.disconnect(); | |
36 div.setAttribute('foo', 'baz'); | |
37 setTimeout(checkNotDeliveredAndMutateMultiple, 0); | |
38 } | |
39 | |
40 function checkNotDeliveredAndMutateMultiple() { | |
41 // ...observer.disconnect() should prevent further delivery of mutations. | |
42 | |
43 assert.equal(mutations, null); | |
44 observer.observe(div, { attributes: true }); | |
45 div.setAttribute('foo', 'bat'); | |
46 div.setAttribute('bar', 'foo'); | |
47 setTimeout(finish); | |
48 } | |
49 | |
50 function finish() { | |
51 // ...re-observing after disconnect works with the same observer. | |
52 | |
53 assert.equal(mutations.length, 2); | |
54 assert.equal(mutations[0].type, "attributes"); | |
55 assert.equal(mutations[0].attributeName, "foo"); | |
56 assert.equal(mutations[1].type, "attributes"); | |
57 assert.equal(mutations[1].attributeName, "bar"); | |
58 observer.disconnect(); | |
59 done(); | |
60 } | |
61 | |
62 start(); | |
63 }); | |
64 | |
65 it('should not notify of attribute changes without asking', function(done) { | |
66 var div; | |
67 var observer; | |
68 var mutations; | |
69 | |
70 function start() { | |
71 div = document.createElement('div'); | |
72 observer = new MutationObserver(function(records) { | |
73 mutations = records; | |
74 }); | |
75 | |
76 observer.observe(div, { childList: true, characterData: true }); | |
77 div.setAttribute('foo', 'bar'); | |
78 setTimeout(finish, 0); | |
79 } | |
80 | |
81 function finish() { | |
82 assert.equal(mutations, null); | |
83 observer.disconnect(); | |
84 done(); | |
85 } | |
86 | |
87 start(); | |
88 }); | |
89 | |
90 it('re-observing the same node with the same observer has the effect of resett
ing the options', function(done) { | |
91 var div; | |
92 var observer; | |
93 var mutations; | |
94 var calls = 0; | |
95 | |
96 function start() { | |
97 div = document.createElement('div'); | |
98 observer = new MutationObserver(function(records) { | |
99 mutations = records; | |
100 calls++; | |
101 }); | |
102 | |
103 observer.observe(div, { attributes: true, characterData: true }); | |
104 observer.observe(div, { attributes: true }); | |
105 div.setAttribute('foo', 'bar'); | |
106 setTimeout(checkDisconnectAndMutate, 0); | |
107 } | |
108 | |
109 function checkDisconnectAndMutate() { | |
110 assert.equal(calls, 1); | |
111 assert.equal(mutations.length, 1); | |
112 assert.equal(mutations[0].type, "attributes"); | |
113 assert.equal(mutations[0].attributeName, "foo"); | |
114 mutations = null; | |
115 observer.observe(div, { attributes: true, characterData: true }); | |
116 observer.observe(div, { childList: true }); | |
117 div.setAttribute('foo', 'baz'); | |
118 setTimeout(finish, 0); | |
119 } | |
120 | |
121 function finish() { | |
122 assert.equal(mutations, null); | |
123 observer.disconnect(); | |
124 done(); | |
125 } | |
126 | |
127 start(); | |
128 }); | |
129 | |
130 it('multiple observers can be registered to a given node and both receive muta
tions', function(done) { | |
131 var div; | |
132 var observer; | |
133 var observer2; | |
134 var mutations; | |
135 var mutations2; | |
136 | |
137 function start() { | |
138 div = document.createElement('div'); | |
139 observer = new MutationObserver(function(records) { | |
140 mutations = records; | |
141 }); | |
142 observer2 = new MutationObserver(function(records) { | |
143 mutations2 = records; | |
144 }); | |
145 observer.observe(div, { attributes: true }); | |
146 observer2.observe(div, { attributes: true }); | |
147 div.setAttribute('foo', 'bar'); | |
148 setTimeout(finish, 0); | |
149 } | |
150 | |
151 function finish() { | |
152 assert.equal(mutations.length, 1); | |
153 assert.equal(mutations[0].type, "attributes"); | |
154 assert.equal(mutations[0].attributeName, "foo"); | |
155 assert.equal(mutations2.length, 1); | |
156 assert.equal(mutations2[0].type, "attributes"); | |
157 assert.equal(mutations2[0].attributeName, "foo"); | |
158 observer.disconnect(); | |
159 observer2.disconnect(); | |
160 done(); | |
161 } | |
162 | |
163 start(); | |
164 }); | |
165 | |
166 it('should deliver mutations on modifications to node properties which delegat
e to attribute storage', function(done) { | |
167 var img, a; | |
168 var observer; | |
169 var mutations; | |
170 | |
171 function start() { | |
172 img = document.createElement('img'); | |
173 a = document.createElement('a'); | |
174 | |
175 observer = new MutationObserver(function(records) { | |
176 mutations = records; | |
177 }); | |
178 | |
179 observer.observe(img, { attributes: true }); | |
180 observer.observe(a, { attributes: true }); | |
181 | |
182 img.src = 'baz.png'; | |
183 a.href = 'foo.html'; | |
184 | |
185 setTimeout(finish, 0); | |
186 } | |
187 | |
188 function finish() { | |
189 assert.equal(mutations.length, 2); | |
190 assert.equal(mutations[0].type, "attributes"); | |
191 assert.equal(mutations[0].attributeName, "src"); | |
192 assert.equal(mutations[1].type, "attributes"); | |
193 assert.equal(mutations[1].attributeName, "href"); | |
194 observer.disconnect(); | |
195 done(); | |
196 } | |
197 | |
198 start(); | |
199 }); | |
200 | |
201 it('should handle basic oldValue delivery', function(done) { | |
202 var div; | |
203 var observer; | |
204 var mutations; | |
205 | |
206 function start() { | |
207 div = document.createElement('div'); | |
208 div.setAttribute('bar', 'boo'); | |
209 | |
210 observer = new MutationObserver(function(records) { | |
211 mutations = records; | |
212 }); | |
213 observer.observe(div, { attributes: true, attributeOldValue: true }); | |
214 div.setAttribute('foo', 'bar'); | |
215 div.setAttribute('foo', 'baz'); | |
216 div.removeAttribute('bar'); | |
217 div.removeAttribute('non-existant'); | |
218 setTimeout(finish, 0); | |
219 } | |
220 | |
221 function finish() { | |
222 assert.equal(mutations.length, 3); | |
223 assert.equal(mutations[0].type, "attributes"); | |
224 assert.equal(mutations[0].attributeName, "foo"); | |
225 assert.equal(mutations[0].oldValue, null); | |
226 assert.equal(mutations[1].type, "attributes"); | |
227 assert.equal(mutations[1].attributeName, "foo"); | |
228 assert.equal(mutations[1].oldValue, "bar"); | |
229 assert.equal(mutations[2].type, "attributes"); | |
230 assert.equal(mutations[2].attributeName, "bar"); | |
231 assert.equal(mutations[2].oldValue, "boo"); | |
232 observer.disconnect(); | |
233 done(); | |
234 } | |
235 | |
236 start(); | |
237 }); | |
238 | |
239 it('should deliver oldValue when needed', function(done) { | |
240 var div; | |
241 var observerWithOldValue; | |
242 var observer; | |
243 var mutationsWithOldValue; | |
244 var mutations; | |
245 | |
246 function start() { | |
247 div = document.createElement('div'); | |
248 div.setAttribute('foo', 'bar'); | |
249 observerWithOldValue = new MutationObserver(function(records) { | |
250 mutationsWithOldValue = records; | |
251 }); | |
252 observer = new MutationObserver(function(records) { | |
253 mutations = records; | |
254 }); | |
255 observerWithOldValue.observe(div, { attributes: true, attributeOldValue: t
rue }); | |
256 observer.observe(div, { attributes: true }); | |
257 div.setAttribute('foo', 'baz'); | |
258 setTimeout(finish, 0); | |
259 } | |
260 | |
261 function finish() { | |
262 assert.equal(mutationsWithOldValue.length, 1); | |
263 assert.equal(mutationsWithOldValue[0].type, "attributes"); | |
264 assert.equal(mutationsWithOldValue[0].attributeName, "foo"); | |
265 assert.equal(mutationsWithOldValue[0].oldValue, "bar"); | |
266 assert.equal(mutations.length, 1); | |
267 assert.equal(mutations[0].type, "attributes"); | |
268 assert.equal(mutations[0].attributeName, "foo"); | |
269 assert.equal(mutations[0].oldValue, null); | |
270 observerWithOldValue.disconnect(); | |
271 observer.disconnect(); | |
272 done(); | |
273 } | |
274 | |
275 start(); | |
276 }); | |
277 | |
278 it('should give attributeOldValue if any entries request it with multiple obse
rvers', function(done) { | |
279 var div; | |
280 var span; | |
281 var observer; | |
282 var mutations; | |
283 | |
284 function start() { | |
285 div = document.createElement('div'); | |
286 span = div.appendChild(document.createElement('span')); | |
287 span.setAttribute('foo', 'bar'); | |
288 observer = new MutationObserver(function(records) { | |
289 mutations = records; | |
290 }); | |
291 observer.observe(div, { attributes: true, attributeOldValue: true, subtree
: true }); | |
292 observer.observe(span, { attributes: true }); | |
293 span.setAttribute('foo', 'baz'); | |
294 setTimeout(finish, 0); | |
295 } | |
296 | |
297 function finish() { | |
298 assert.equal(mutations.length, 1); | |
299 assert.equal(mutations[0].type, "attributes"); | |
300 assert.equal(mutations[0].attributeName, "foo"); | |
301 assert.equal(mutations[0].oldValue, "bar"); | |
302 observer.disconnect(); | |
303 done(); | |
304 } | |
305 | |
306 start(); | |
307 }); | |
308 | |
309 it('should handle setting an attribute via reflected IDL attribute', function(
done) { | |
310 var div; | |
311 var observer; | |
312 var mutations; | |
313 | |
314 function start() { | |
315 div = document.createElement('div'); | |
316 observer = new MutationObserver(function(records) { | |
317 mutations = records; | |
318 }); | |
319 observer.observe(div, { attributes: true, attributeOldValue: true }); | |
320 div.id = 'foo'; | |
321 div.id = 'bar'; | |
322 div.id = null; | |
323 setTimeout(finish, 0); | |
324 } | |
325 | |
326 function finish() { | |
327 assert.equal(mutations.length, 3); | |
328 assert.equal(mutations[0].type, "attributes"); | |
329 assert.equal(mutations[0].attributeName, "id"); | |
330 assert.equal(mutations[0].oldValue, null); | |
331 assert.equal(mutations[1].type, "attributes"); | |
332 assert.equal(mutations[1].attributeName, "id"); | |
333 assert.equal(mutations[1].oldValue, "foo"); | |
334 assert.equal(mutations[2].type, "attributes"); | |
335 assert.equal(mutations[2].attributeName, "id"); | |
336 assert.equal(mutations[2].oldValue, "bar"); | |
337 observer.disconnect(); | |
338 done(); | |
339 } | |
340 | |
341 start(); | |
342 }); | |
343 | |
344 it('should respect attributeFilter on HTML elements', function(done) { | |
345 var div, path; | |
346 var observer; | |
347 var mutations; | |
348 | |
349 function start() { | |
350 observer = new MutationObserver(function(records) { | |
351 mutations = records; | |
352 }); | |
353 | |
354 div = document.createElement('div'); | |
355 observer.observe(div, { attributes: true, attributeFilter: ['foo', 'bar',
'booM'] }); | |
356 div.setAttribute('foo', 'foo'); | |
357 div.setAttribute('bar', 'bar'); | |
358 div.setAttribute('baz', 'baz'); | |
359 div.setAttribute('BOOm', 'boom'); | |
360 | |
361 setTimeout(finish, 0); | |
362 } | |
363 | |
364 function finish() { | |
365 // ...only foo and bar should be received. | |
366 | |
367 assert.equal(mutations.length, 2); | |
368 assert.equal(mutations[0].type, "attributes"); | |
369 assert.equal(mutations[0].attributeName, "foo"); | |
370 assert.equal(mutations[1].type, "attributes"); | |
371 assert.equal(mutations[1].attributeName, "bar"); | |
372 observer.disconnect(); | |
373 done(); | |
374 } | |
375 | |
376 start(); | |
377 }); | |
378 | |
379 it('should respect different attributeFilters when observing multiple subtree
nodes', function(done) { | |
380 var div, div2, div3; | |
381 var observer; | |
382 var mutations; | |
383 | |
384 function start() { | |
385 observer = new MutationObserver(function(records) { | |
386 mutations = records; | |
387 }); | |
388 | |
389 div = document.createElement('div'); | |
390 div2 = div.appendChild(document.createElement('div')); | |
391 div3 = div2.appendChild(document.createElement('div')); | |
392 | |
393 observer.observe(div, { attributes: true, subtree: true, attributeFilter:
['foo', 'bar'] }); | |
394 observer.observe(div2, { attributes: true, subtree: true, attributeFilter:
['bar', 'bat'] }); | |
395 | |
396 div3.setAttribute('foo', 'foo'); | |
397 div3.setAttribute('bar', 'bar'); | |
398 div3.setAttribute('bat', 'bat'); | |
399 div3.setAttribute('baz', 'baz'); | |
400 | |
401 setTimeout(checkAndObserveAll, 0); | |
402 } | |
403 | |
404 function checkAndObserveAll() { | |
405 // ...only foo, bar & bat should be received. | |
406 | |
407 assert.equal(mutations.length, 3); | |
408 assert.equal(mutations[0].type, "attributes"); | |
409 assert.equal(mutations[0].attributeName, "foo"); | |
410 assert.equal(mutations[1].type, "attributes"); | |
411 assert.equal(mutations[1].attributeName, "bar"); | |
412 assert.equal(mutations[2].type, "attributes"); | |
413 assert.equal(mutations[2].attributeName, "bat"); | |
414 | |
415 observer.observe(div2, { attributes: true, subtree: true }); | |
416 div3.setAttribute('bar', 'bar'); | |
417 div3.setAttribute('bat', 'bat'); | |
418 div3.setAttribute('baz', 'baz'); | |
419 | |
420 setTimeout(finish, 0); | |
421 } | |
422 | |
423 function finish() { | |
424 // ...bar, bat & baz should all be received. | |
425 | |
426 assert.equal(mutations.length, 3); | |
427 assert.equal(mutations[0].type, "attributes"); | |
428 assert.equal(mutations[0].attributeName, "bar"); | |
429 assert.equal(mutations[1].type, "attributes"); | |
430 assert.equal(mutations[1].attributeName, "bat"); | |
431 assert.equal(mutations[2].type, "attributes"); | |
432 assert.equal(mutations[2].attributeName, "baz"); | |
433 | |
434 observer.disconnect(); | |
435 done(); | |
436 } | |
437 | |
438 start(); | |
439 }); | |
440 | |
441 it('should create records for the style property', function(done) { | |
442 var div, path; | |
443 var observer; | |
444 var mutations; | |
445 | |
446 function start() { | |
447 observer = new MutationObserver(function(records) { | |
448 mutations = records; | |
449 }); | |
450 | |
451 div = document.createElement('div'); | |
452 div.setAttribute('style', 'color: yellow; width: 100px;'); | |
453 observer.observe(div, { attributes: true }); | |
454 div.style.color = 'red'; | |
455 div.style.width = '200px'; | |
456 div.style.color = 'blue'; | |
457 | |
458 setTimeout(checkAndContinue, 0); | |
459 } | |
460 | |
461 function checkAndContinue() { | |
462 assert.equal(mutations.length, 3); | |
463 assert.equal(mutations[0].type, "attributes"); | |
464 assert.equal(mutations[0].attributeName, "style"); | |
465 assert.equal(mutations[0].oldValue, null); | |
466 assert.equal(mutations[1].type, "attributes"); | |
467 assert.equal(mutations[1].attributeName, "style"); | |
468 assert.equal(mutations[1].oldValue, null); | |
469 assert.equal(mutations[2].type, "attributes"); | |
470 assert.equal(mutations[2].attributeName, "style"); | |
471 assert.equal(mutations[2].oldValue, null); | |
472 | |
473 mutations = null; | |
474 div.getAttribute('style'); | |
475 setTimeout(finish, 0); | |
476 } | |
477 | |
478 function finish() { | |
479 // ...mutation record created. | |
480 | |
481 assert.equal(mutations, null); | |
482 | |
483 observer.disconnect(); | |
484 done(); | |
485 } | |
486 | |
487 start(); | |
488 }); | |
489 | |
490 it('should have oldValue for style property mutations', function(done) { | |
491 var div, path; | |
492 var observer; | |
493 var mutations; | |
494 | |
495 function start() { | |
496 observer = new MutationObserver(function(records) { | |
497 mutations = records; | |
498 }); | |
499 | |
500 div = document.createElement('div'); | |
501 div.setAttribute('style', 'color: yellow; width: 100px;'); | |
502 observer.observe(div, { attributes: true, attributeOldValue: true }); | |
503 div.style.color = 'red'; | |
504 div.style.width = '200px'; | |
505 div.style.color = 'blue'; | |
506 | |
507 setTimeout(checkAndContinue, 0); | |
508 } | |
509 | |
510 function checkAndContinue() { | |
511 assert.equal(mutations.length, 3); | |
512 assert.equal(mutations[0].type, "attributes"); | |
513 assert.equal(mutations[0].attributeName, "style"); | |
514 assert.equal(mutations[0].oldValue, "color: yellow; width: 100px;"); | |
515 assert.equal(mutations[1].type, "attributes"); | |
516 assert.equal(mutations[1].attributeName, "style"); | |
517 assert.equal(mutations[1].oldValue, "color: rgb(255, 0, 0); width: 100px;"
); | |
518 assert.equal(mutations[2].type, "attributes"); | |
519 assert.equal(mutations[2].attributeName, "style"); | |
520 assert.equal(mutations[2].oldValue, "color: rgb(255, 0, 0); width: 200px;"
); | |
521 | |
522 mutations = null; | |
523 div.getAttribute('style'); | |
524 setTimeout(finish, 0); | |
525 } | |
526 | |
527 function finish() { | |
528 // ...mutation record created. | |
529 | |
530 assert.equal(mutations, null); | |
531 | |
532 observer.disconnect(); | |
533 done(); | |
534 } | |
535 | |
536 start(); | |
537 }); | |
538 | |
539 it('should not create records for noop style property mutation', function(done
) { | |
540 var div, path; | |
541 var observer; | |
542 var mutations; | |
543 | |
544 function start() { | |
545 observer = new MutationObserver(function(records) { | |
546 mutations = records; | |
547 }); | |
548 | |
549 div = document.createElement('div'); | |
550 div.setAttribute('style', 'color: yellow; width: 100px;'); | |
551 observer.observe(div, { attributes: true }); | |
552 div.style.removeProperty('height'); | |
553 | |
554 setTimeout(finish, 0); | |
555 } | |
556 | |
557 function finish() { | |
558 assert.equal(mutations, null); | |
559 | |
560 observer.disconnect(); | |
561 done(); | |
562 } | |
563 | |
564 start(); | |
565 }); | |
566 | |
567 it('should create records when mutating through the attribute collection', fun
ction(done) { | |
568 var observer; | |
569 var mutations; | |
570 var div; | |
571 | |
572 function start() { | |
573 observer = new MutationObserver(function(records) { | |
574 mutations = records; | |
575 }); | |
576 | |
577 div = document.createElement('div'); | |
578 div.setAttribute('data-test', 'foo'); | |
579 observer.observe(div, { attributes: true, attributeOldValue: true }); | |
580 div.attributes['data-test'].value = 'bar'; | |
581 | |
582 setTimeout(finish, 0); | |
583 } | |
584 | |
585 function finish() { | |
586 assert.equal(mutations.length, 1); | |
587 assert.equal(mutations[0].target, div); | |
588 assert.equal(mutations[0].type, "attributes"); | |
589 assert.equal(mutations[0].attributeName, "data-test"); | |
590 assert.equal(mutations[0].oldValue, "foo"); | |
591 | |
592 observer.disconnect(); | |
593 done(); | |
594 } | |
595 | |
596 start(); | |
597 }); | |
598 }); | |
599 </script> | |
600 </body> | |
601 </html> | |
OLD | NEW |