manualtest.js (7929B)
1 // Initial setup 2 //@{ 3 var globalValue; 4 if (globalValue === undefined) { 5 globalValue = command in defaultValues ? defaultValues[command] : ""; 6 } 7 var keyPrefix = globalValue == "" 8 ? "manualtest-" + command + "-" 9 : "manualtest-" + command + "-" + globalValue + "-"; 10 (function(){ 11 var manualTests = tests[command] 12 .map(function(test) { return normalizeTest(command, test) }) 13 .filter(function(test) { return test[1][1] == globalValue }); 14 var relevantMultiTests = tests.multitest 15 .map(function(test) { return normalizeTest("multitest", test) }) 16 .filter(function(test) { 17 // We only want multitests if there's exactly one occurrence of the 18 // command we're testing for, and the value is correct, and that's 19 // the last command we're testing. Some of these limitations could 20 // be removed in the future. 21 return test[test.length - 1][0] === command 22 && test[test.length - 1][1] === globalValue; 23 }); 24 25 tests = manualTests.concat(relevantMultiTests); 26 })(); 27 //@} 28 29 function clearCachedResults() { 30 //@{ 31 for (var key in localStorage) { 32 if (key.indexOf(keyPrefix) === 0) { 33 localStorage.removeItem(key); 34 } 35 } 36 } 37 //@} 38 39 var numManualTests = 0; 40 var currentTestIdx = null; 41 42 // Make sure styleWithCss is always reset to false at the start of a test run 43 // (I'm looking at you, Firefox) 44 try { document.execCommand("stylewithcss", false, "false") } catch(e) {} 45 46 function runTests() { 47 //@{ 48 // We don't ask the user to hit a key on all tests, so make sure not to 49 // claim more tests are going to be run than actually are. 50 for (var i = 0; i < tests.length; i++) { 51 if (localStorage.getItem(keyPrefix + JSON.stringify(tests[i])) === null) { 52 numManualTests++; 53 } 54 } 55 56 currentTestIdx = 0; 57 58 var runTestsButton = document.querySelector("#tests input[type=button]"); 59 runTestsButton.parentNode.removeChild(runTestsButton); 60 61 var addTestButton = document.querySelector("#tests input[type=button]"); 62 var input = document.querySelector("#tests label input"); 63 // This code actually focuses and clicks everything because for some 64 // reason, anything else doesn't work in IE9 . . . 65 input.value = JSON.stringify(tests[0]); 66 input.focus(); 67 addTestButton.click(); 68 } 69 //@} 70 71 function addTest() { 72 //@{ 73 var tr = doSetup("#tests table", 0); 74 var input = document.querySelector("#tests label input"); 75 var test = JSON.parse(input.value); 76 doInputCell(tr, test, test.length == 2 ? command : "multitest"); 77 doSpecCell(tr, test, test.length == 2 ? command : "multitest"); 78 if (localStorage.getItem(keyPrefix + JSON.stringify(test)) !== null) { 79 // Yay, I get to cheat. Remove the overlay div so the user doesn't 80 // keep hitting the key, in case it takes a while. 81 var browserCell = document.createElement("td"); 82 tr.appendChild(browserCell); 83 browserCell.innerHTML = localStorage[keyPrefix + JSON.stringify(test)]; 84 doBrowserCellButton(browserCell, test); 85 document.getElementById("overlay").style.display = ""; 86 doSameCell(tr); 87 runNextTest(test); 88 } else { 89 doBrowserCell(tr, test, function() { 90 doSameCell(tr); 91 runNextTest(); 92 }); 93 } 94 } 95 //@} 96 97 function runNextTest() { 98 //@{ 99 doTearDown(); 100 var input = document.querySelector("#tests label input"); 101 if (currentTestIdx === null 102 || currentTestIdx + 1 >= tests.length) { 103 currentTestIdx = null; 104 document.getElementById("overlay").style.display = ""; 105 input.value = ""; 106 return; 107 } 108 currentTestIdx++; 109 input.value = JSON.stringify(tests[currentTestIdx]); 110 input.focus(); 111 addTest(); 112 } 113 //@} 114 115 function doBrowserCell(tr, test, callback) { 116 //@{ 117 var browserCell = document.createElement("td"); 118 tr.appendChild(browserCell); 119 120 try { 121 var points = setupCell(browserCell, test[0]); 122 123 var testDiv = browserCell.firstChild; 124 // Work around weird Firefox bug: 125 // https://bugzilla.mozilla.org/show_bug.cgi?id=649138 126 document.body.appendChild(testDiv); 127 testDiv.onkeyup = function() { 128 continueBrowserCell(test, testDiv, browserCell); 129 callback(); 130 }; 131 testDiv.contentEditable = "true"; 132 testDiv.spellcheck = false; 133 if (currentTestIdx === null) { 134 document.getElementById("testcount").style.display = "none"; 135 } else { 136 document.getElementById("testcount").style.display = ""; 137 document.querySelector("#testcount > span").textContent = numManualTests; 138 numManualTests--; 139 } 140 document.getElementById("overlay").style.display = "block"; 141 testDiv.focus(); 142 setSelection(points[0], points[1], points[2], points[3]); 143 // Execute any extra commands beforehand, for multitests 144 for (var i = 1; i < test.length - 1; i++) { 145 document.execCommand(test[i][0], false, test[i][1]); 146 } 147 } catch (e) { 148 browserCellException(e, testDiv, browserCell); 149 callback(); 150 } 151 } 152 //@} 153 154 function continueBrowserCell(test, testDiv, browserCell) { 155 //@{ 156 try { 157 testDiv.contentEditable = "inherit"; 158 testDiv.removeAttribute("spellcheck"); 159 var compareDiv1 = testDiv.cloneNode(true); 160 161 if (getSelection().rangeCount) { 162 addBrackets(getSelection().getRangeAt(0)); 163 } 164 browserCell.insertBefore(testDiv, browserCell.firstChild); 165 166 if (!browserCell.childNodes.length == 2) { 167 throw "The cell didn't have two children. Did something spill outside the test div?"; 168 } 169 170 compareDiv1.normalize(); 171 // Sigh, Gecko is crazy 172 var treeWalker = document.createTreeWalker(compareDiv1, NodeFilter.SHOW_ELEMENT, null, null); 173 while (treeWalker.nextNode()) { 174 var remove = [].filter.call(treeWalker.currentNode.attributes, function(attrib) { 175 return /^_moz_/.test(attrib.name) || attrib.value == "_moz"; 176 }); 177 for (var i = 0; i < remove.length; i++) { 178 treeWalker.currentNode.removeAttribute(remove[i].name); 179 } 180 } 181 var compareDiv2 = compareDiv1.cloneNode(false); 182 compareDiv2.innerHTML = compareDiv1.innerHTML; 183 if (!compareDiv1.isEqualNode(compareDiv2) 184 && compareDiv1.innerHTML != compareDiv2.innerHTML) { 185 throw "DOM does not round-trip through serialization! " 186 + compareDiv1.innerHTML + " vs. " + compareDiv2.innerHTML; 187 } 188 if (!compareDiv1.isEqualNode(compareDiv2)) { 189 throw "DOM does not round-trip through serialization (although innerHTML is the same)! " 190 + compareDiv1.innerHTML; 191 } 192 193 browserCell.lastChild.textContent = browserCell.firstChild.innerHTML; 194 } catch (e) { 195 browserCellException(e, testDiv, browserCell); 196 } 197 198 localStorage[keyPrefix + JSON.stringify(test)] = browserCell.innerHTML; 199 200 doBrowserCellButton(browserCell, test); 201 } 202 //@} 203 204 function doBrowserCellButton(browserCell, test) { 205 //@{ 206 var button = document.createElement("button"); 207 browserCell.lastChild.appendChild(button); 208 button.textContent = "Redo browser output"; 209 button.onclick = function() { 210 localStorage.removeItem(keyPrefix + JSON.stringify(test)); 211 var tr = browserCell.parentNode; 212 while (browserCell.nextSibling) { 213 tr.removeChild(browserCell.nextSibling); 214 } 215 tr.removeChild(browserCell); 216 doBrowserCell(tr, test, function() { 217 doSameCell(tr); 218 doTearDown(); 219 document.getElementById("overlay").style.display = ""; 220 tr.scrollIntoView(); 221 }); 222 }; 223 } 224 //@} 225 // vim: foldmarker=@{,@} foldmethod=marker