Node-replaceChild.html (13812B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <title>Node.replaceChild</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <body><a><b></b><c></c></a> 7 <div id="log"></div> 8 <!-- First test shared pre-insertion checks that work similarly for replaceChild 9 and insertBefore --> 10 <script> 11 var insertFunc = Node.prototype.replaceChild; 12 </script> 13 <script src="pre-insertion-validation-notfound.js"></script> 14 <script> 15 // IDL. 16 test(function() { 17 var a = document.createElement("div"); 18 assert_throws_js(TypeError, function() { 19 a.replaceChild(null, null); 20 }); 21 22 var b = document.createElement("div"); 23 assert_throws_js(TypeError, function() { 24 a.replaceChild(b, null); 25 }); 26 assert_throws_js(TypeError, function() { 27 a.replaceChild(null, b); 28 }); 29 }, "Passing null to replaceChild should throw a TypeError.") 30 31 // Step 3. 32 test(function() { 33 var a = document.createElement("div"); 34 var b = document.createElement("div"); 35 var c = document.createElement("div"); 36 assert_throws_dom("NotFoundError", function() { 37 a.replaceChild(b, c); 38 }); 39 40 var d = document.createElement("div"); 41 d.appendChild(b); 42 assert_throws_dom("NotFoundError", function() { 43 a.replaceChild(b, c); 44 }); 45 assert_throws_dom("NotFoundError", function() { 46 a.replaceChild(b, a); 47 }); 48 }, "If child's parent is not the context node, a NotFoundError exception should be thrown"); 49 50 // Step 1. 51 test(function() { 52 var nodes = getNonParentNodes(); 53 54 var a = document.createElement("div"); 55 var b = document.createElement("div"); 56 nodes.forEach(function(node) { 57 assert_throws_dom("HierarchyRequestError", function() { 58 node.replaceChild(a, b); 59 }); 60 }); 61 }, "If the context node is not a node that can contain children, a HierarchyRequestError exception should be thrown") 62 63 // Step 2. 64 test(function() { 65 var a = document.createElement("div"); 66 var b = document.createElement("div"); 67 68 assert_throws_dom("HierarchyRequestError", function() { 69 a.replaceChild(a, a); 70 }); 71 72 a.appendChild(b); 73 assert_throws_dom("HierarchyRequestError", function() { 74 a.replaceChild(a, b); 75 }); 76 77 var c = document.createElement("div"); 78 c.appendChild(a); 79 assert_throws_dom("HierarchyRequestError", function() { 80 a.replaceChild(c, b); 81 }); 82 }, "If node is an inclusive ancestor of the context node, a HierarchyRequestError should be thrown.") 83 84 // Steps 4/5. 85 test(function() { 86 var doc = document.implementation.createHTMLDocument("title"); 87 var doc2 = document.implementation.createHTMLDocument("title2"); 88 assert_throws_dom("HierarchyRequestError", function() { 89 doc.replaceChild(doc2, doc.documentElement); 90 }); 91 92 assert_throws_dom("HierarchyRequestError", function() { 93 doc.replaceChild(doc.createTextNode("text"), doc.documentElement); 94 }); 95 }, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.") 96 97 // Step 6.1. 98 test(function() { 99 var doc = document.implementation.createHTMLDocument("title"); 100 101 var df = doc.createDocumentFragment(); 102 df.appendChild(doc.createElement("a")); 103 df.appendChild(doc.createElement("b")); 104 assert_throws_dom("HierarchyRequestError", function() { 105 doc.replaceChild(df, doc.documentElement); 106 }); 107 108 df = doc.createDocumentFragment(); 109 df.appendChild(doc.createTextNode("text")); 110 assert_throws_dom("HierarchyRequestError", function() { 111 doc.replaceChild(df, doc.documentElement); 112 }); 113 114 df = doc.createDocumentFragment(); 115 df.appendChild(doc.createComment("comment")); 116 df.appendChild(doc.createTextNode("text")); 117 assert_throws_dom("HierarchyRequestError", function() { 118 doc.replaceChild(df, doc.documentElement); 119 }); 120 }, "If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.") 121 test(function() { 122 var doc = document.implementation.createHTMLDocument("title"); 123 doc.removeChild(doc.documentElement); 124 125 var df = doc.createDocumentFragment(); 126 df.appendChild(doc.createElement("a")); 127 df.appendChild(doc.createElement("b")); 128 assert_throws_dom("HierarchyRequestError", function() { 129 doc.replaceChild(df, doc.doctype); 130 }); 131 }, "If the context node is a document (without element children), inserting a DocumentFragment that contains multiple elements should throw a HierarchyRequestError.") 132 133 // Step 6.1. 134 test(function() { 135 // The context node has an element child that is not /child/. 136 var doc = document.implementation.createHTMLDocument("title"); 137 var comment = doc.appendChild(doc.createComment("foo")); 138 assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]); 139 140 var df = doc.createDocumentFragment(); 141 df.appendChild(doc.createElement("a")); 142 assert_throws_dom("HierarchyRequestError", function() { 143 doc.replaceChild(df, comment); 144 }); 145 assert_throws_dom("HierarchyRequestError", function() { 146 doc.replaceChild(df, doc.doctype); 147 }); 148 }, "If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError.") 149 test(function() { 150 // A doctype is following /child/. 151 var doc = document.implementation.createHTMLDocument("title"); 152 var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); 153 doc.removeChild(doc.documentElement); 154 assert_array_equals(doc.childNodes, [comment, doc.doctype]); 155 156 var df = doc.createDocumentFragment(); 157 df.appendChild(doc.createElement("a")); 158 assert_throws_dom("HierarchyRequestError", function() { 159 doc.replaceChild(df, comment); 160 }); 161 }, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.") 162 163 // Step 6.2. 164 test(function() { 165 var doc = document.implementation.createHTMLDocument("title"); 166 var comment = doc.appendChild(doc.createComment("foo")); 167 assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]); 168 169 var a = doc.createElement("a"); 170 assert_throws_dom("HierarchyRequestError", function() { 171 doc.replaceChild(a, comment); 172 }); 173 assert_throws_dom("HierarchyRequestError", function() { 174 doc.replaceChild(a, doc.doctype); 175 }); 176 }, "If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError.") 177 test(function() { 178 var doc = document.implementation.createHTMLDocument("title"); 179 var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); 180 doc.removeChild(doc.documentElement); 181 assert_array_equals(doc.childNodes, [comment, doc.doctype]); 182 183 var a = doc.createElement("a"); 184 assert_throws_dom("HierarchyRequestError", function() { 185 doc.replaceChild(a, comment); 186 }); 187 }, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.") 188 189 // Step 6.3. 190 test(function() { 191 var doc = document.implementation.createHTMLDocument("title"); 192 var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild); 193 assert_array_equals(doc.childNodes, [comment, doc.doctype, doc.documentElement]); 194 195 var doctype = document.implementation.createDocumentType("html", "", ""); 196 assert_throws_dom("HierarchyRequestError", function() { 197 doc.replaceChild(doctype, comment); 198 }); 199 assert_throws_dom("HierarchyRequestError", function() { 200 doc.replaceChild(doctype, doc.documentElement); 201 }); 202 }, "If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError.") 203 test(function() { 204 var doc = document.implementation.createHTMLDocument("title"); 205 var comment = doc.appendChild(doc.createComment("foo")); 206 doc.removeChild(doc.doctype); 207 assert_array_equals(doc.childNodes, [doc.documentElement, comment]); 208 209 var doctype = document.implementation.createDocumentType("html", "", ""); 210 assert_throws_dom("HierarchyRequestError", function() { 211 doc.replaceChild(doctype, comment); 212 }); 213 }, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.") 214 215 // Steps 4/5. 216 test(function() { 217 var df = document.createDocumentFragment(); 218 var a = df.appendChild(document.createElement("a")); 219 220 var doc = document.implementation.createHTMLDocument("title"); 221 assert_throws_dom("HierarchyRequestError", function() { 222 df.replaceChild(doc, a); 223 }); 224 225 var doctype = document.implementation.createDocumentType("html", "", ""); 226 assert_throws_dom("HierarchyRequestError", function() { 227 df.replaceChild(doctype, a); 228 }); 229 }, "If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError.") 230 test(function() { 231 var el = document.createElement("div"); 232 var a = el.appendChild(document.createElement("a")); 233 234 var doc = document.implementation.createHTMLDocument("title"); 235 assert_throws_dom("HierarchyRequestError", function() { 236 el.replaceChild(doc, a); 237 }); 238 239 var doctype = document.implementation.createDocumentType("html", "", ""); 240 assert_throws_dom("HierarchyRequestError", function() { 241 el.replaceChild(doctype, a); 242 }); 243 }, "If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError.") 244 245 // Step 6. 246 test(function() { 247 var a = document.createElement("div"); 248 var b = document.createElement("div"); 249 var c = document.createElement("div"); 250 a.appendChild(b); 251 a.appendChild(c); 252 assert_array_equals(a.childNodes, [b, c]); 253 assert_equals(a.replaceChild(c, b), b); 254 assert_array_equals(a.childNodes, [c]); 255 }, "Replacing a node with its next sibling should work (2 children)"); 256 test(function() { 257 var a = document.createElement("div"); 258 var b = document.createElement("div"); 259 var c = document.createElement("div"); 260 var d = document.createElement("div"); 261 var e = document.createElement("div"); 262 a.appendChild(b); 263 a.appendChild(c); 264 a.appendChild(d); 265 a.appendChild(e); 266 assert_array_equals(a.childNodes, [b, c, d, e]); 267 assert_equals(a.replaceChild(d, c), c); 268 assert_array_equals(a.childNodes, [b, d, e]); 269 }, "Replacing a node with its next sibling should work (4 children)"); 270 test(function() { 271 var a = document.createElement("div"); 272 var b = document.createElement("div"); 273 var c = document.createElement("div"); 274 a.appendChild(b); 275 a.appendChild(c); 276 assert_array_equals(a.childNodes, [b, c]); 277 assert_equals(a.replaceChild(b, b), b); 278 assert_array_equals(a.childNodes, [b, c]); 279 assert_equals(a.replaceChild(c, c), c); 280 assert_array_equals(a.childNodes, [b, c]); 281 }, "Replacing a node with itself should not move the node"); 282 283 // Step 7. 284 test(function() { 285 var doc = document.implementation.createHTMLDocument("title"); 286 var doctype = doc.doctype; 287 assert_array_equals(doc.childNodes, [doctype, doc.documentElement]); 288 289 var doc2 = document.implementation.createHTMLDocument("title2"); 290 var doctype2 = doc2.doctype; 291 assert_array_equals(doc2.childNodes, [doctype2, doc2.documentElement]); 292 293 doc.replaceChild(doc2.doctype, doc.doctype); 294 assert_array_equals(doc.childNodes, [doctype2, doc.documentElement]); 295 assert_array_equals(doc2.childNodes, [doc2.documentElement]); 296 assert_equals(doctype.parentNode, null); 297 assert_equals(doctype.ownerDocument, doc); 298 assert_equals(doctype2.parentNode, doc); 299 assert_equals(doctype2.ownerDocument, doc); 300 }, "If the context node is a document, inserting a new doctype should work.") 301 302 // Bugs. 303 test(function() { 304 var doc = document.implementation.createHTMLDocument("title"); 305 var df = doc.createDocumentFragment(); 306 var a = df.appendChild(doc.createElement("a")); 307 assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement)); 308 assert_array_equals(doc.childNodes, [doc.doctype, a]); 309 }, "Replacing the document element with a DocumentFragment containing a single element should work."); 310 test(function() { 311 var doc = document.implementation.createHTMLDocument("title"); 312 var df = doc.createDocumentFragment(); 313 var a = df.appendChild(doc.createComment("a")); 314 var b = df.appendChild(doc.createElement("b")); 315 var c = df.appendChild(doc.createComment("c")); 316 assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement)); 317 assert_array_equals(doc.childNodes, [doc.doctype, a, b, c]); 318 }, "Replacing the document element with a DocumentFragment containing a single element and comments should work."); 319 test(function() { 320 var doc = document.implementation.createHTMLDocument("title"); 321 var a = doc.createElement("a"); 322 assert_equals(doc.documentElement, doc.replaceChild(a, doc.documentElement)); 323 assert_array_equals(doc.childNodes, [doc.doctype, a]); 324 }, "Replacing the document element with a single element should work."); 325 test(function() { 326 document.addEventListener("DOMNodeRemoved", function(e) { 327 document.body.appendChild(document.createElement("x")); 328 }, false); 329 var a = document.body.firstChild, b = a.firstChild, c = b.nextSibling; 330 assert_equals(a.replaceChild(c, b), b); 331 assert_equals(b.parentNode, null); 332 assert_equals(a.firstChild, c); 333 assert_equals(c.parentNode, a); 334 }, "replaceChild should work in the presence of mutation events.") 335 test(function() { 336 var TEST_ID = "findme"; 337 var gBody = document.getElementsByTagName("body")[0]; 338 var parent = document.createElement("div"); 339 gBody.appendChild(parent); 340 var child = document.createElement("div"); 341 parent.appendChild(child); 342 var df = document.createDocumentFragment(); 343 var fragChild = df.appendChild(document.createElement("div")); 344 fragChild.setAttribute("id", TEST_ID); 345 parent.replaceChild(df, child); 346 assert_equals(document.getElementById(TEST_ID), fragChild, "should not be null"); 347 }, "Replacing an element with a DocumentFragment should allow a child of the DocumentFragment to be found by Id.") 348 349 </script>