2 * Copyright 2017 Jacek Caban for CodeWeavers
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.
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.
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
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");
26 sync_test("input_selection", function() {
27 var input = document.createElement("input");
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);
39 input.selectionStart = 2;
42 input.selectionStart = -1;
45 input.selectionStart = 10;
48 input.selectionEnd = 2;
51 input.selectionEnd = -1;
54 input.selectionEnd = 10;
57 input.setSelectionRange(2, 3);
60 input.setSelectionRange(-1, 10);
63 input.setSelectionRange(3, 3);
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);
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);
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);
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());
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);
155 iframe.src = "empty/file";
159 sync_test("anchor", function() {
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" },
170 protocol: "ftp:", host: "", path: "path" },
171 { href: "mailto:path",
172 protocol: "mailto:", host: "", path: "path" },
174 protocol: "ws:", host: "", path: "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" },
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);
196 sync_test("getElementsByClassName", function() {
199 document.body.innerHTML = '<div class="class1">'
200 + '<div class="class1"></div>'
201 + '<a id="class1" class="class2"></a>'
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";
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>'
245 + '<script class="class1"></script>';
247 var e = document.querySelector("nomatch");
248 ok(e === null, "e = " + e);
249 e = document.body.querySelector("nomatch");
250 ok(e === null, "e = " + e);
252 e = document.querySelector(".class1");
253 ok(e.tagName === "DIV", "e.tagName = " + e.tagName);
254 e = document.body.querySelector(".class1");
255 ok(e.tagName === "DIV", "e.tagName = " + e.tagName);
256 ok(e.msMatchesSelector(".class1") === true, "msMatchesSelector returned " + e.msMatchesSelector(".class1"));
257 ok(e.msMatchesSelector(".class2") === false, "msMatchesSelector returned " + e.msMatchesSelector(".class2"));
259 e = document.querySelector("a");
260 ok(e.tagName === "A", "e.tagName = " + e.tagName);
261 e = document.body.querySelector("a");
262 ok(e.tagName === "A", "e.tagName = " + e.tagName);
265 sync_test("compare_position", function() {
266 document.body.innerHTML = '<div><div></div><div></div></div>';
268 var parent = document.body.firstChild;
269 var child1 = parent.firstChild;
270 var child2 = child1.nextSibling;
271 var elem = document.createElement("div");
273 function compare_position(node1, node2, expected_result, ignore_mask) {
274 var cmp = node1.compareDocumentPosition(node2);
275 ok((cmp & ~ignore_mask) == expected_result,
276 "compareDocumentPosition returned " + cmp + " expected " + expected_result);
279 compare_position(child1, child2, 4);
280 compare_position(child2, child1, 2);
281 compare_position(parent, child1, 0x14);
282 compare_position(parent, child2, 0x14);
283 compare_position(parent, elem, 0x21, 6);
284 compare_position(elem, parent, 0x21, 6);
287 sync_test("rects", function() {
288 document.body.innerHTML = '<div>test</div>';
289 var elem = document.body.firstChild;
290 var rects = elem.getClientRects();
291 var rect = elem.getBoundingClientRect();
293 ok(rects.length === 1, "rect.length = " + rects.length);
294 ok(rects[0].top === rect.top, "rects[0].top = " + rects[0].top + " rect.top = " + rect.top);
295 ok(rects[0].bottom === rect.bottom, "rects[0].bottom = " + rects[0].bottom + " rect.bottom = " + rect.bottom);
296 ok(rect.height === rect.bottom - rect.top, "rect.height = " + rect.height + " rect.bottom = " + rect.bottom + " rect.top = " + rect.top);
297 ok(rect.width === rect.right - rect.left, "rect.width = " + rect.width + " rect.right = " + rect.right + " rect.left = " + rect.left);
299 elem = document.createElement("style");
300 rects = elem.getClientRects();
301 ok(rects.length === 0, "rect.length = " + rects.length);
304 sync_test("document_owner", function() {
307 ok(document.ownerDocument === null, "ownerDocument = " + document.ownerDocument);
308 ok(document.body.ownerDocument === document,
309 "body.ownerDocument = " + document.body.ownerDocument);
310 ok(document.documentElement.ownerDocument === document,
311 "documentElement.ownerDocument = " + document.documentElement.ownerDocument);
313 node = document.createElement("test");
314 ok(node.ownerDocument === document, "element.ownerDocument = " + node.ownerDocument);
316 node = document.createDocumentFragment();
317 ok(node.ownerDocument === document, "fragment.ownerDocument = " + node.ownerDocument);
319 node = document.createTextNode("test");
320 ok(node.ownerDocument === document, "text.ownerDocument = " + node.ownerDocument);
323 sync_test("style_properties", function() {
324 document.body.innerHTML = '<div>test</div><svg></svg>';
325 var elem = document.body.firstChild;
326 var style = elem.style;
327 var current_style = elem.currentStyle;
328 var computed_style = window.getComputedStyle(elem);
331 style.cssFloat = "left";
332 ok(style.cssFloat === "left", "cssFloat = " + style.cssFloat);
333 ok(style.getPropertyValue("float") === "left",
334 'style.getPropertyValue("float") = ' + style.getPropertyValue("float"));
335 ok(style.getPropertyValue("cssFloat") === "",
336 'style.getPropertyValue("cssFloat") = ' + style.getPropertyValue("cssFloat"));
338 val = style.removeProperty("float");
339 ok(val === "left", "removeProperty() returned " + val);
340 ok(style.cssFloat === "", "cssFloat = " + style.cssFloat);
342 style.cssFloat = "left";
343 val = style.removeProperty("FloaT");
344 ok(val === "left", "removeProperty() returned " + val);
345 ok(style.cssFloat === "", "cssFloat = " + style.cssFloat);
347 style.cssFloat = "left";
348 val = style.removeProperty("cssFloat");
349 ok(val === "", "removeProperty() returned " + val);
350 ok(style.cssFloat === "left", "cssFloat = " + style.cssFloat);
351 ok(style["float"] === "left", "float = " + style["float"]);
353 style.testVal = "test";
354 val = style.removeProperty("testVal");
355 ok(val === "", "removeProperty() returned " + val);
356 ok(style.testVal === "test", "testVal = " + style.testVal);
358 style["z-index"] = 1;
359 ok(style.zIndex === 1, "zIndex = " + style.zIndex);
360 ok(style["z-index"] === 1, "z-index = " + style["z-index"]);
361 ok(style.getPropertyValue("z-index") === "1",
362 'style.getPropertyValue("x-index") = ' + style.getPropertyValue("z-index"));
363 ok(style.getPropertyValue("zIndex") === "",
364 'style.getPropertyValue("xIndex") = ' + style.getPropertyValue("zIndex"));
366 style.setProperty("border-width", "5px");
367 ok(style.borderWidth === "5px", "style.borderWidth = " + style.borderWidth);
370 style.setProperty("border-width", 6);
371 ok(style.borderWidth === "5px", "style.borderWidth = " + style.borderWidth);
373 win_skip("skipping setProperty tests on too old IE version");
377 style.setProperty("border-width", "7px", "test");
378 ok(style.borderWidth === "5px", "style.borderWidth = " + style.borderWidth);
380 style.setProperty("border-width", "6px", "");
381 ok(style.borderWidth === "6px", "style.borderWidth = " + style.borderWidth);
383 style.setProperty("border-width", "7px", "important");
384 ok(style.borderWidth === "7px", "style.borderWidth = " + style.borderWidth);
386 style.setProperty("border-width", "8px", undefined);
387 ok(style.borderWidth === "7px", "style.borderWidth = " + style.borderWidth);
389 style.clip = "rect(1px 1px 10px 10px)";
390 ok(style.clip === "rect(1px, 1px, 10px, 10px)", "style.clip = " + style.clip);
391 ok(current_style.clip === "rect(1px, 1px, 10px, 10px)",
392 "current_style.clip = " + current_style.clip);
393 ok(computed_style.clip === "rect(1px, 1px, 10px, 10px)",
394 "computed_style.clip = " + current_style.clip);
397 ok(current_style.zIndex === 2, "current_style.zIndex = " + current_style.zIndex);
398 ok(computed_style.zIndex === 2, "computed_style.zIndex = " + computed_style.zIndex);
401 current_style.zIndex = 1;
402 ok(false, "expected exception");
406 computed_style.zIndex = 1;
407 ok(false, "expected exception");
410 elem = elem.nextSibling;
411 computed_style = window.getComputedStyle(elem);
413 elem.style.zIndex = 4;
414 ok(computed_style.zIndex === 4, "computed_style.zIndex = " + computed_style.zIndex);
416 window.getComputedStyle(elem, null);
419 sync_test("stylesheets", function() {
420 document.body.innerHTML = '<style>.div { margin-right: 1px; }</style>';
421 var elem = document.body.firstChild;
423 ok(document.styleSheets.length === 1, "document.styleSheets.length = " + document.styleSheets.length);
425 var stylesheet = document.styleSheets.item(0);
426 ok(stylesheet.rules.length === 1, "stylesheet.rules.length = " + stylesheet.rules.length);
427 ok(typeof(stylesheet.rules.item(0)) === "object",
428 "typeof(stylesheet.rules.item(0)) = " + typeof(stylesheet.rules.item(0)));
430 stylesheet = document.styleSheets[0];
431 ok(stylesheet.rules.length === 1, "document.styleSheets[0].rules.length = " + stylesheet.rules.length);
434 stylesheet.rules.item(1);
435 ok(false, "expected exception");
438 ok(stylesheet.href === null, "stylesheet.href = " + stylesheet.href);
440 var id = stylesheet.insertRule(".input { margin-left: 1px; }", 0);
441 ok(id === 0, "id = " + id);
442 ok(document.styleSheets.length === 1, "document.styleSheets.length = " + document.styleSheets.length);
445 stylesheet.insertRule(".input { margin-left: 1px; }", 3);
446 ok(false, "expected exception");
449 id = stylesheet.addRule(".p", "margin-top: 2px");
450 ok(id === 2, "id = " + id);
451 ok(document.styleSheets.length === 1, "document.styleSheets.length = " + document.styleSheets.length);
452 ok(stylesheet.rules.length === 3, "stylesheet.rules.length = " + stylesheet.rules.length);
454 id = stylesheet.addRule(".pre", "border: none", -1);
455 ok(id === 3, "id = " + id);
456 ok(stylesheet.rules.length === 4, "stylesheet.rules.length = " + stylesheet.rules.length);
458 id = stylesheet.addRule(".h1", " ", 0);
459 ok(id === 0, "id = " + id);
460 ok(stylesheet.rules.length === 5, "stylesheet.rules.length = " + stylesheet.rules.length);
462 id = stylesheet.addRule(".h2", "color: black", 8);
463 ok(id === 5, "id = " + id);
464 ok(stylesheet.rules.length === 6, "stylesheet.rules.length = " + stylesheet.rules.length);
467 stylesheet.addRule("", "border: none", 0);
468 ok(false, "expected exception");
471 stylesheet.addRule(".img", "", 0);
472 ok(false, "expected exception");
476 sync_test("storage", function() {
477 ok(typeof(window.sessionStorage) === "object",
478 "typeof(window.sessionStorage) = " + typeof(window.sessionStorage));
479 ok(typeof(window.localStorage) === "object" || typeof(window.localStorage) === "unknown",
480 "typeof(window.localStorage) = " + typeof(window.localStorage));
482 var item = sessionStorage.getItem("nonexisting");
483 ok(item === null, "'nonexisting' item = " + item);
484 item = sessionStorage["nonexisting"];
485 ok(item === undefined, "[nonexisting] item = " + item);
486 ok(!("nonexisting" in sessionStorage), "nonexisting in sessionStorage");
488 sessionStorage.setItem("foobar", 42);
489 ok("foobar" in sessionStorage, "foobar not in sessionStorage");
490 item = sessionStorage.getItem("foobar");
491 ok(item === "42", "'foobar' item = " + item);
492 item = sessionStorage["foobar"];
493 ok(item === "42", "[foobar] item = " + item);
494 sessionStorage.removeItem("foobar");
495 item = sessionStorage["foobar"];
496 ok(item === undefined, "[foobar] item after removal = " + item);
498 sessionStorage["barfoo"] = true;
499 ok("barfoo" in sessionStorage, "barfoo not in sessionStorage");
500 item = sessionStorage["barfoo"];
501 ok(item === "true", "[barfoo] item = " + item);
502 item = sessionStorage.getItem("barfoo");
503 ok(item === "true", "'barfoo' item = " + item);
506 async_test("animation", function() {
507 document.body.innerHTML =
509 " @keyframes testAnimation {0% { opacity: 0; } 100% { opacity: 1; }}" +
510 " .testAnimation { animation-name: testAnimation; animation-duration: 0.01s; }" +
512 var div = document.createElement("div");
513 div.addEventListener("animationstart", function() {
514 div.addEventListener("animationend", next_test);
516 document.body.appendChild(div);
517 div.className = "testAnimation";
520 sync_test("navigator", function() {
521 ok(typeof(window.navigator) === "object",
522 "typeof(window.navigator) = " + typeof(window.navigator));
524 var v = window.navigator;
525 ok(v === window.navigator, "v != window.navigator");
527 ok(window.navigator.testProp, "window.navigator.testProp = " + window.navigator.testProp);
530 sync_test("elem_props", function() {
531 var elem = document.body;
533 ok(elem.accessKey === "", "accessKey = " + elem.accessKey);
534 elem.accessKey = "q";
535 ok(elem.accessKey === "q", "accessKey = " + elem.accessKey + " expected q");
538 async_test("animation_frame", function() {
539 var id = requestAnimationFrame(function(x) { ok(false, "request was supposed to be cancelled"); });
540 id = cancelAnimationFrame(id);
541 ok(id === undefined, "cancelAnimationFrame returned " + id);
543 id = requestAnimationFrame(function(x) {
544 ok(this === window, "this != window");
545 ok(typeof(x) === "number", "x = " + x);
546 ok(arguments.length === 1, "arguments.length = " + arguments.length);
549 cancelAnimationFrame(0);
552 ok(typeof(id) === "number", "id = " + id);
553 ok(id !== 0, "id = 0");
556 sync_test("title", function() {
557 var elem = document.createElement("div");
558 ok(elem.title === "", "div.title = " + elem.title);
559 ok(elem.getAttribute("title") === null, "title attribute = " + elem.getAttribute("title"));
561 ok(elem.title === "test", "div.title = " + elem.title);
562 ok(elem.getAttribute("title") === "test", "title attribute = " + elem.getAttribute("title"));
564 var orig = document.title;
565 document.title = "w i n e test";
566 var title = document.getElementsByTagName("title")[0];
567 ok(title.text === "w i n e test", "<title> element text = " + title.text);
568 title.text = "winetest";
569 ok(title.text === "winetest", "<title> element text after change = " + title.text);
570 ok(document.title === "winetest", "document.title after <title> change = " + document.title);
572 elem = document.createElement("title");
573 ok(elem.text === "", "detached <title> element text = " + elem.text);
574 elem.text = "foobar";
575 ok(elem.text === "foobar", "detached <title> element text after change = " + elem.text);
576 ok(document.title === "winetest", "document.title after detached <title> change = " + document.title);
578 title.parentNode.replaceChild(elem, title);
579 ok(document.title === "foobar", "document.title after <title> replaced = " + document.title);
580 document.title = orig;
583 sync_test("disabled", function() {
584 var elem = document.createElement("div");
585 document.body.appendChild(elem);
586 ok(elem.disabled === false, "div.disabled = " + elem.disabled);
587 ok(elem.getAttribute("disabled") === null, "disabled attribute = " + elem.getAttribute("disabled") + " expected null");
589 elem.disabled = true;
590 ok(elem.disabled === true, "div.disabled = " + elem.disabled);
591 ok(elem.getAttribute("disabled") === "", "disabled attribute = " + elem.getAttribute("disabled") + " expected \"\"");
593 elem.disabled = false;
594 ok(elem.disabled === false, "div.disabled = " + elem.disabled);
595 ok(elem.getAttribute("disabled") === null, "disabled attribute = " + elem.getAttribute("disabled") + " expected null");
597 elem.setAttribute("disabled", "false");
598 ok(elem.disabled === true, "div.disabled = " + elem.disabled);
599 ok(elem.getAttribute("disabled") === "false", "disabled attribute = " + elem.getAttribute("disabled"));
601 elem.removeAttribute("disabled");
602 ok(elem.disabled === false, "div.disabled = " + elem.disabled);
603 ok(elem.getAttribute("disabled") === null, "disabled attribute = " + elem.getAttribute("disabled") + " expected null");
606 sync_test("hasAttribute", function() {
607 document.body.innerHTML = '<div attr="test"></div>';
608 var elem = document.body.firstChild, r;
610 r = elem.hasAttribute("attr");
611 ok(r === true, "hasAttribute(attr) returned " + r);
612 r = elem.hasAttribute("attr2");
613 ok(r === false, "hasAttribute(attr2) returned " + r);
615 elem.setAttribute("attr2", "abc");
616 r = elem.hasAttribute("attr2");
617 ok(r === true, "hasAttribute(attr2) returned " + r);
619 elem.removeAttribute("attr");
620 r = elem.hasAttribute("attr");
621 ok(r === false, "hasAttribute(attr) returned " + r);
624 sync_test("classList", function() {
625 var elem = document.createElement("div");
626 var classList = elem.classList, i;
628 var props = [ "add", "contains", "item", "length", "remove", "toggle" ];
629 for(i = 0; i < props.length; i++)
630 ok(props[i] in classList, props[i] + " not found in classList.");
632 props = [ "entries", "forEach", "keys", "replace", "supports", "value", "values"];
633 for(i = 0; i < props.length; i++)
634 ok(!(props[i] in classList), props[i] + " found in classList.");
637 ok(elem.className === "a", "Expected className 'a', got " + elem.className);
640 ok(elem.className === "a b", "Expected className 'a b', got " + elem.className);
643 ok(elem.className === "a b c", "Expected className 'a b c', got " + elem.className);
646 ok(elem.className === "a b c 4", "Expected className 'a b c 4', got " + elem.className);
649 ok(elem.className === "a b c 4", "(2) Expected className 'a b c 4', got " + elem.className);
650 ok(("" + classList) === "a b c 4", "Expected classList value 'a b c 4', got " + classList);
651 ok(classList.toString() === "a b c 4", "Expected classList toString 'a b c 4', got " + classList.toString());
653 var exception = false
663 ok(exception && elem.className === "a b c 4", "Expected exception, className 'a b c 4', got exception "
664 + exception + ", className" + elem.className);
675 ok(exception, "Expected exception for classList.add(\"\")");
680 classList.add("e f");
686 ok(exception, "Expected exception for classList.add(\"e f\")");
691 classList.contains();
697 ok(exception, "Expected exception for classList.contains()");
702 classList.contains("");
708 ok(exception, "Expected exception for classList.contains(\"\")");
713 classList.contains("a b");
719 ok(exception, "Expected exception for classList.contains(\"a b\")");
721 ok(classList.contains("4") === true, "contains: expected '4' to return true");
722 ok(classList.contains("b") === true, "contains: expected 'b' to return true");
723 ok(classList.contains("d") === false, "contains: expected 'd' to return false");
725 classList.remove("e");
726 ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className);
731 classList.remove("e f");
737 ok(exception, "remove: expected exception for classList.remove(\"e f\")");
742 classList.remove("");
748 ok(exception, "remove: expected exception for classList.remove(\"\")");
750 classList.remove("d");
751 ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className);
753 classList.remove("c");
754 ok(elem.className === "a b 4", "remove: expected className 'a b 4', got " + elem.className);
757 ok(elem.className === "a b", "remove: expected className 'a b', got " + elem.className);
759 classList.remove('a');
760 ok(elem.className === "b", "remove: expected className 'b', got " + elem.className);
762 classList.remove("a");
763 ok(elem.className === "b", "remove (2): expected className 'b', got " + elem.className);
765 classList.remove("b");
766 ok(elem.className === "", "remove: expected className '', got " + elem.className);
768 elem.className = " testclass foobar ";
769 ok(("" + classList) === " testclass foobar ", "Expected classList value ' testclass foobar ', got " + classList);
770 ok(classList.toString() === " testclass foobar ", "Expected classList toString ' testclass foobar ', got " + classList.toString());
773 sync_test("importNode", function() {
774 var node, node2, orig_node, doc = document.implementation.createHTMLDocument("TestDoc");
775 doc.body.innerHTML = '<div id="test"><span/></div>';
776 orig_node = doc.getElementById("test");
778 node = document.importNode(orig_node, false);
779 ok(node !== orig_node, "node = orig_node");
780 ok(orig_node.hasChildNodes() === true, "orig_node does not have child nodes");
781 ok(orig_node.parentNode === doc.body, "orig_node.parentNode = " + orig_node.parentNode);
782 ok(node.hasChildNodes() === false, "node has child nodes with shallow import");
783 ok(node.parentNode === null, "node.parentNode = " + node.parentNode);
785 node = document.importNode(orig_node, true);
786 ok(node !== orig_node, "node = orig_node");
787 ok(orig_node.hasChildNodes() === true, "orig_node does not have child nodes");
788 ok(orig_node.parentNode === doc.body, "orig_node.parentNode = " + orig_node.parentNode);
789 ok(node.hasChildNodes() === true, "node does not have child nodes with deep import");
790 ok(node.parentNode === null, "node.parentNode = " + node.parentNode);
792 node2 = document.importNode(node, false);
793 ok(node !== node2, "node = node2");
794 ok(node.hasChildNodes() === true, "node does not have child nodes");
795 ok(node.parentNode === null, "node.parentNode = " + node.parentNode);
796 ok(node2.hasChildNodes() === false, "node2 has child nodes");
797 ok(node2.parentNode === null, "node2.parentNode = " + node2.parentNode);