include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / mshtml / tests / dom.js
blob325cacf482376692f48b5e89c0d4cc63546459c0
1 /*
2  * Copyright 2017 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
19 var tests = [];
21 sync_test("url", function() {
22     ok(document.URL === "http://winetest.example.org/index.html?dom.js", "document.URL = " + document.URL);
23     ok(!("documentURI" in document), "documentURI in document");
24 });
26 sync_test("input_selection", function() {
27     var input = document.createElement("input");
28     input.type = "text";
29     input.value = "test";
30     document.body.appendChild(input);
32     function test_range(start, end) {
33         ok(input.selectionStart === start, "input.selectionStart = " + input.selectionStart + " expected " + start);
34         ok(input.selectionEnd === end, "input.selectionEnd = " + input.selectionEnd + " expected " + end);
35     }
37     test_range(0, 0);
39     input.selectionStart = 2;
40     test_range(2, 2);
42     input.selectionStart = -1;
43     test_range(0, 2);
45     input.selectionStart = 10;
46     test_range(4, 4);
48     input.selectionEnd = 2;
49     test_range(2, 2);
51     input.selectionEnd = -1;
52     test_range(0, 0);
54     input.selectionEnd = 10;
55     test_range(0, 4);
57     input.setSelectionRange(2, 3);
58     test_range(2, 3);
60     input.setSelectionRange(-1, 10);
61     test_range(0, 4);
63     input.setSelectionRange(3, 3);
64     test_range(3, 3);
65 });
67 sync_test("textContent", function() {
68     var text = document.createTextNode("test");
69     ok(text.textContent === "test", "text.textContent = " + text.textContent);
71     var div = document.createElement("div");
72     document.body.appendChild(div);
73     div.innerHTML = "abc<script>/* */</script><div>text</div>";
74     ok(div.textContent === "abc/* */text", "div.textContent = " + div.textContent);
76     div.textContent = "test";
77     ok(div.textContent === "test", "div.textContent = " + div.textContent);
78     ok(div.childNodes.length === 1, "div.childNodes.length = " + div.childNodes.length);
79     ok(div.firstChild.textContent === "test", "div.firstChild.textContent = " + div.firstChild.textContent);
81     div.textContent = "";
82     ok(div.textContent === "", "div.textContent = " + div.textContent);
83     ok(div.childNodes.length === 0, "div.childNodes.length = " + div.childNodes.length);
85     div.textContent = null;
86     ok(div.textContent === "", "div.textContent = " + div.textContent);
87     div.textContent = 11;
88     ok(div.textContent === "11", "div.textContent = " + div.textContent);
89     div.textContent = 10.5;
90     ok(div.textContent === "10.5", "div.textContent = " + div.textContent);
92     ok(document.textContent === null, "document.textContent = " + document.textContent);
93 });
95 sync_test("ElementTraversal", function() {
96     var div = document.createElement("div");
97     div.innerHTML = "abc<b>bold</b><script>/* */</script><div>text</div>def";
98     ok(div.childElementCount === 3, "div.childElementCount = " + div.childElementCount);
99     ok(div.firstElementChild.outerHTML === "<b>bold</b>",
100             "div.firstElementChild.outerHTML = " + div.firstElementChild.outerHTML);
101     ok(div.lastElementChild.outerHTML === "<div>text</div>",
102             "div.lastElementChild.outerHTML = " + div.lastElementChild.outerHTML);
103     ok(div.firstElementChild.nextElementSibling.outerHTML === "<script>/* */</script>",
104             "div.firstElementChild.nextElementSibling.outerHTML = " + div.firstElementChild.nextElementSibling.outerHTML);
105     ok(div.lastElementChild.nextElementSibling === null,
106             "div.lastElementChild.nextElementSibling = " + div.lastElementChild.nextElementSibling);
107     ok(div.lastElementChild.previousElementSibling.outerHTML === "<script>/* */</script>",
108             "div.lastElementChild.previousElementSibling.outerHTML = " + div.lastElementChild.previousElementSibling.outerHTML);
109     ok(div.firstElementChild.previousElementSibling === null,
110             "div.firstElementChild.previousElementSibling = " + div.firstElementChild.previousElementSibling);
112     div.innerHTML = "abc";
113     ok(div.childElementCount === 0, "div.childElementCount = " + div.childElementCount);
114     ok(div.firstElementChild === null, "div.firstElementChild = " + div.firstElementChild);
115     ok(div.lastElementChild === null, "div.lastElementChild = " + div.lastElementChild);
117     ok(!("childElementCount" in document), "childElementCount found in document");
118     ok(!("firstElementChild" in document), "firstElementChild found in document");
119     ok(!("nextElementSibling" in document), "nextElementSibling found in document");
122 sync_test("head", function() {
123     var h = document.head;
124     ok(h.tagName === "HEAD", "h.tagName = " + h.tagName);
125     ok(h === document.getElementsByTagName("head")[0], "unexpected head element");
128 async_test("iframe", function() {
129     document.body.innerHTML = '<iframe src="runscript.html?frame.js"></iframe>'
130     var iframe = document.body.firstChild;
132     iframe.onload = guard(function() {
133         var r = iframe.contentWindow.global_object.get_global_value();
134         ok(r === "global value", "get_global_value() returned " + r);
136         var f = iframe.contentWindow.global_object.get_global_value;
137         ok(f() === "global value", "f() returned " + f());
139         next_test();
140     });
143 async_test("iframe_location", function() {
144     document.body.innerHTML = '<iframe src="emptyfile"></iframe>'
145     var iframe = document.body.firstChild;
147     iframe.onload = function() {
148         ok(iframe.contentWindow.location.pathname === "/emptyfile",
149            "path = " + iframe.contentWindow.location.pathname);
150         iframe.onload = function () {
151             ok(iframe.contentWindow.location.pathname === "/empty/file",
152                "path = " + iframe.contentWindow.location.pathname);
153             next_test();
154         }
155         iframe.src = "empty/file";
156     }
159 sync_test("anchor", function() {
160     var anchor_tests = [
161         { href: "http://www.winehq.org:123/about",
162           protocol: "http:", host: "www.winehq.org:123", path: "/about" },
163         { href: "https://www.winehq.org:123/about",
164           protocol: "https:", host: "www.winehq.org:123", path: "/about" },
165         { href: "about:blank",
166           protocol: "about:", host: "", path: "/blank", todo_pathname: 1 },
167         { href: "unknown:path",
168           protocol: "unknown:", host: "", path: "path" },
169         { href: "ftp:path",
170           protocol: "ftp:", host: "", path: "path" },
171         { href: "mailto:path",
172           protocol: "mailto:", host: "", path: "path" },
173         { href: "ws:path",
174           protocol: "ws:", host: "", path: "path" },
175         { href: "file:path",
176           protocol: "file:", host: "", path: "/path", todo_pathname: 1 },
177         { href: "file:///c:/dir/file.html",
178           protocol: "file:", host: "", path: "/c:/dir/file.html" },
179         { href: "http://www.winehq.org/about",
180           protocol: "http:", host: "www.winehq.org", path: "/about" },
181         { href: "https://www.winehq.org/about",
182           protocol: "https:", host: "www.winehq.org", path: "/about" },
183     ];
185     for(var i in anchor_tests) {
186         var t = anchor_tests[i];
187         document.body.innerHTML = '<a href="' + t.href + '">';
188         var anchor = document.body.firstChild;
189         ok(anchor.protocol === t.protocol, "anchor(" + t.href + ").protocol = " + anchor.protocol);
190         ok(anchor.host === t.host, "anchor(" + t.href + ").host = " + anchor.host);
191         todo_wine_if("todo_pathname" in t).
192         ok(anchor.pathname === t.path, "anchor(" + t.href + ").pathname = " + anchor.pathname);
193     }
196 sync_test("getElementsByClassName", function() {
197     var elems;
199     document.body.innerHTML = '<div class="class1">'
200         + '<div class="class1"></div>'
201         + '<a id="class1" class="class2"></a>'
202         + '</div>'
203         + '<script class="class1"></script>';
205     elems = document.getElementsByClassName("class1");
206     ok(elems.length === 3, "elems.length = " + elems.length);
207     ok(elems[0].tagName === "DIV", "elems[0].tagName = " + elems[0].tagName);
208     ok(elems[1].tagName === "DIV", "elems[1].tagName = " + elems[1].tagName);
209     ok(elems[2].tagName === "SCRIPT", "elems[2].tagName = " + elems[2].tagName);
211     elems = document.getElementsByClassName("class2");
212     ok(elems.length === 1, "elems.length = " + elems.length);
213     ok(elems[0].tagName === "A", "elems[0].tagName = " + elems[0].tagName);
215     elems = document.getElementsByClassName("classnotfound");
216     ok(elems.length == 0, "elems.length = " + elems.length);
219 sync_test("createElementNS", function() {
220     var svg_ns = "http://www.w3.org/2000/svg";
221     var elem;
223     elem = document.createElementNS(null, "test");
224     ok(elem.tagName === "test", "elem.tagName = " + elem.tagName);
225     ok(elem.namespaceURI === null, "elem.namespaceURI = " + elem.namespaceURI);
227     elem = document.createElementNS(svg_ns, "test");
228     ok(elem.tagName === "test", "elem.tagName = " + elem.tagName);
229     ok(elem.namespaceURI === svg_ns, "elem.namespaceURI = " + elem.namespaceURI);
231     elem = document.createElementNS(svg_ns, "svg");
232     ok(elem.tagName === "svg", "elem.tagName = " + elem.tagName);
233     ok(elem.namespaceURI === svg_ns, "elem.namespaceURI = " + elem.namespaceURI);
235     elem = document.createElementNS("test", "svg");
236     ok(elem.tagName === "svg", "elem.tagName = " + elem.tagName);
237     ok(elem.namespaceURI === "test", "elem.namespaceURI = " + elem.namespaceURI);
240 sync_test("query_selector", function() {
241     document.body.innerHTML = '<div class="class1">'
242         + '<div class="class1"></div>'
243         + '<a id="class1" class="class2"></a>'
244         + '</div>'
245         + '<script class="class1"></script>';
247     var frag = document.createDocumentFragment()
248     var e = document.createElement("div");
249     e.innerHTML = '<div class="class3"></div><a id="class3" class="class4"></a></div>';
250     frag.appendChild(e);
251     var e = document.createElement("script");
252     e.className = "class3";
253     frag.appendChild(e);
255     e = document.querySelector("nomatch");
256     ok(e === null, "e = " + e);
257     e = document.body.querySelector("nomatch");
258     ok(e === null, "e = " + e);
259     e = frag.querySelector("nomatch");
260     ok(e === null, "e = " + e);
262     e = document.querySelector(".class1");
263     ok(e.tagName === "DIV", "e.tagName = " + e.tagName);
264     e = document.body.querySelector(".class1");
265     ok(e.tagName === "DIV", "e.tagName = " + e.tagName);
266     ok(e.msMatchesSelector(".class1") === true, "msMatchesSelector returned " + e.msMatchesSelector(".class1"));
267     ok(e.msMatchesSelector(".class2") === false, "msMatchesSelector returned " + e.msMatchesSelector(".class2"));
268     e = document.querySelector(".class3");
269     ok(e === null, "e = " + e);
270     e = document.body.querySelector(".class3");
271     ok(e === null, "e = " + e);
273     e = frag.querySelector(".class3");
274     ok(e.tagName === "DIV", "e.tagName = " + e.tagName);
275     e = frag.querySelector(".class4");
276     ok(e.tagName === "A", "e.tagName = " + e.tagName);
277     e = frag.querySelector(".class1");
278     ok(e === null, "e = " + e);
279     e = frag.querySelector(".class2");
280     ok(e === null, "e = " + e);
282     e = document.querySelector("a");
283     ok(e.tagName === "A", "e.tagName = " + e.tagName);
284     e = document.body.querySelector("a");
285     ok(e.tagName === "A", "e.tagName = " + e.tagName);
286     e = frag.querySelector("a");
287     ok(e.tagName === "A", "e.tagName = " + e.tagName);
289     e = document.querySelectorAll(".class1");
290     ok(e.length === 3, "e.length = " + e.length);
291     e = document.body.querySelectorAll(".class1");
292     ok(e.length === 3, "e.length = " + e.length);
293     e = document.querySelectorAll(".class2");
294     ok(e.length === 1, "e.length = " + e.length);
295     e = document.body.querySelectorAll(".class2");
296     ok(e.length === 1, "e.length = " + e.length);
297     e = frag.querySelectorAll(".class3");
298     ok(e.length === 2, "e.length = " + e.length);
299     e = frag.querySelectorAll(".class4");
300     ok(e.length === 1, "e.length = " + e.length);
303 sync_test("compare_position", function() {
304     document.body.innerHTML = '<div><div></div><div></div></div>';
306     var parent = document.body.firstChild;
307     var child1 = parent.firstChild;
308     var child2 = child1.nextSibling;
309     var elem = document.createElement("div");
311     function compare_position(node1, node2, expected_result, ignore_mask) {
312         var cmp = node1.compareDocumentPosition(node2);
313         ok((cmp & ~ignore_mask) == expected_result,
314            "compareDocumentPosition returned " + cmp + " expected " + expected_result);
315     }
317     compare_position(child1, child2, 4);
318     compare_position(child2, child1, 2);
319     compare_position(parent, child1, 0x14);
320     compare_position(parent, child2, 0x14);
321     compare_position(parent, elem, 0x21, 6);
322     compare_position(elem, parent, 0x21, 6);
325 sync_test("rects", function() {
326     document.body.innerHTML = '<div>test</div>';
327     var elem = document.body.firstChild;
328     var rects = elem.getClientRects();
329     var rect = elem.getBoundingClientRect();
331     ok(rects.length === 1, "rect.length = " + rects.length);
332     ok(rects[0].top === rect.top, "rects[0].top = " + rects[0].top + " rect.top = " + rect.top);
333     ok(rects[0].bottom === rect.bottom, "rects[0].bottom = " + rects[0].bottom + " rect.bottom = " + rect.bottom);
334     ok(rect.height === rect.bottom - rect.top, "rect.height = " + rect.height + " rect.bottom = " + rect.bottom + " rect.top = " + rect.top);
335     ok(rect.width === rect.right - rect.left, "rect.width = " + rect.width + " rect.right = " + rect.right + " rect.left = " + rect.left);
337     elem = document.createElement("style");
338     rects = elem.getClientRects();
339     ok(rects.length === 0, "rect.length = " + rects.length);
342 sync_test("document_lastModified", function() {
343     // actually it seems to be rounded up from about ~250ms above a sec, but be more conservative with the check
344     var diff = Date.parse(document.lastModified) - performance.timing.navigationStart;
345     ok(diff > -1000 && diff < 1000, "lastModified too far from navigationStart: " + diff);
348 sync_test("document_owner", function() {
349     var node;
351     ok(document.ownerDocument === null, "ownerDocument = " + document.ownerDocument);
352     ok(document.body.ownerDocument === document,
353        "body.ownerDocument = " + document.body.ownerDocument);
354     ok(document.documentElement.ownerDocument === document,
355        "documentElement.ownerDocument = " + document.documentElement.ownerDocument);
357     node = document.createElement("test");
358     ok(node.ownerDocument === document, "element.ownerDocument = " + node.ownerDocument);
360     node = document.createDocumentFragment();
361     ok(node.ownerDocument === document, "fragment.ownerDocument = " + node.ownerDocument);
363     node = document.createTextNode("test");
364     ok(node.ownerDocument === document, "text.ownerDocument = " + node.ownerDocument);
367 sync_test("style_properties", function() {
368     document.body.innerHTML = '<div>test</div><svg></svg>';
369     var elem = document.body.firstChild;
370     var style = elem.style;
371     var current_style = elem.currentStyle;
372     var computed_style = window.getComputedStyle(elem);
373     var val;
375     style.cssFloat = "left";
376     ok(style.cssFloat === "left", "cssFloat = " + style.cssFloat);
377     ok(style.getPropertyValue("float") === "left",
378        'style.getPropertyValue("float") = ' + style.getPropertyValue("float"));
379     ok(style.getPropertyValue("cssFloat") === "",
380        'style.getPropertyValue("cssFloat") = ' + style.getPropertyValue("cssFloat"));
382     val = style.removeProperty("float");
383     ok(val === "left", "removeProperty() returned " + val);
384     ok(style.cssFloat === "", "cssFloat = " + style.cssFloat);
386     style.cssFloat = "left";
387     val = style.removeProperty("FloaT");
388     ok(val === "left", "removeProperty() returned " + val);
389     ok(style.cssFloat === "", "cssFloat = " + style.cssFloat);
391     style.cssFloat = "left";
392     val = style.removeProperty("cssFloat");
393     ok(val === "", "removeProperty() returned " + val);
394     ok(style.cssFloat === "left", "cssFloat = " + style.cssFloat);
395     ok(style["float"] === "left", "float = " + style["float"]);
397     style.testVal = "test";
398     val = style.removeProperty("testVal");
399     ok(val === "", "removeProperty() returned " + val);
400     ok(style.testVal === "test", "testVal = " + style.testVal);
402     style["z-index"] = 1;
403     ok(style.zIndex === 1, "zIndex = " + style.zIndex);
404     ok(style["z-index"] === 1, "z-index = " + style["z-index"]);
405     ok(style.getPropertyValue("z-index") === "1",
406        'style.getPropertyValue("x-index") = ' + style.getPropertyValue("z-index"));
407     ok(style.getPropertyValue("zIndex") === "",
408        'style.getPropertyValue("xIndex") = ' + style.getPropertyValue("zIndex"));
410     style.setProperty("border-width", "5px");
411     ok(style.borderWidth === "5px", "style.borderWidth = " + style.borderWidth);
413     try {
414         style.setProperty("border-width", 6);
415         ok(style.borderWidth === "5px", "style.borderWidth = " + style.borderWidth);
416     }catch(e) {
417         win_skip("skipping setProperty tests on too old IE version");
418         return;
419     }
421     style.setProperty("border-width", "7px", "test");
422     ok(style.borderWidth === "5px", "style.borderWidth = " + style.borderWidth);
424     style.setProperty("border-width", "6px", "");
425     ok(style.borderWidth === "6px", "style.borderWidth = " + style.borderWidth);
427     style.setProperty("border-width", "7px", "important");
428     ok(style.borderWidth === "7px", "style.borderWidth = " + style.borderWidth);
430     style.setProperty("border-width", "8px", undefined);
431     ok(style.borderWidth === "7px", "style.borderWidth = " + style.borderWidth);
433     style.clip = "rect(1px 1px 10px 10px)";
434     ok(style.clip === "rect(1px, 1px, 10px, 10px)", "style.clip = " + style.clip);
435     ok(current_style.clip === "rect(1px, 1px, 10px, 10px)",
436        "current_style.clip = " + current_style.clip);
437     ok(computed_style.clip === "rect(1px, 1px, 10px, 10px)",
438        "computed_style.clip = " + current_style.clip);
440     style.zIndex = 2;
441     ok(current_style.zIndex === 2, "current_style.zIndex = " + current_style.zIndex);
442     ok(computed_style.zIndex === 2, "computed_style.zIndex = " + computed_style.zIndex);
444     try {
445         current_style.zIndex = 1;
446         ok(false, "expected exception");
447     }catch(e) {}
449     try {
450         computed_style.zIndex = 1;
451         ok(false, "expected exception");
452     }catch(e) {}
454     elem = elem.nextSibling;
455     computed_style = window.getComputedStyle(elem);
457     elem.style.zIndex = 4;
458     ok(computed_style.zIndex === 4, "computed_style.zIndex = " + computed_style.zIndex);
460     window.getComputedStyle(elem, null);
463 sync_test("stylesheets", function() {
464     document.body.innerHTML = '<style>.div { margin-right: 1px; }</style>';
465     var elem = document.body.firstChild;
467     ok(document.styleSheets.length === 1, "document.styleSheets.length = " + document.styleSheets.length);
469     var stylesheet = document.styleSheets.item(0);
470     ok(stylesheet.rules.length === 1, "stylesheet.rules.length = " + stylesheet.rules.length);
471     ok(typeof(stylesheet.rules.item(0)) === "object",
472        "typeof(stylesheet.rules.item(0)) = " + typeof(stylesheet.rules.item(0)));
474     stylesheet = document.styleSheets[0];
475     ok(stylesheet.rules.length === 1, "document.styleSheets[0].rules.length = " + stylesheet.rules.length);
477     try {
478         stylesheet.rules.item(1);
479         ok(false, "expected exception");
480     }catch(e) {}
482     ok(stylesheet.href === null, "stylesheet.href = " + stylesheet.href);
484     var id = stylesheet.insertRule(".input { margin-left: 1px; }", 0);
485     ok(id === 0, "id = " + id);
486     ok(document.styleSheets.length === 1, "document.styleSheets.length = " + document.styleSheets.length);
488     try {
489         stylesheet.insertRule(".input { margin-left: 1px; }", 3);
490         ok(false, "expected exception");
491     }catch(e) {}
493     id = stylesheet.addRule(".p", "margin-top: 2px");
494     ok(id === 2, "id = " + id);
495     ok(document.styleSheets.length === 1, "document.styleSheets.length = " + document.styleSheets.length);
496     ok(stylesheet.rules.length === 3, "stylesheet.rules.length = " + stylesheet.rules.length);
498     id = stylesheet.addRule(".pre", "border: none", -1);
499     ok(id === 3, "id = " + id);
500     ok(stylesheet.rules.length === 4, "stylesheet.rules.length = " + stylesheet.rules.length);
502     id = stylesheet.addRule(".h1", " ", 0);
503     ok(id === 0, "id = " + id);
504     ok(stylesheet.rules.length === 5, "stylesheet.rules.length = " + stylesheet.rules.length);
506     id = stylesheet.addRule(".h2", "color: black", 8);
507     ok(id === 5, "id = " + id);
508     ok(stylesheet.rules.length === 6, "stylesheet.rules.length = " + stylesheet.rules.length);
510     try {
511         stylesheet.addRule("", "border: none", 0);
512         ok(false, "expected exception");
513     }catch(e) {}
514     try {
515         stylesheet.addRule(".img", "", 0);
516         ok(false, "expected exception");
517     }catch(e) {}
520 sync_test("storage", function() {
521     ok(typeof(window.sessionStorage) === "object",
522        "typeof(window.sessionStorage) = " + typeof(window.sessionStorage));
523     ok(typeof(window.localStorage) === "object" || typeof(window.localStorage) === "unknown",
524        "typeof(window.localStorage) = " + typeof(window.localStorage));
526     var item = sessionStorage.getItem("nonexisting");
527     ok(item === null, "'nonexisting' item = " + item);
528     item = sessionStorage["nonexisting"];
529     ok(item === undefined, "[nonexisting] item = " + item);
530     ok(!("nonexisting" in sessionStorage), "nonexisting in sessionStorage");
532     sessionStorage.setItem("foobar", 42);
533     ok("foobar" in sessionStorage, "foobar not in sessionStorage");
534     item = sessionStorage.getItem("foobar");
535     ok(item === "42", "'foobar' item = " + item);
536     item = sessionStorage["foobar"];
537     ok(item === "42", "[foobar] item = " + item);
538     sessionStorage.removeItem("foobar");
539     item = sessionStorage["foobar"];
540     ok(item === undefined, "[foobar] item after removal = " + item);
542     sessionStorage["barfoo"] = true;
543     ok("barfoo" in sessionStorage, "barfoo not in sessionStorage");
544     item = sessionStorage["barfoo"];
545     ok(item === "true", "[barfoo] item = " + item);
546     item = sessionStorage.getItem("barfoo");
547     ok(item === "true", "'barfoo' item = " + item);
550 async_test("animation", function() {
551     document.body.innerHTML =
552         "<style>" +
553         "  @keyframes testAnimation {0% { opacity: 0; } 100% { opacity: 1; }}" +
554         "  .testAnimation { animation-name: testAnimation; animation-duration: 0.01s; }" +
555         "</style>";
556     var div = document.createElement("div");
557     div.addEventListener("animationstart", function() {
558         div.addEventListener("animationend", next_test);
559     });
560     document.body.appendChild(div);
561     div.className = "testAnimation";
564 sync_test("navigator", function() {
565     ok(typeof(window.navigator) === "object",
566        "typeof(window.navigator) = " + typeof(window.navigator));
568     var v = window.navigator;
569     ok(v === window.navigator, "v != window.navigator");
570     v.testProp = true;
571     ok(window.navigator.testProp, "window.navigator.testProp = " + window.navigator.testProp);
574 sync_test("elem_props", function() {
575     var elem = document.body;
577     ok(elem.accessKey === "", "accessKey = " + elem.accessKey);
578     elem.accessKey = "q";
579     ok(elem.accessKey === "q", "accessKey = " + elem.accessKey + " expected q");
582 async_test("animation_frame", function() {
583     var id = requestAnimationFrame(function(x) { ok(false, "request was supposed to be cancelled"); });
584     id = cancelAnimationFrame(id);
585     ok(id === undefined, "cancelAnimationFrame returned " + id);
587     id = requestAnimationFrame(function(x) {
588         ok(this === window, "this != window");
589         ok(typeof(x) === "number", "x = " + x);
590         ok(arguments.length === 1, "arguments.length = " + arguments.length);
591         next_test();
592     });
593     cancelAnimationFrame(0);
594     clearInterval(id);
595     clearTimeout(id);
596     ok(typeof(id) === "number", "id = " + id);
597     ok(id !== 0, "id = 0");
600 sync_test("title", function() {
601     var elem = document.createElement("div");
602     ok(elem.title === "", "div.title = " + elem.title);
603     ok(elem.getAttribute("title") === null, "title attribute = " + elem.getAttribute("title"));
604     elem.title = "test";
605     ok(elem.title === "test", "div.title = " + elem.title);
606     ok(elem.getAttribute("title") === "test", "title attribute = " + elem.getAttribute("title"));
608     var orig = document.title;
609     document.title = "w i n e test";
610     var title = document.getElementsByTagName("title")[0];
611     ok(title.text === "w i n e test", "<title> element text = " + title.text);
612     title.text = "winetest";
613     ok(title.text === "winetest", "<title> element text after change = " + title.text);
614     ok(document.title === "winetest", "document.title after <title> change = " + document.title);
616     elem = document.createElement("title");
617     ok(elem.text === "", "detached <title> element text = " + elem.text);
618     elem.text = "foobar";
619     ok(elem.text === "foobar", "detached <title> element text after change = " + elem.text);
620     ok(document.title === "winetest", "document.title after detached <title> change = " + document.title);
622     title.parentNode.replaceChild(elem, title);
623     ok(document.title === "foobar", "document.title after <title> replaced = " + document.title);
624     document.title = orig;
627 sync_test("disabled", function() {
628     var elem = document.createElement("div");
629     document.body.appendChild(elem);
630     ok(elem.disabled === false, "div.disabled = " + elem.disabled);
631     ok(elem.getAttribute("disabled") === null, "disabled attribute = " + elem.getAttribute("disabled") + " expected null");
633     elem.disabled = true;
634     ok(elem.disabled === true, "div.disabled = " + elem.disabled);
635     ok(elem.getAttribute("disabled") === "", "disabled attribute = " + elem.getAttribute("disabled") + " expected \"\"");
637     elem.disabled = false;
638     ok(elem.disabled === false, "div.disabled = " + elem.disabled);
639     ok(elem.getAttribute("disabled") === null, "disabled attribute = " + elem.getAttribute("disabled") + " expected null");
641     elem.setAttribute("disabled", "false");
642     ok(elem.disabled === true, "div.disabled = " + elem.disabled);
643     ok(elem.getAttribute("disabled") === "false", "disabled attribute = " + elem.getAttribute("disabled"));
645     elem.removeAttribute("disabled");
646     ok(elem.disabled === false, "div.disabled = " + elem.disabled);
647     ok(elem.getAttribute("disabled") === null, "disabled attribute = " + elem.getAttribute("disabled") + " expected null");
650 sync_test("hasAttribute", function() {
651     document.body.innerHTML = '<div attr="test"></div>';
652     var elem = document.body.firstChild, r;
654     r = elem.hasAttribute("attr");
655     ok(r === true, "hasAttribute(attr) returned " + r);
656     r = elem.hasAttribute("attr2");
657     ok(r === false, "hasAttribute(attr2) returned " + r);
659     elem.setAttribute("attr2", "abc");
660     r = elem.hasAttribute("attr2");
661     ok(r === true, "hasAttribute(attr2) returned " + r);
663     elem.removeAttribute("attr");
664     r = elem.hasAttribute("attr");
665     ok(r === false, "hasAttribute(attr) returned " + r);
668 sync_test("classList", function() {
669     var elem = document.createElement("div");
670     var classList = elem.classList, i, r;
672     var props = [ "add", "contains", "item", "length", "remove", "toggle" ];
673     for(i = 0; i < props.length; i++)
674         ok(props[i] in classList, props[i] + " not found in classList.");
676     props = [ "entries", "forEach", "keys", "replace", "supports", "value", "values"];
677     for(i = 0; i < props.length; i++)
678         ok(!(props[i] in classList), props[i] + " found in classList.");
680     classList.add("a");
681     ok(elem.className === "a", "Expected className 'a', got " + elem.className);
682     ok(classList.length === 1, "Expected length 1 for className 'a', got " + classList.length);
684     classList.add("b");
685     ok(elem.className === "a b", "Expected className 'a b', got " + elem.className);
686     ok(classList.length === 2, "Expected length 2 for className 'a b', got " + classList.length);
688     classList.add("c");
689     ok(elem.className === "a b c", "Expected className 'a b c', got " + elem.className);
690     ok(classList.length === 3, "Expected length 3 for className 'a b c', got " + classList.length);
692     classList.add(4);
693     ok(elem.className === "a b c 4", "Expected className 'a b c 4', got " + elem.className);
694     ok(classList.length === 4, "Expected length 4 for className 'a b c 4', got " + classList.length);
696     classList.add("c");
697     ok(elem.className === "a b c 4", "(2) Expected className 'a b c 4', got " + elem.className);
698     ok(("" + classList) === "a b c 4", "Expected classList value 'a b c 4', got " + classList);
699     ok(classList.toString() === "a b c 4", "Expected classList toString 'a b c 4', got " + classList.toString());
701     var exception = false
703     try
704     {
705         classList.add();
706     }
707     catch(e)
708     {
709         exception = true;
710     }
711     ok(exception && elem.className === "a b c 4", "Expected exception, className 'a b c 4', got exception "
712             + exception + ", className" + elem.className);
714     exception = false
715     try
716     {
717         classList.add("");
718     }
719     catch(e)
720     {
721         exception = true;
722     }
723     ok(exception, "Expected exception for classList.add(\"\")");
725     exception = false
726     try
727     {
728         classList.add("e f");
729     }
730     catch(e)
731     {
732         exception = true;
733     }
734     ok(exception, "Expected exception for classList.add(\"e f\")");
736     exception = false;
737     try
738     {
739         classList.contains();
740     }
741     catch(e)
742     {
743         exception = true;
744     }
745     ok(exception, "Expected exception for classList.contains()");
747     exception = false;
748     try
749     {
750         classList.contains("");
751     }
752     catch(e)
753     {
754         exception = true;
755     }
756     ok(exception, "Expected exception for classList.contains(\"\")");
758     exception = false;
759     try
760     {
761         classList.contains("a b");
762     }
763     catch(e)
764     {
765         exception = true;
766     }
767     ok(exception, "Expected exception for classList.contains(\"a b\")");
769     ok(classList.contains("4") === true, "contains: expected '4' to return true");
770     ok(classList.contains("b") === true, "contains: expected 'b' to return true");
771     ok(classList.contains("d") === false, "contains: expected 'd' to return false");
773     r = classList.item(-1);
774     ok(r === null, "item(-1) = " + r);
775     r = classList.item(0);
776     ok(r === "a", "item(0) = " + r);
777     r = classList.item(1);
778     ok(r === "b", "item(1) = " + r);
779     r = classList.item(2);
780     ok(r === "c", "item(2) = " + r);
781     r = classList.item(3);
782     ok(r === "4", "item(3) = " + r);
783     r = classList.item(4);
784     ok(r === null, "item(4) = " + r);
786     classList.remove("e");
787     ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className);
789     exception = false
790     try
791     {
792         classList.remove("e f");
793     }
794     catch(e)
795     {
796         exception = true;
797     }
798     ok(exception, "remove: expected exception for classList.remove(\"e f\")");
800     exception = false
801     try
802     {
803         classList.remove("");
804     }
805     catch(e)
806     {
807         exception = true;
808     }
809     ok(exception, "remove: expected exception for classList.remove(\"\")");
811     classList.remove("d");
812     ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className);
814     classList.remove("c");
815     ok(elem.className === "a b 4", "remove: expected className 'a b 4', got " + elem.className);
817     classList.remove(4);
818     ok(elem.className === "a b", "remove: expected className 'a b', got " + elem.className);
820     classList.remove('a');
821     ok(elem.className === "b", "remove: expected className 'b', got " + elem.className);
823     classList.remove("a");
824     ok(elem.className === "b", "remove (2): expected className 'b', got " + elem.className);
826     classList.remove("b");
827     ok(elem.className === "", "remove: expected className '', got " + elem.className);
829     exception = false;
830     try
831     {
832         classList.toggle();
833     }
834     catch(e)
835     {
836         exception = true;
837     }
838     ok(exception, "Expected exception for classList.toggle()");
840     exception = false;
841     try
842     {
843         classList.toggle("");
844     }
845     catch(e)
846     {
847         exception = true;
848     }
849     ok(exception, "Expected exception for classList.toggle(\"\")");
851     exception = false;
852     try
853     {
854         classList.toggle("a b");
855     }
856     catch(e)
857     {
858         exception = true;
859     }
860     ok(exception, "Expected exception for classList.toggle(\"a b\")");
862     // toggle's second arg is not implemented by IE, and ignored
863     r = classList.toggle("abc");
864     ok(r === true, "toggle('abc') returned " + r);
865     ok(elem.className === "abc", "toggle('abc'): got className " + elem.className);
867     r = classList.toggle("def", false);
868     ok(r === true, "toggle('def', false) returned " + r);
869     ok(elem.className === "abc def", "toggle('def', false): got className " + elem.className);
871     r = classList.toggle("123", 1234);
872     ok(r === true, "toggle('123', 1234) returned " + r);
873     ok(elem.className === "abc def 123", "toggle('123', 1234): got className " + elem.className);
875     r = classList.toggle("def", true);
876     ok(r === false, "toggle('def', true) returned " + r);
877     ok(elem.className === "abc 123", "toggle('def', true): got className " + elem.className);
879     r = classList.toggle("123", null);
880     ok(r === false, "toggle('123', null) returned " + r);
881     ok(elem.className === "abc", "toggle('123', null): got className " + elem.className);
883     elem.className = "  testclass    foobar  ";
884     ok(classList.length === 2, "Expected length 2 for className '  testclass    foobar  ', got " + classList.length);
885     ok(("" + classList) === "  testclass    foobar  ", "Expected classList value '  testclass    foobar  ', got " + classList);
886     ok(classList.toString() === "  testclass    foobar  ", "Expected classList toString '  testclass    foobar  ', got " + classList.toString());
888     r = classList[-1];
889     ok(r === null, "classList[-1] = " + r);
890     r = classList[0];
891     ok(r === "testclass", "classList[0] = " + r);
892     r = classList[1];
893     ok(r === "foobar", "classList[1] = " + r);
894     r = classList[2];
895     ok(r === null, "classList[2] = " + r);
897     classList[0] = "barfoo";
898     classList[2] = "added";
899     ok(classList.toString() === "  testclass    foobar  ", "Expected classList toString to not be changed after setting indexed props, got " + classList.toString());
901     try
902     {
903         classList[0]();
904         ok(false, "Expected exception calling classList[0]");
905     }
906     catch(e)
907     {
908         ok(e.number === 0xa138a - 0x80000000, "Calling classList[0] threw " + e.number);
909     }
911     try
912     {
913         new classList[0]();
914         ok(false, "Expected exception calling classList[0] as constructor");
915     }
916     catch(e)
917     {
918         ok(e.number === 0xa01bd - 0x80000000, "Calling classList[0] as constructor threw " + e.number);
919     }
922 sync_test("importNode", function() {
923     var node, node2, orig_node, doc = document.implementation.createHTMLDocument("TestDoc");
924     doc.body.innerHTML = '<div id="test"><span/></div>';
925     orig_node = doc.getElementById("test");
927     node = document.importNode(orig_node, false);
928     ok(node !== orig_node, "node = orig_node");
929     ok(orig_node.hasChildNodes() === true, "orig_node does not have child nodes");
930     ok(orig_node.parentNode === doc.body, "orig_node.parentNode = " + orig_node.parentNode);
931     ok(node.hasChildNodes() === false, "node has child nodes with shallow import");
932     ok(node.parentNode === null, "node.parentNode = " + node.parentNode);
934     node = document.importNode(orig_node, true);
935     ok(node !== orig_node, "node = orig_node");
936     ok(orig_node.hasChildNodes() === true, "orig_node does not have child nodes");
937     ok(orig_node.parentNode === doc.body, "orig_node.parentNode = " + orig_node.parentNode);
938     ok(node.hasChildNodes() === true, "node does not have child nodes with deep import");
939     ok(node.parentNode === null, "node.parentNode = " + node.parentNode);
941     node2 = document.importNode(node, false);
942     ok(node !== node2, "node = node2");
943     ok(node.hasChildNodes() === true, "node does not have child nodes");
944     ok(node.parentNode === null, "node.parentNode = " + node.parentNode);
945     ok(node2.hasChildNodes() === false, "node2 has child nodes");
946     ok(node2.parentNode === null, "node2.parentNode = " + node2.parentNode);