attributes.html (35775B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <title>Attributes tests</title> 4 <link rel=help href="https://dom.spec.whatwg.org/#attr"> 5 <link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattribute"> 6 <link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattributens"> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="attributes.js"></script> 10 <script src="productions.js"></script> 11 <div id="log"></div> 12 <span id="test1"></span> 13 <span class="&<>foo"></span> 14 <script> 15 var XML = "http://www.w3.org/XML/1998/namespace" 16 var XMLNS = "http://www.w3.org/2000/xmlns/" 17 18 // toggleAttribute exhaustive tests 19 // Step 1 20 test(function() { 21 var el = document.createElement("foo") 22 for (var i = 0; i < invalid_names.length; i++) { 23 assert_throws_dom( 24 "INVALID_CHARACTER_ERR", 25 function() { el.toggleAttribute(invalid_names[i], true) }, 26 `toggleAttribute("${invalid_names[i]}", true)`); 27 } 28 for (var i = 0; i < invalid_names.length; i++) { 29 assert_throws_dom( 30 "INVALID_CHARACTER_ERR", 31 function() { el.toggleAttribute(invalid_names[i]) }, 32 `toggleAttribute("${invalid_names[i]}")`); 33 } 34 for (var i = 0; i < invalid_names.length; i++) { 35 assert_throws_dom( 36 "INVALID_CHARACTER_ERR", 37 function() { el.toggleAttribute(invalid_names[i], false) }, 38 `toggleAttribute("${invalid_names[i]}", false)`); 39 } 40 }, "When qualifiedName does not match the Name production, an " + 41 "INVALID_CHARACTER_ERR exception is to be thrown. (toggleAttribute)") 42 43 // Step 2 44 test(function() { 45 var el = document.createElement("div") 46 assert_true(el.toggleAttribute("ALIGN")) 47 assert_true(!el.hasAttributeNS("", "ALIGN")) 48 assert_true(el.hasAttributeNS("", "align")) 49 assert_true(el.hasAttribute("align")) 50 assert_true(!el.toggleAttribute("ALIGN")) 51 assert_true(!el.hasAttributeNS("", "ALIGN")) 52 assert_true(!el.hasAttributeNS("", "align")) 53 assert_true(!el.hasAttribute("align")) 54 }, "toggleAttribute should lowercase its name argument (upper case attribute)") 55 test(function() { 56 var el = document.createElement("div") 57 assert_true(el.toggleAttribute("CHEEseCaKe")) 58 assert_true(!el.hasAttributeNS("", "CHEEseCaKe")) 59 assert_true(el.hasAttributeNS("", "cheesecake")) 60 assert_true(el.hasAttribute("cheesecake")) 61 }, "toggleAttribute should lowercase its name argument (mixed case attribute)") 62 63 // Step 3 64 test(function() { 65 var el = document.createElement("foo") 66 var tests = ["xmlns", "xmlns:a", "xmlnsx", "xmlns0"] 67 for (var i = 0; i < tests.length; i++) { 68 assert_true(el.toggleAttribute(tests[i])); 69 assert_true(el.hasAttribute(tests[i])); 70 } 71 }, "toggleAttribute should not throw even when qualifiedName starts with 'xmlns'") 72 73 // Step 4 74 test(function() { 75 var el = document.createElement("foo") 76 for (var i = 0; i < valid_names.length; i++) { 77 assert_true(el.toggleAttribute(valid_names[i])) 78 assert_true(el.hasAttribute(valid_names[i])) 79 assert_true(!el.toggleAttribute(valid_names[i])) 80 assert_true(!el.hasAttribute(valid_names[i])) 81 // Check using force attr 82 assert_true(el.toggleAttribute(valid_names[i], true)) 83 assert_true(el.hasAttribute(valid_names[i])) 84 assert_true(el.toggleAttribute(valid_names[i], true)) 85 assert_true(el.hasAttribute(valid_names[i])) 86 assert_true(!el.toggleAttribute(valid_names[i], false)) 87 assert_true(!el.hasAttribute(valid_names[i])) 88 } 89 }, "Basic functionality should be intact. (toggleAttribute)") 90 91 // Step 5 92 test(function() { 93 var el = document.createElement("foo") 94 el.toggleAttribute("a") 95 el.toggleAttribute("b") 96 el.setAttribute("a", "thing") 97 el.toggleAttribute("c") 98 attributes_are(el, [["a", "thing"], 99 ["b", ""], 100 ["c", ""]]) 101 }, "toggleAttribute should not change the order of previously set attributes.") 102 test(function() { 103 var el = document.createElement("baz") 104 el.setAttributeNS("ab", "attr", "fail") 105 el.setAttributeNS("kl", "attr", "pass") 106 el.toggleAttribute("attr") 107 attributes_are(el, [["attr", "pass", "kl"]]) 108 }, "toggleAttribute should set the first attribute with the given name") 109 test(function() { 110 // Based on a test by David Flanagan. 111 var el = document.createElement("baz") 112 el.setAttributeNS("foo", "foo:bar", "1"); 113 el.setAttributeNS("foo", "foo:bat", "2"); 114 assert_equals(el.getAttribute("foo:bar"), "1") 115 assert_equals(el.getAttribute("foo:bat"), "2") 116 attr_is(el.attributes[0], "1", "bar", "foo", "foo", "foo:bar") 117 attr_is(el.attributes[1], "2", "bat", "foo", "foo", "foo:bat") 118 el.toggleAttribute("foo:bar"); 119 assert_true(!el.hasAttribute("foo:bar")) 120 attr_is(el.attributes[0], "2", "bat", "foo", "foo", "foo:bat") 121 }, "toggleAttribute should set the attribute with the given qualified name") 122 123 test(function() { 124 var el = document.createElement("foo") 125 el.style = "color: red; background-color: green" 126 assert_equals(el.toggleAttribute("style"), false) 127 }, "Toggling element with inline style should make inline style disappear") 128 129 // setAttribute exhaustive tests 130 // Step 1 131 test(function() { 132 var el = document.createElement("foo") 133 for (var i = 0; i < invalid_names.length; i++) { 134 assert_throws_dom("INVALID_CHARACTER_ERR", function() { el.setAttribute(invalid_names[i], "test") }) 135 } 136 }, "When qualifiedName does not match the Name production, an " + 137 "INVALID_CHARACTER_ERR exception is to be thrown. (setAttribute)") 138 139 // Step 2 140 test(function() { 141 var el = document.createElement("div") 142 el.setAttribute("ALIGN", "left") 143 assert_equals(el.getAttributeNS("", "ALIGN"), null) 144 assert_equals(el.getAttributeNS("", "align"), "left") 145 assert_equals(el.getAttribute("align"), "left") 146 }, "setAttribute should lowercase its name argument (upper case attribute)") 147 test(function() { 148 var el = document.createElement("div") 149 el.setAttribute("CHEEseCaKe", "tasty") 150 assert_equals(el.getAttributeNS("", "CHEEseCaKe"), null) 151 assert_equals(el.getAttributeNS("", "cheesecake"), "tasty") 152 assert_equals(el.getAttribute("cheesecake"), "tasty") 153 }, "setAttribute should lowercase its name argument (mixed case attribute)") 154 155 // Step 3 156 test(function() { 157 var el = document.createElement("foo") 158 var tests = ["xmlns", "xmlns:a", "xmlnsx", "xmlns0"] 159 for (var i = 0; i < tests.length; i++) { 160 el.setAttribute(tests[i], "success"); 161 } 162 }, "setAttribute should not throw even when qualifiedName starts with 'xmlns'") 163 164 // Step 4 165 test(function() { 166 var el = document.createElement("foo") 167 for (var i = 0; i < valid_names.length; i++) { 168 el.setAttribute(valid_names[i], "test") 169 assert_equals(el.getAttribute(valid_names[i]), "test") 170 } 171 }, "Basic functionality should be intact.") 172 173 // Step 5 174 test(function() { 175 var el = document.createElement("foo") 176 el.setAttribute("a", "1") 177 el.setAttribute("b", "2") 178 el.setAttribute("a", "3") 179 el.setAttribute("c", "4") 180 attributes_are(el, [["a", "3"], 181 ["b", "2"], 182 ["c", "4"]]) 183 }, "setAttribute should not change the order of previously set attributes.") 184 test(function() { 185 var el = document.createElement("baz") 186 el.setAttributeNS("ab", "attr", "fail") 187 el.setAttributeNS("kl", "attr", "pass") 188 el.setAttribute("attr", "pass") 189 attributes_are(el, [["attr", "pass", "ab"], 190 ["attr", "pass", "kl"]]) 191 }, "setAttribute should set the first attribute with the given name") 192 test(function() { 193 // Based on a test by David Flanagan. 194 var el = document.createElement("baz") 195 el.setAttributeNS("foo", "foo:bar", "1"); 196 assert_equals(el.getAttribute("foo:bar"), "1") 197 attr_is(el.attributes[0], "1", "bar", "foo", "foo", "foo:bar") 198 el.setAttribute("foo:bar", "2"); 199 assert_equals(el.getAttribute("foo:bar"), "2") 200 attr_is(el.attributes[0], "2", "bar", "foo", "foo", "foo:bar") 201 }, "setAttribute should set the attribute with the given qualified name") 202 203 // setAttributeNS exhaustive tests 204 // Step 1 205 test(function() { 206 var el = document.createElement("foo") 207 for (var i = 0, il = invalid_names.length; i < il; ++i) { 208 assert_throws_dom("INVALID_CHARACTER_ERR", 209 function() { el.setAttributeNS("a", invalid_names[i], "fail") }) 210 } 211 }, "When qualifiedName does not match the Name production, an " + 212 "INVALID_CHARACTER_ERR exception is to be thrown. (setAttributeNS)") 213 214 // Step 2 215 test(function() { 216 var el = document.createElement("foo") 217 for (var i = 0, il = invalid_qnames.length; i < il; ++i) { 218 assert_throws_dom("INVALID_CHARACTER_ERR", 219 function() { el.setAttributeNS("a", invalid_qnames[i], "fail") }, 220 "Expected exception for " + invalid_qnames[i] + ".") 221 } 222 }, "When qualifiedName does not match the QName production, an " + 223 "INVALID_CHARACTER_ERR exception is to be thrown.") 224 225 // Step 3 226 test(function() { 227 var el = document.createElement("foo") 228 el.setAttributeNS(null, "aa", "bb") 229 el.setAttributeNS("", "xx", "bb") 230 attributes_are(el, [["aa", "bb"], 231 ["xx", "bb"]]) 232 }, "null and the empty string should result in a null namespace.") 233 234 // Step 4 235 test(function() { 236 var el = document.createElement("foo") 237 assert_throws_dom("NAMESPACE_ERR", 238 function() { el.setAttributeNS("", "aa:bb", "fail") }) 239 assert_throws_dom("NAMESPACE_ERR", 240 function() { el.setAttributeNS(null, "aa:bb", "fail") }) 241 }, "A namespace is required to use a prefix.") 242 243 // Step 5 244 test(function() { 245 var el = document.createElement("foo") 246 assert_throws_dom("NAMESPACE_ERR", 247 function() { el.setAttributeNS("a", "xml:bb", "fail") }) 248 }, "The xml prefix should not be allowed for arbitrary namespaces") 249 test(function() { 250 var el = document.createElement("foo") 251 el.setAttributeNS(XML, "a:bb", "pass") 252 assert_equals(el.attributes.length, 1) 253 attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb") 254 }, "XML-namespaced attributes don't need an xml prefix") 255 256 // Step 6 257 test(function() { 258 var el = document.createElement("foo") 259 assert_throws_dom("NAMESPACE_ERR", 260 function() { el.setAttributeNS("a", "xmlns:bb", "fail") }) 261 }, "The xmlns prefix should not be allowed for arbitrary namespaces") 262 test(function() { 263 var el = document.createElement("foo") 264 assert_throws_dom("NAMESPACE_ERR", 265 function() { el.setAttributeNS("a", "xmlns", "fail") }) 266 }, "The xmlns qualified name should not be allowed for arbitrary namespaces") 267 test(function() { 268 var el = document.createElement("foo") 269 el.setAttributeNS("ns", "a:xmlns", "pass") 270 assert_equals(el.attributes.length, 1) 271 attr_is(el.attributes[0], "pass", "xmlns", "ns", "a", "a:xmlns") 272 }, "xmlns should be allowed as local name") 273 274 // Step 7 275 test(function() { 276 var el = document.createElement("foo") 277 assert_throws_dom("NAMESPACE_ERR", 278 function() { el.setAttributeNS(XMLNS, "a:xmlns", "fail") }) 279 assert_throws_dom("NAMESPACE_ERR", 280 function() { el.setAttributeNS(XMLNS, "b:foo", "fail") }) 281 }, "The XMLNS namespace should require xmlns as prefix or qualified name") 282 test(function() { 283 var el = document.createElement("foo") 284 el.setAttributeNS(XMLNS, "xmlns:a", "pass") 285 assert_equals(el.attributes.length, 1) 286 attr_is(el.attributes[0], "pass", "a", XMLNS, "xmlns", "xmlns:a") 287 }, "xmlns should be allowed as prefix in the XMLNS namespace") 288 test(function() { 289 var el = document.createElement("foo") 290 el.setAttributeNS(XMLNS, "xmlns", "pass") 291 assert_equals(el.attributes.length, 1) 292 attr_is(el.attributes[0], "pass", "xmlns", XMLNS, null, "xmlns") 293 }, "xmlns should be allowed as qualified name in the XMLNS namespace") 294 295 // Step 8-9 296 test(function() { 297 var el = document.createElement("foo") 298 el.setAttributeNS("a", "foo:bar", "X") 299 assert_equals(el.attributes.length, 1) 300 attr_is(el.attributes[0], "X", "bar", "a", "foo", "foo:bar") 301 302 el.setAttributeNS("a", "quux:bar", "Y") 303 assert_equals(el.attributes.length, 1) 304 attr_is(el.attributes[0], "Y", "bar", "a", "foo", "foo:bar") 305 el.removeAttributeNS("a", "bar") 306 }, "Setting the same attribute with another prefix should not change the prefix") 307 308 // Miscellaneous tests 309 test(function() { 310 var el = document.createElement("iframe") 311 el.setAttribute("src", "file:///home") 312 assert_equals(el.getAttribute("src"), "file:///home") 313 }, "setAttribute should not throw even if a load is not allowed") 314 test(function() { 315 var docFragment = document.createDocumentFragment() 316 var newOne = document.createElement("newElement") 317 newOne.setAttribute("newdomestic", "Yes") 318 docFragment.appendChild(newOne) 319 var domesticNode = docFragment.firstChild 320 var attr = domesticNode.attributes.item(0) 321 attr_is(attr, "Yes", "newdomestic", null, null, "newdomestic") 322 }, "Attributes should work in document fragments.") 323 test(function() { 324 var el = document.createElement("foo") 325 el.setAttribute("x", "y") 326 var attr = el.attributes[0] 327 attr.value = "Y<" 328 attr_is(attr, "Y<", "x", null, null, "x") 329 assert_equals(el.getAttribute("x"), "Y<") 330 }, "Attribute values should not be parsed.") 331 test(function() { 332 var el = document.getElementsByTagName("span")[0] 333 attr_is(el.attributes[0], "test1", "id", null, null, "id") 334 }, "Specified attributes should be accessible.") 335 test(function() { 336 var el = document.getElementsByTagName("span")[1] 337 attr_is(el.attributes[0], "&<>foo", "class", null, null, "class") 338 }, "Entities in attributes should have been expanded while parsing.") 339 340 test(function() { 341 var el = document.createElement("div") 342 assert_equals(el.hasAttribute("bar"), false) 343 assert_equals(el.hasAttributeNS(null, "bar"), false) 344 assert_equals(el.hasAttributeNS("", "bar"), false) 345 assert_equals(el.getAttribute("bar"), null) 346 assert_equals(el.getAttributeNS(null, "bar"), null) 347 assert_equals(el.getAttributeNS("", "bar"), null) 348 }, "Unset attributes return null") 349 test(function() { 350 var el = document.createElement("div") 351 el.setAttributeNS("ab", "attr", "t1") 352 el.setAttributeNS("kl", "attr", "t2") 353 assert_equals(el.hasAttribute("attr"), true) 354 assert_equals(el.hasAttributeNS("ab", "attr"), true) 355 assert_equals(el.hasAttributeNS("kl", "attr"), true) 356 assert_equals(el.getAttribute("attr"), "t1") 357 assert_equals(el.getAttributeNS("ab", "attr"), "t1") 358 assert_equals(el.getAttributeNS("kl", "attr"), "t2") 359 assert_equals(el.getAttributeNS(null, "attr"), null) 360 assert_equals(el.getAttributeNS("", "attr"), null) 361 }, "First set attribute is returned by getAttribute") 362 test(function() { 363 var el = document.createElement("div") 364 el.setAttribute("style", "color:#fff;") 365 assert_equals(el.hasAttribute("style"), true) 366 assert_equals(el.hasAttributeNS(null, "style"), true) 367 assert_equals(el.hasAttributeNS("", "style"), true) 368 assert_equals(el.getAttribute("style"), "color:#fff;") 369 assert_equals(el.getAttributeNS(null, "style"), "color:#fff;") 370 assert_equals(el.getAttributeNS("", "style"), "color:#fff;") 371 }, "Style attributes are not normalized") 372 test(function() { 373 var el = document.createElement("div") 374 el.setAttributeNS("", "ALIGN", "left") 375 assert_equals(el.hasAttribute("ALIGN"), false) 376 assert_equals(el.hasAttribute("align"), false) 377 assert_equals(el.hasAttributeNS(null, "ALIGN"), true) 378 assert_equals(el.hasAttributeNS(null, "align"), false) 379 assert_equals(el.hasAttributeNS("", "ALIGN"), true) 380 assert_equals(el.hasAttributeNS("", "align"), false) 381 assert_equals(el.getAttribute("ALIGN"), null) 382 assert_equals(el.getAttribute("align"), null) 383 assert_equals(el.getAttributeNS(null, "ALIGN"), "left") 384 assert_equals(el.getAttributeNS("", "ALIGN"), "left") 385 assert_equals(el.getAttributeNS(null, "align"), null) 386 assert_equals(el.getAttributeNS("", "align"), null) 387 el.removeAttributeNS("", "ALIGN") 388 }, "Only lowercase attributes are returned on HTML elements (upper case attribute)") 389 test(function() { 390 var el = document.createElement("div") 391 el.setAttributeNS("", "CHEEseCaKe", "tasty") 392 assert_equals(el.hasAttribute("CHEESECAKE"), false) 393 assert_equals(el.hasAttribute("CHEEseCaKe"), false) 394 assert_equals(el.hasAttribute("cheesecake"), false) 395 assert_equals(el.hasAttributeNS("", "CHEESECAKE"), false) 396 assert_equals(el.hasAttributeNS("", "CHEEseCaKe"), true) 397 assert_equals(el.hasAttributeNS("", "cheesecake"), false) 398 assert_equals(el.hasAttributeNS(null, "CHEESECAKE"), false) 399 assert_equals(el.hasAttributeNS(null, "CHEEseCaKe"), true) 400 assert_equals(el.hasAttributeNS(null, "cheesecake"), false) 401 assert_equals(el.getAttribute("CHEESECAKE"), null) 402 assert_equals(el.getAttribute("CHEEseCaKe"), null) 403 assert_equals(el.getAttribute("cheesecake"), null) 404 assert_equals(el.getAttributeNS(null, "CHEESECAKE"), null) 405 assert_equals(el.getAttributeNS("", "CHEESECAKE"), null) 406 assert_equals(el.getAttributeNS(null, "CHEEseCaKe"), "tasty") 407 assert_equals(el.getAttributeNS("", "CHEEseCaKe"), "tasty") 408 assert_equals(el.getAttributeNS(null, "cheesecake"), null) 409 assert_equals(el.getAttributeNS("", "cheesecake"), null) 410 el.removeAttributeNS("", "CHEEseCaKe") 411 }, "Only lowercase attributes are returned on HTML elements (mixed case attribute)") 412 test(function() { 413 var el = document.createElement("div") 414 document.body.appendChild(el) 415 el.setAttributeNS("", "align", "left") 416 el.setAttributeNS("xx", "align", "right") 417 el.setAttributeNS("", "foo", "left") 418 el.setAttributeNS("xx", "foo", "right") 419 assert_equals(el.hasAttribute("align"), true) 420 assert_equals(el.hasAttribute("foo"), true) 421 assert_equals(el.hasAttributeNS("xx", "align"), true) 422 assert_equals(el.hasAttributeNS(null, "foo"), true) 423 assert_equals(el.getAttribute("align"), "left") 424 assert_equals(el.getAttribute("foo"), "left") 425 assert_equals(el.getAttributeNS("xx", "align"), "right") 426 assert_equals(el.getAttributeNS(null, "foo"), "left") 427 assert_equals(el.getAttributeNS("", "foo"), "left") 428 el.removeAttributeNS("", "align") 429 el.removeAttributeNS("xx", "align") 430 el.removeAttributeNS("", "foo") 431 el.removeAttributeNS("xx", "foo") 432 document.body.removeChild(el) 433 }, "First set attribute is returned with mapped attribute set first") 434 test(function() { 435 var el = document.createElement("div") 436 el.setAttributeNS("xx", "align", "right") 437 el.setAttributeNS("", "align", "left") 438 el.setAttributeNS("xx", "foo", "right") 439 el.setAttributeNS("", "foo", "left") 440 assert_equals(el.hasAttribute("align"), true) 441 assert_equals(el.hasAttribute("foo"), true) 442 assert_equals(el.hasAttributeNS("xx", "align"), true) 443 assert_equals(el.hasAttributeNS(null, "foo"), true) 444 assert_equals(el.getAttribute("align"), "right") 445 assert_equals(el.getAttribute("foo"), "right") 446 assert_equals(el.getAttributeNS("xx", "align"), "right") 447 assert_equals(el.getAttributeNS(null, "foo"), "left") 448 assert_equals(el.getAttributeNS("", "foo"), "left") 449 el.removeAttributeNS("", "align") 450 el.removeAttributeNS("xx", "align") 451 el.removeAttributeNS("", "foo") 452 el.removeAttributeNS("xx", "foo") 453 }, "First set attribute is returned with mapped attribute set later") 454 455 test(function() { 456 var el = document.createElementNS("http://www.example.com", "foo") 457 el.setAttribute("A", "test") 458 assert_equals(el.hasAttribute("A"), true, "hasAttribute()") 459 assert_equals(el.hasAttributeNS("", "A"), true, "el.hasAttributeNS(\"\")") 460 assert_equals(el.hasAttributeNS(null, "A"), true, "el.hasAttributeNS(null)") 461 assert_equals(el.hasAttributeNS(undefined, "A"), true, "el.hasAttributeNS(undefined)") 462 assert_equals(el.hasAttributeNS("foo", "A"), false, "el.hasAttributeNS(\"foo\")") 463 464 assert_equals(el.getAttribute("A"), "test", "getAttribute()") 465 assert_equals(el.getAttributeNS("", "A"), "test", "el.getAttributeNS(\"\")") 466 assert_equals(el.getAttributeNS(null, "A"), "test", "el.getAttributeNS(null)") 467 assert_equals(el.getAttributeNS(undefined, "A"), "test", "el.getAttributeNS(undefined)") 468 assert_equals(el.getAttributeNS("foo", "A"), null, "el.getAttributeNS(\"foo\")") 469 }, "Non-HTML element with upper-case attribute") 470 471 test(function() { 472 var el = document.createElement("div") 473 el.setAttribute("pre:fix", "value 1") 474 el.setAttribute("fix", "value 2") 475 476 var prefixed = el.attributes[0] 477 assert_equals(prefixed.localName, "pre:fix", "prefixed local name") 478 assert_equals(prefixed.namespaceURI, null, "prefixed namespace") 479 480 var unprefixed = el.attributes[1] 481 assert_equals(unprefixed.localName, "fix", "unprefixed local name") 482 assert_equals(unprefixed.namespaceURI, null, "unprefixed namespace") 483 484 el.removeAttributeNS(null, "pre:fix") 485 assert_equals(el.attributes[0], unprefixed) 486 }, "Attribute with prefix in local name") 487 488 test(function() { 489 var el = document.createElement("div") 490 el.setAttribute("foo", "bar") 491 var attr = el.attributes[0] 492 assert_equals(attr.ownerElement, el) 493 el.removeAttribute("foo") 494 assert_equals(attr.ownerElement, null) 495 }, "Attribute loses its owner when removed") 496 497 test(function() { 498 var el = document.createElement("div") 499 el.setAttribute("foo", "bar") 500 var attr = el.attributes[0] 501 var attrNode = el.getAttributeNode("foo"); 502 var attrNodeNS = el.getAttributeNodeNS("", "foo"); 503 assert_equals(attr, attrNode); 504 assert_equals(attr, attrNodeNS); 505 el.setAttributeNS("x", "foo2", "bar2"); 506 var attr2 = el.attributes[1]; 507 var attrNodeNS2 = el.getAttributeNodeNS("x", "foo2"); 508 assert_equals(attr2, attrNodeNS2); 509 }, "Basic functionality of getAttributeNode/getAttributeNodeNS") 510 511 test(function() { 512 var el = document.createElement("div") 513 el.setAttribute("foo", "bar") 514 var attrNode = el.getAttributeNode("foo"); 515 var attrNodeNS = el.getAttributeNodeNS("", "foo"); 516 assert_equals(attrNode, attrNodeNS); 517 el.removeAttribute("foo"); 518 var el2 = document.createElement("div"); 519 el2.setAttributeNode(attrNode); 520 assert_equals(attrNode, el2.getAttributeNode("foo")); 521 assert_equals(attrNode, el2.attributes[0]); 522 assert_equals(attrNode.ownerElement, el2); 523 assert_equals(attrNode.value, "bar"); 524 525 var el3 = document.createElement("div"); 526 el2.removeAttribute("foo"); 527 el3.setAttribute("foo", "baz"); 528 el3.setAttributeNode(attrNode); 529 assert_equals(el3.getAttribute("foo"), "bar"); 530 }, "Basic functionality of setAttributeNode") 531 532 test(function() { 533 var el = document.createElement("div"); 534 var attr1 = document.createAttributeNS("ns1", "p1:name"); 535 attr1.value = "value1"; 536 var attr2 = document.createAttributeNS("ns2", "p2:name"); 537 attr2.value = "value2"; 538 el.setAttributeNode(attr1); 539 el.setAttributeNode(attr2); 540 assert_equals(el.getAttributeNodeNS("ns1", "name").value, "value1"); 541 assert_equals(el.getAttributeNodeNS("ns2", "name").value, "value2"); 542 }, "setAttributeNode should distinguish attributes with same local name and different namespaces") 543 544 test(function() { 545 var el = document.createElement("div"); 546 var attr1 = document.createAttributeNS("ns1", "p1:name"); 547 attr1.value = "value1"; 548 var attr2 = document.createAttributeNS("ns1", "p1:NAME"); 549 attr2.value = "VALUE2"; 550 el.setAttributeNode(attr1); 551 el.setAttributeNode(attr2); 552 assert_equals(el.getAttributeNodeNS("ns1", "name").value, "value1"); 553 assert_equals(el.getAttributeNodeNS("ns1", "NAME").value, "VALUE2"); 554 }, "setAttributeNode doesn't have case-insensitivity even with an HTMLElement 1") 555 556 test(function() { 557 var el = document.createElement("div"); 558 var attr1 = document.createAttributeNS("ns1", "FOOBAR"); 559 var attr2 = document.createAttributeNS("ns1", "FOOBAR"); 560 assert_equals(el.setAttributeNode(attr1), null); 561 assert_equals(attr1.ownerElement, el); 562 assert_equals(attr2.ownerElement, null); 563 var oldAttr = el.setAttributeNode(attr2); 564 assert_equals(oldAttr, attr1); 565 assert_equals(attr1.ownerElement, null); 566 assert_equals(attr2.ownerElement, el); 567 }, "setAttributeNode doesn't have case-insensitivity even with an HTMLElement 2") 568 569 test(function() { 570 var el = document.createElement("div"); 571 var attr1 = document.createAttributeNS("ns1", "foobar"); 572 var attr2 = document.createAttributeNS("ns1", "FOOBAR"); 573 assert_equals(el.setAttributeNode(attr1), null); 574 assert_equals(attr1.ownerElement, el); 575 assert_equals(attr2.ownerElement, null); 576 assert_equals(el.setAttributeNode(attr2), null); 577 assert_equals(attr1.ownerElement, el); 578 assert_equals(attr2.ownerElement, el); 579 }, "setAttributeNode doesn't have case-insensitivity even with an HTMLElement 3") 580 581 test(function() { 582 var el = document.createElement("div") 583 el.setAttributeNS("x", "foo", "bar") 584 var attrNode = el.getAttributeNodeNS("x", "foo"); 585 el.removeAttribute("foo"); 586 var el2 = document.createElement("div"); 587 el2.setAttributeNS("x", "foo", "baz"); 588 el2.setAttributeNodeNS(attrNode); 589 assert_equals(el2.getAttributeNS("x", "foo"), "bar"); 590 }, "Basic functionality of setAttributeNodeNS") 591 592 test(function() { 593 var el = document.createElement("div"); 594 var other = document.createElement("div"); 595 var attr = document.createAttribute("foo"); 596 assert_equals(el.setAttributeNode(attr), null); 597 assert_equals(attr.ownerElement, el); 598 assert_throws_dom("INUSE_ATTRIBUTE_ERR", 599 function() { other.setAttributeNode(attr) }, 600 "Attribute already associated with el") 601 }, "If attr’s element is neither null nor element, throw an InUseAttributeError."); 602 603 test(function() { 604 var el = document.createElement("div"); 605 var attr = document.createAttribute("foo"); 606 assert_equals(el.setAttributeNode(attr), null); 607 el.setAttribute("bar", "qux"); 608 assert_equals(el.setAttributeNode(attr), attr); 609 assert_equals(el.attributes[0], attr); 610 }, "Replacing an attr by itself"); 611 612 test(function() { 613 var el = document.createElement("div") 614 el.setAttribute("foo", "bar") 615 var attrNode = el.getAttributeNode("foo"); 616 el.removeAttributeNode(attrNode); 617 var el2 = document.createElement("div"); 618 el2.setAttributeNode(attrNode); 619 assert_equals(el2.attributes[0], attrNode); 620 assert_equals(el.attributes.length, 0); 621 }, "Basic functionality of removeAttributeNode") 622 623 test(function() { 624 var el = document.createElement("div") 625 el.setAttribute("foo", "bar") 626 var attrNode = el.getAttributeNode("foo"); 627 var el2 = document.createElement("div"); 628 assert_throws_dom("INUSE_ATTRIBUTE_ERR", function(){el2.setAttributeNode(attrNode)}); 629 }, "setAttributeNode on bound attribute should throw InUseAttributeError") 630 631 // Have to use an async_test to see what a DOMAttrModified listener sees, 632 // because otherwise the event dispatch code will swallow our exceptions. And 633 // we want to make sure this test always happens, even when no mutation events 634 // run. 635 var setAttributeNode_mutation_test = async_test("setAttributeNode, if it fires mutation events, should fire one with the new node when resetting an existing attribute"); 636 637 test(function(){ 638 var el = document.createElement("div") 639 var attrNode1 = document.createAttribute("foo"); 640 attrNode1.value = "bar"; 641 el.setAttributeNode(attrNode1); 642 var attrNode2 = document.createAttribute("foo"); 643 attrNode2.value = "baz"; 644 645 el.addEventListener("DOMAttrModified", function(e) { 646 // If this never gets called, that's OK, I guess. But if it gets called, it 647 // better represent a single modification with attrNode2 as the relatedNode. 648 // We have to do an inner test() call here, because otherwise the exceptions 649 // our asserts trigger will get swallowed by the event dispatch code. 650 setAttributeNode_mutation_test.step(function() { 651 assert_equals(e.attrName, "foo"); 652 assert_equals(e.attrChange, MutationEvent.MODIFICATION); 653 assert_equals(e.prevValue, "bar"); 654 assert_equals(e.newValue, "baz"); 655 assert_equals(e.relatedNode, attrNode2); 656 }); 657 }); 658 659 var oldNode = el.setAttributeNode(attrNode2); 660 assert_equals(oldNode, attrNode1, 661 "Must return the old attr node from a setAttributeNode call"); 662 }, "setAttributeNode, if it fires mutation events, should fire one with the new node when resetting an existing attribute (outer shell)"); 663 setAttributeNode_mutation_test.done(); 664 665 test(function(){ 666 var el = document.createElement("div") 667 el.setAttribute("a", "b"); 668 el.setAttribute("c", "d"); 669 670 assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.name }), 671 ["a", "c"]); 672 assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.value }), 673 ["b", "d"]); 674 675 var attrNode = document.createAttribute("a"); 676 attrNode.value = "e"; 677 el.setAttributeNode(attrNode); 678 679 assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.name }), 680 ["a", "c"]); 681 assert_array_equals(Array.prototype.map.call(el.attributes, function(a) { return a.value }), 682 ["e", "d"]); 683 }, "setAttributeNode called with an Attr that has the same name as an existing one should not change attribute order"); 684 685 test(function() { 686 var el = document.createElement("div"); 687 el.setAttribute("foo", "bar"); 688 assert_equals(el.getAttributeNames().length, 1); 689 assert_equals(el.getAttributeNames()[0], el.attributes[0].name); 690 assert_equals(el.getAttributeNames()[0], "foo"); 691 692 el.removeAttribute("foo"); 693 assert_equals(el.getAttributeNames().length, 0); 694 695 el.setAttribute("foo", "bar"); 696 el.setAttributeNS("", "FOO", "bar"); 697 el.setAttributeNS("dummy1", "foo", "bar"); 698 el.setAttributeNS("dummy2", "dummy:foo", "bar"); 699 assert_equals(el.getAttributeNames().length, 4); 700 assert_equals(el.getAttributeNames()[0], "foo"); 701 assert_equals(el.getAttributeNames()[1], "FOO"); 702 assert_equals(el.getAttributeNames()[2], "foo"); 703 assert_equals(el.getAttributeNames()[3], "dummy:foo"); 704 assert_equals(el.getAttributeNames()[0], el.attributes[0].name); 705 assert_equals(el.getAttributeNames()[1], el.attributes[1].name); 706 assert_equals(el.getAttributeNames()[2], el.attributes[2].name); 707 assert_equals(el.getAttributeNames()[3], el.attributes[3].name); 708 709 el.removeAttributeNS("", "FOO"); 710 assert_equals(el.getAttributeNames().length, 3); 711 assert_equals(el.getAttributeNames()[0], "foo"); 712 assert_equals(el.getAttributeNames()[1], "foo"); 713 assert_equals(el.getAttributeNames()[2], "dummy:foo"); 714 assert_equals(el.getAttributeNames()[0], el.attributes[0].name); 715 assert_equals(el.getAttributeNames()[1], el.attributes[1].name); 716 assert_equals(el.getAttributeNames()[2], el.attributes[2].name); 717 }, "getAttributeNames tests"); 718 719 function getEnumerableOwnProps1(obj) { 720 var arr = []; 721 for (var prop in obj) { 722 if (obj.hasOwnProperty(prop)) { 723 arr.push(prop); 724 } 725 } 726 return arr; 727 } 728 729 function getEnumerableOwnProps2(obj) { 730 return Object.getOwnPropertyNames(obj).filter( 731 function (name) { return Object.getOwnPropertyDescriptor(obj, name).enumerable; }) 732 } 733 734 test(function() { 735 var el = document.createElement("div"); 736 el.setAttribute("a", ""); 737 el.setAttribute("b", ""); 738 assert_array_equals(getEnumerableOwnProps1(el.attributes), 739 ["0", "1"]) 740 assert_array_equals(getEnumerableOwnProps2(el.attributes), 741 ["0", "1"]) 742 assert_array_equals(Object.getOwnPropertyNames(el.attributes), 743 ["0", "1", "a", "b"]) 744 }, "Own property correctness with basic attributes"); 745 746 test(function() { 747 var el = document.createElement("div"); 748 el.setAttributeNS("", "a", ""); 749 el.setAttribute("b", ""); 750 el.setAttributeNS("foo", "a", ""); 751 assert_array_equals(getEnumerableOwnProps1(el.attributes), 752 ["0", "1", "2"]) 753 assert_array_equals(getEnumerableOwnProps2(el.attributes), 754 ["0", "1", "2"]) 755 assert_array_equals(Object.getOwnPropertyNames(el.attributes), 756 ["0", "1", "2", "a", "b"]) 757 for (var propName of Object.getOwnPropertyNames(el.attributes)) { 758 assert_true(el.attributes[propName] instanceof Attr, 759 "el.attributes has an Attr for property name " + propName); 760 } 761 }, "Own property correctness with non-namespaced attribute before same-name namespaced one"); 762 763 test(function() { 764 var el = document.createElement("div"); 765 el.setAttributeNS("foo", "a", ""); 766 el.setAttribute("b", ""); 767 el.setAttributeNS("", "a", ""); 768 assert_array_equals(getEnumerableOwnProps1(el.attributes), 769 ["0", "1", "2"]) 770 assert_array_equals(getEnumerableOwnProps2(el.attributes), 771 ["0", "1", "2"]) 772 assert_array_equals(Object.getOwnPropertyNames(el.attributes), 773 ["0", "1", "2", "a", "b"]) 774 for (var propName of Object.getOwnPropertyNames(el.attributes)) { 775 assert_true(el.attributes[propName] instanceof Attr, 776 "el.attributes has an Attr for property name " + propName); 777 } 778 }, "Own property correctness with namespaced attribute before same-name non-namespaced one"); 779 780 test(function() { 781 var el = document.createElement("div"); 782 el.setAttributeNS("foo", "a:b", ""); 783 el.setAttributeNS("foo", "c:d", ""); 784 el.setAttributeNS("bar", "a:b", ""); 785 assert_array_equals(getEnumerableOwnProps1(el.attributes), 786 ["0", "1", "2"]) 787 assert_array_equals(getEnumerableOwnProps2(el.attributes), 788 ["0", "1", "2"]) 789 assert_array_equals(Object.getOwnPropertyNames(el.attributes), 790 ["0", "1", "2", "a:b", "c:d"]) 791 for (var propName of Object.getOwnPropertyNames(el.attributes)) { 792 assert_true(el.attributes[propName] instanceof Attr, 793 "el.attributes has an Attr for property name " + propName); 794 } 795 }, "Own property correctness with two namespaced attributes with the same name-with-prefix"); 796 797 test(function() { 798 var el = document.createElement("div"); 799 el.setAttributeNS("foo", "A:B", ""); 800 el.setAttributeNS("bar", "c:D", ""); 801 el.setAttributeNS("baz", "e:F", ""); 802 el.setAttributeNS("qux", "g:h", ""); 803 el.setAttributeNS("", "I", ""); 804 el.setAttributeNS("", "j", ""); 805 assert_array_equals(Object.getOwnPropertyNames(el.attributes), 806 ["0", "1", "2", "3", "4", "5", "g:h", "j"]) 807 for (var propName of Object.getOwnPropertyNames(el.attributes)) { 808 assert_true(el.attributes[propName] instanceof Attr, 809 "el.attributes has an Attr for property name " + propName); 810 } 811 }, "Own property names should only include all-lowercase qualified names for an HTML element in an HTML document"); 812 813 test(function() { 814 var el = document.createElementNS("", "div"); 815 el.setAttributeNS("foo", "A:B", ""); 816 el.setAttributeNS("bar", "c:D", ""); 817 el.setAttributeNS("baz", "e:F", ""); 818 el.setAttributeNS("qux", "g:h", ""); 819 el.setAttributeNS("", "I", ""); 820 el.setAttributeNS("", "j", ""); 821 assert_array_equals(Object.getOwnPropertyNames(el.attributes), 822 ["0", "1", "2", "3", "4", "5", "A:B", "c:D", "e:F", "g:h", "I", "j"]) 823 for (var propName of Object.getOwnPropertyNames(el.attributes)) { 824 assert_true(el.attributes[propName] instanceof Attr, 825 "el.attributes has an Attr for property name " + propName); 826 } 827 }, "Own property names should include all qualified names for a non-HTML element in an HTML document"); 828 829 test(function() { 830 var doc = document.implementation.createDocument(null, ""); 831 assert_equals(doc.contentType, "application/xml"); 832 var el = doc.createElementNS("http://www.w3.org/1999/xhtml", "div"); 833 el.setAttributeNS("foo", "A:B", ""); 834 el.setAttributeNS("bar", "c:D", ""); 835 el.setAttributeNS("baz", "e:F", ""); 836 el.setAttributeNS("qux", "g:h", ""); 837 el.setAttributeNS("", "I", ""); 838 el.setAttributeNS("", "j", ""); 839 assert_array_equals(Object.getOwnPropertyNames(el.attributes), 840 ["0", "1", "2", "3", "4", "5", "A:B", "c:D", "e:F", "g:h", "I", "j"]) 841 for (var propName of Object.getOwnPropertyNames(el.attributes)) { 842 assert_true(el.attributes[propName] instanceof Attr, 843 "el.attributes has an Attr for property name " + propName); 844 } 845 }, "Own property names should include all qualified names for an HTML element in a non-HTML document"); 846 </script>