1 <html> 2 <head> 3 <title>Fragment Mutation Tests</title> 4 <script> 5 6 if (window.layoutTestController) 7 layoutTestController.dumpAsText(); 8 9 var log = []; 10 11 function logResult(description, outcome) 12 { 13 log.push({ description: description, outcome: outcome}); 14 } 15 16 function printLog(methodName) 17 { 18 var entries = log.map(function(entry) { 19 return "<li>" + entry.description + ": " + entry.outcome; 20 }); 21 document.body.appendChild(document.createElement("p")).innerHTML = "This test creates a fragment containing three elements: \"B\", \"U\", and \"P\", " + 22 " attempts to " + methodName + " this fragment and studies effects of mutation events on the fragment."; 23 document.body.appendChild(document.createElement("ul")).innerHTML = entries.join("\n"); 24 document.body.appendChild(document.createElement("br")); 25 log = []; 26 } 27 28 function produceNodeNameString(nodes) 29 { 30 var node = nodes.firstChild; 31 var result = ""; 32 while(node) { 33 result += node.nodeName; 34 node = node.nextSibling; 35 } 36 return result; 37 } 38 39 function expectException(code) 40 { 41 return function(stash, exception) { 42 if (!exception) 43 return "FAIL, expected exception with code " + code + ". The resulting fragment was: \"" + produceNodeNameString(stash) + "\"."; 44 45 if (code == exception.code) 46 return "PASS"; 47 return "FAIL, expected exception code: " + code + ", was: " + exception + "."; 48 } 49 } 50 51 function expectNodes(nodes) 52 { 53 return function(stash, exception) { 54 if (exception) 55 return "FAIL, unexpected exception thrown: " + exception; 56 var result = produceNodeNameString(stash); 57 if (nodes == result) 58 return "PASS"; 59 return "FAIL, expected \"" + nodes + "\", was \"" + result + "\"."; 60 }; 61 } 62 63 function testFragment(method, description, mutationHandler, expectation, nonStop) 64 { 65 var once = 0; 66 var logged = 0; 67 var frag = document.createDocumentFragment(); 68 var stash = document.body.appendChild(document.createElement("div")); 69 frag.appendChild(document.createElement("b")); 70 frag.appendChild(document.createElement("u")); 71 frag.appendChild(document.createElement("p")); 72 frag.addEventListener("DOMSubtreeModified", function(evt) 73 { 74 if (!nonStop && once++) 75 return; 76 77 try { 78 mutationHandler(evt, frag, stash); 79 } 80 catch(e) { 81 logResult(description, expectation(stash, e)); 82 logged++; 83 } 84 }, false); 85 86 try { 87 method(stash, frag); 88 } 89 catch(e) { 90 logResult(description, expectation(stash, e)); 91 logged++; 92 } 93 if (!logged) 94 logResult(description, expectation(stash)); 95 document.body.removeChild(stash); 96 } 97 98 function appendChildMethod(object, subject) 99 { 100 object.appendChild(subject); 101 } 102 103 function insertBeforeMethod(object, subject) 104 { 105 object.insertBefore(subject, object.firstChild); 106 } 107 108 function runTest(methodName, method) 109 { 110 var missing = document.body.appendChild(document.createElement("em")); 111 testFragment(method, "Inserting an element in front of the next item in fragment should not affect the result", function(evt, frag) 112 { 113 frag.insertBefore(missing, frag.firstChild); 114 }, expectNodes("BUP")); 115 116 testFragment(method, "Removing next item should not abort iteration", function(evt, frag) 117 { 118 frag.removeChild(frag.firstChild); 119 }, expectNodes("BUP")); 120 121 var extra = document.body.appendChild(document.createElement("em")); 122 testFragment(method, "Appending an element at the end of the fragment should not affect the result", function(evt, frag) 123 { 124 frag.appendChild(extra); 125 }, expectNodes("BUP")); 126 127 testFragment(method, "Continually re-appending removed element to the fragment should eventually throw NOT_FOUND_ERR", function(evt, frag, stash) 128 { 129 stash.insertBefore(frag.lastChild, stash.firstChild); 130 }, expectException(8), true); 131 132 testFragment(method, "Moving next item to become previous sibling of the re-parentee should not result in stack exhaustion", function(evt, frag, stash) 133 { 134 document.body.insertBefore(frag.firstChild, stash); 135 }, expectNodes("BUP")); 136 printLog(methodName); 137 } 138 function runTests() 139 { 140 runTest("appendChild", appendChildMethod); 141 runTest("insertBefore", insertBeforeMethod); 142 } 143 144 </script> 145 </head> 146 <body onload="runTests()"> 147 </body> 148 </html>