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