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 |