5 <script src="../js/resources/js-test-pre.js"></script>
10 <div id="console"></div>
13 window.jsTestIsAsync = true;
14 var mutations, mutations2;
16 var div, removedDiv1, removedDiv2, addedDiv1, addedDiv2, addedDiv3;
18 function testBasic() {
23 debug('Testing basic aspects of childList observation.');
26 div = document.createElement('div');
27 observer = new WebKitMutationObserver(function(m) {
31 observer.observe(div, { childList: true });
32 removedDiv1 = div.appendChild(document.createElement('div'));
33 setTimeout(checkDisconnectAndMutate, 0);
36 function checkDisconnectAndMutate() {
37 debug('...can childList changes be observed at all');
39 shouldBe('mutations.length', '1');
40 shouldBe('mutations[0].type', '"childList"');
41 shouldBe('mutations[0].addedNodes.length', '1');
42 shouldBe('mutations[0].addedNodes[0]', 'removedDiv1');
45 observer.disconnect();
46 removedDiv1 = div.appendChild(document.createElement('div'));
47 setTimeout(checkNotDeliveredAndMutateMultiple, 0);
50 function checkNotDeliveredAndMutateMultiple() {
51 debug('...observer.disconnect() should prevent further delivery of mutations.');
53 shouldBe('mutations', 'null');
54 observer.observe(div, { childList: true });
55 removedDiv1 = div.removeChild(div.firstChild);
56 removedDiv2 = div.removeChild(div.firstChild);
61 debug('...re-observing after disconnect works with the same observer.');
63 shouldBe('mutations.length', '2');
64 shouldBe('mutations[0].type', '"childList"');
65 shouldBe('mutations[0].removedNodes.length', '1');
66 shouldBe('mutations[0].removedNodes[0]', 'removedDiv1');
67 shouldBe('mutations[1].type', '"childList"');
68 shouldBe('mutations[1].removedNodes.length', '1');
69 shouldBe('mutations[1].removedNodes[0]', 'removedDiv2');
70 observer.disconnect();
78 function testWrongType() {
83 debug('Testing that observing without specifying "childList" does not result in hearing about childList changes.');
86 div = document.createElement('div');
87 observer = new WebKitMutationObserver(function(m) {
91 observer.observe(div, { attributes: true, characterData: true });
92 div.appendChild(document.createElement('div'));
93 setTimeout(finish, 0);
97 shouldBe('mutations', 'null');
98 observer.disconnect();
106 function testMultipleRegistration() {
111 debug('Testing that re-observing the same node with the same observer has the effect of resetting the options.');
115 div = document.createElement('div');
116 observer = new WebKitMutationObserver(function(m) {
121 observer.observe(div, { childList: true, characterData: true });
122 observer.observe(div, { childList: true });
123 div.appendChild(document.createElement('div'));
124 setTimeout(checkDisconnectAndMutate, 0);
127 function checkDisconnectAndMutate() {
128 shouldBe('calls', '1');
129 shouldBe('mutations.length', '1');
130 shouldBe('mutations[0].type', '"childList"');
132 observer.observe(div, { childList: true, characterData: true });
133 observer.observe(div, { attributes: true });
134 div.appendChild(document.createElement('div'));
135 setTimeout(finish, 0);
139 shouldBe('mutations', 'null');
140 observer.disconnect();
148 function testMultipleObservers() {
154 debug('Testing that multiple observers can be registered to a given node and both receive mutations.');
156 div = document.createElement('div');
157 observer = new WebKitMutationObserver(function(m) {
160 observer2 = new WebKitMutationObserver(function(m) {
163 observer.observe(div, { childList: true });
164 observer2.observe(div, { childList: true });
165 div.appendChild(document.createElement('div'));
166 setTimeout(finish, 0);
170 shouldBe('mutations.length', '1');
171 shouldBe('mutations[0].type', '"childList"');
172 shouldBe('mutations2.length', '1');
173 shouldBe('mutations2[0].type', '"childList"');
174 observer.disconnect();
175 observer2.disconnect();
183 function testInnerHTMLAndInnerText() {
188 debug('Testing that innerText and innerHTML always result in a single childList mutation.');
191 div = document.createElement('div');
192 div.innerHTML = '<span>Foo</span><div>Bar</div>';
193 removedDiv1 = div.firstChild;
194 removedDiv2 = removedDiv1.nextSibling;
195 observer = new WebKitMutationObserver(function(m) {
199 observer.observe(div, { childList: true });
200 div.innerHTML = 'foo<img src="bar.png"><p>Baz</p>';
201 addedDiv1 = div.childNodes[0];
202 addedDiv2 = div.childNodes[1];
203 addedDiv3 = div.childNodes[2];
204 setTimeout(checkInnerHTML, 0);
207 function checkInnerHTML() {
208 debug('...innerHTML');
210 shouldBe('mutations.length', '1');
211 shouldBe('mutations[0].type', '"childList"');
212 shouldBe('mutations[0].addedNodes.length', '3');
213 shouldBe('mutations[0].addedNodes[0]', 'addedDiv1');
214 shouldBe('mutations[0].addedNodes[1]', 'addedDiv2');
215 shouldBe('mutations[0].addedNodes[2]', 'addedDiv3');
216 shouldBe('mutations[0].removedNodes.length', '2');
217 shouldBe('mutations[0].removedNodes[0]', 'removedDiv1');
218 shouldBe('mutations[0].removedNodes[1]', 'removedDiv2');
221 div.innerText = 'foo';
222 setTimeout(finish, 0);
226 debug('...innerText');
228 shouldBe('mutations.length', '1');
229 shouldBe('mutations[0].type', '"childList"');
230 shouldBe('mutations[0].addedNodes.length', '1');
231 shouldBe('mutations[0].removedNodes.length', '3');
232 observer.disconnect();
240 function testReplaceChild() {
246 debug('Testing that replaceChild results in minimal childList mutations.');
249 div = document.createElement('div');
250 div.innerHTML = '<span>Foo</span><div>Bar</div>';
251 removedDiv1 = div.firstChild;
253 observer = new WebKitMutationObserver(function(m) {
257 observer.observe(div, { childList: true });
258 addedDiv1 = document.createElement('div');
259 div.replaceChild(addedDiv1, div.firstChild);
260 setTimeout(checkReplaceWithNode, 0);
263 function checkReplaceWithNode() {
264 debug('...simple replace child');
266 shouldBe('mutations.length', '1');
267 shouldBe('mutations[0].type', '"childList"');
268 shouldBe('mutations[0].addedNodes.length', '1');
269 shouldBe('mutations[0].addedNodes[0]', 'addedDiv1');
270 shouldBe('mutations[0].removedNodes.length', '1');
271 shouldBe('mutations[0].removedNodes[0]', 'removedDiv1');
274 fragment = document.createDocumentFragment();
275 addedDiv1 = fragment.appendChild(document.createElement('div'));
276 addedDiv2 = fragment.appendChild(document.createElement('div'));
277 removedDiv1 = div.firstChild;
279 div.replaceChild(fragment, removedDiv1);
281 setTimeout(finish, 0);
285 debug('...replace with DocumentFragment');
287 shouldBe('mutations.length', '1');
288 shouldBe('mutations[0].type', '"childList"');
289 shouldBe('mutations[0].addedNodes.length', '2');
290 shouldBe('mutations[0].addedNodes[0]', 'addedDiv1');
291 shouldBe('mutations[0].addedNodes[1]', 'addedDiv2');
292 shouldBe('mutations[0].removedNodes.length', '1');
293 shouldBe('mutations[0].removedNodes[0]', 'removedDiv1');
295 observer.disconnect();
303 function testInsertBefore() {
309 debug('Testing that insertBefore results in minimal childList mutations.');
312 div = document.createElement('div');
313 div.innerHTML = '<span>Foo</span>';
314 fragment = document.createDocumentFragment();
315 addedDiv1 = fragment.appendChild(document.createElement('div'));
316 addedDiv2 = fragment.appendChild(document.createElement('div'));
318 observer = new WebKitMutationObserver(function(m) {
322 observer.observe(div, { childList: true });
323 div.insertBefore(fragment, div.firstChild);
324 setTimeout(finish, 0);
329 shouldBe('mutations.length', '1');
330 shouldBe('mutations[0].type', '"childList"');
331 shouldBe('mutations[0].addedNodes.length', '2');
332 shouldBe('mutations[0].addedNodes[0]', 'addedDiv1');
333 shouldBe('mutations[0].addedNodes[1]', 'addedDiv2');
334 shouldBe('mutations[0].removedNodes.length', '0');
336 observer.disconnect();
344 function testAppendChild() {
350 debug('Testing that appendChild results in minimal childList mutations.');
353 div = document.createElement('div');
354 div.innerHTML = '<span>Foo</span>';
355 fragment = document.createDocumentFragment();
356 addedDiv1 = fragment.appendChild(document.createElement('div'));
357 addedDiv2 = fragment.appendChild(document.createElement('div'));
359 observer = new WebKitMutationObserver(function(m) {
363 observer.observe(div, { childList: true });
364 div.appendChild(fragment);
365 setTimeout(finish, 0);
369 shouldBe('mutations.length', '1');
370 shouldBe('mutations[0].type', '"childList"');
371 shouldBe('mutations[0].addedNodes.length', '2');
372 shouldBe('mutations[0].addedNodes[0]', 'addedDiv1');
373 shouldBe('mutations[0].addedNodes[1]', 'addedDiv2');
374 shouldBe('mutations[0].removedNodes.length', '0');
376 observer.disconnect();
384 var tests = [testBasic, testWrongType, testMultipleRegistration, testMultipleObservers, testInnerHTMLAndInnerText, testReplaceChild, testInsertBefore, testAppendChild];
387 function runNextTest() {
388 if (testIndex < tests.length)
389 tests[testIndex++]();
394 description('Test WebKitMutationObserver.observe on attributes.');
396 if (!window.WebKitMutationObserver)
397 testFailed('This test requires ENABLE(MUTATION_OBSERVERS)');
402 <script src="../js/resources/js-test-post.js"></script>