| 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 |