JS Test Harness: Remove more link tags
[WebKit-https.git] / LayoutTests / fast / mutation / observe-childList.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <script src="../js/resources/js-test-pre.js"></script>
6 <title></title>
7 </head>
8 <body>
9 <p id=description></p>
10 <div id="console"></div>
11 <script>
12
13 window.jsTestIsAsync = true;
14 var mutations, mutations2;
15 var calls;
16 var div, removedDiv1, removedDiv2, addedDiv1, addedDiv2, addedDiv3;
17
18 function testBasic() {
19     var div;
20     var observer;
21
22     function start() {
23         debug('Testing basic aspects of childList observation.');
24
25         mutations = null;
26         div = document.createElement('div');
27         observer = new WebKitMutationObserver(function(m) {
28             mutations = m;
29         });
30
31         observer.observe(div, { childList: true });
32         removedDiv1 = div.appendChild(document.createElement('div'));
33         setTimeout(checkDisconnectAndMutate, 0);
34     }
35
36     function checkDisconnectAndMutate() {
37         debug('...can childList changes be observed at all');
38
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');
43
44         mutations = null;
45         observer.disconnect();
46         removedDiv1 = div.appendChild(document.createElement('div'));
47         setTimeout(checkNotDeliveredAndMutateMultiple, 0);
48     }
49
50     function checkNotDeliveredAndMutateMultiple() {
51         debug('...observer.disconnect() should prevent further delivery of mutations.');
52
53         shouldBe('mutations', 'null');
54         observer.observe(div, { childList: true });
55         removedDiv1 = div.removeChild(div.firstChild);
56         removedDiv2 = div.removeChild(div.firstChild);
57         setTimeout(finish);
58     }
59
60     function finish() {
61         debug('...re-observing after disconnect works with the same observer.');
62
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();
71         debug('');
72         runNextTest();
73     }
74
75     start();
76 }
77
78 function testWrongType() {
79     var div;
80     var observer;
81
82     function start() {
83         debug('Testing that observing without specifying "childList" does not result in hearing about childList changes.');
84
85         mutations = null;
86         div = document.createElement('div');
87         observer = new WebKitMutationObserver(function(m) {
88             mutations = m;
89         });
90
91         observer.observe(div, { attributes: true, characterData: true });
92         div.appendChild(document.createElement('div'));
93         setTimeout(finish, 0);
94     }
95
96     function finish() {
97         shouldBe('mutations', 'null');
98         observer.disconnect();
99         debug('');
100         runNextTest();
101     }
102
103     start();
104 }
105
106 function testMultipleRegistration() {
107     var div;
108     var observer;
109
110     function start() {
111         debug('Testing that re-observing the same node with the same observer has the effect of resetting the options.');
112
113         calls = 0;
114         mutations = null;
115         div = document.createElement('div');
116         observer = new WebKitMutationObserver(function(m) {
117             mutations = m;
118             calls++;
119         });
120
121         observer.observe(div, { childList: true, characterData: true });
122         observer.observe(div, { childList: true });
123         div.appendChild(document.createElement('div'));
124         setTimeout(checkDisconnectAndMutate, 0);
125     }
126
127     function checkDisconnectAndMutate() {
128         shouldBe('calls', '1');
129         shouldBe('mutations.length', '1');
130         shouldBe('mutations[0].type', '"childList"');
131         mutations = null;
132         observer.observe(div, { childList: true, characterData: true });
133         observer.observe(div, { attributes: true });
134         div.appendChild(document.createElement('div'));
135         setTimeout(finish, 0);
136     }
137
138     function finish() {
139         shouldBe('mutations', 'null');
140         observer.disconnect();
141         debug('');
142         runNextTest();
143     }
144
145     start();
146 }
147
148 function testMultipleObservers() {
149     var div;
150     var observer;
151     var observer2;
152
153     function start() {
154         debug('Testing that multiple observers can be registered to a given node and both receive mutations.');
155         mutations = null;
156         div = document.createElement('div');
157         observer = new WebKitMutationObserver(function(m) {
158             mutations = m;
159         });
160         observer2 = new WebKitMutationObserver(function(m) {
161             mutations2 = m;
162         });
163         observer.observe(div, { childList: true });
164         observer2.observe(div, { childList: true });
165         div.appendChild(document.createElement('div'));
166         setTimeout(finish, 0);
167     }
168
169     function finish() {
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();
176         debug('');
177         runNextTest();
178     }
179
180     start();
181 }
182
183 function testInnerHTMLAndInnerText() {
184     var div;
185     var observer;
186
187     function start() {
188         debug('Testing that innerText and innerHTML always result in a single childList mutation.');
189
190         mutations = null;
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) {
196             mutations = m;
197         });
198
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);
205     }
206
207     function checkInnerHTML() {
208         debug('...innerHTML');
209
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');
219
220         mutations = null;
221         div.innerText = 'foo';
222         setTimeout(finish, 0);
223     }
224
225     function finish() {
226         debug('...innerText');
227
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();
233         debug('');
234         runNextTest();
235     }
236
237     start();
238 }
239
240 function testReplaceChild() {
241     var div;
242     var observer;
243     var fragment;
244
245     function start() {
246         debug('Testing that replaceChild results in minimal childList mutations.');
247
248         mutations = null;
249         div = document.createElement('div');
250         div.innerHTML = '<span>Foo</span><div>Bar</div>';
251         removedDiv1 = div.firstChild;
252
253         observer = new WebKitMutationObserver(function(m) {
254             mutations = m;
255         });
256
257         observer.observe(div, { childList: true });
258         addedDiv1 = document.createElement('div');
259         div.replaceChild(addedDiv1, div.firstChild);
260         setTimeout(checkReplaceWithNode, 0);
261     }
262
263     function checkReplaceWithNode() {
264         debug('...simple replace child');
265
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');
272
273         mutations = null;
274         fragment = document.createDocumentFragment();
275         addedDiv1 = fragment.appendChild(document.createElement('div'));
276         addedDiv2 = fragment.appendChild(document.createElement('div'));
277         removedDiv1 = div.firstChild;
278
279         div.replaceChild(fragment, removedDiv1);
280
281         setTimeout(finish, 0);
282     }
283
284     function finish() {
285         debug('...replace with DocumentFragment');
286
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');
294
295         observer.disconnect();
296         debug('');
297         runNextTest();
298     }
299
300     start();
301 }
302
303 function testInsertBefore() {
304     var div;
305     var observer;
306     var fragment;
307
308     function start() {
309         debug('Testing that insertBefore results in minimal childList mutations.');
310
311         mutations = null;
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'));
317
318         observer = new WebKitMutationObserver(function(m) {
319             mutations = m;
320         });
321
322         observer.observe(div, { childList: true });
323         div.insertBefore(fragment, div.firstChild);
324         setTimeout(finish, 0);
325     }
326
327
328     function finish() {
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');
335
336         observer.disconnect();
337         debug('');
338         runNextTest();
339     }
340
341     start();
342 }
343
344 function testAppendChild() {
345     var div;
346     var observer;
347     var fragment;
348
349     function start() {
350         debug('Testing that appendChild results in minimal childList mutations.');
351
352         mutations = null;
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'));
358
359         observer = new WebKitMutationObserver(function(m) {
360             mutations = m;
361         });
362
363         observer.observe(div, { childList: true });
364         div.appendChild(fragment);
365         setTimeout(finish, 0);
366     }
367
368     function finish() {
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');
375
376         observer.disconnect();
377         debug('');
378         runNextTest();
379     }
380
381     start();
382 }
383
384 var tests = [testBasic, testWrongType, testMultipleRegistration, testMultipleObservers, testInnerHTMLAndInnerText, testReplaceChild, testInsertBefore, testAppendChild];
385 var testIndex = 0;
386  
387 function runNextTest() {
388     if (testIndex < tests.length)
389         tests[testIndex++]();
390     else
391         finishJSTest();
392 }
393
394 description('Test WebKitMutationObserver.observe on attributes.');
395
396 if (!window.WebKitMutationObserver)
397     testFailed('This test requires ENABLE(MUTATION_OBSERVERS)');
398 else
399     runNextTest();
400
401 </script>
402 <script src="../js/resources/js-test-post.js"></script>
403 </body>
404 </html>