// Initial setup //@{ var globalValue; if (globalValue === undefined) { globalValue = command in defaultValues ? defaultValues[command] : ""; } var keyPrefix = globalValue == "" ? "manualtest-" + command + "-" : "manualtest-" + command + "-" + globalValue + "-"; (function(){ var manualTests = tests[command] .map(function(test) { return normalizeTest(command, test) }) .filter(function(test) { return test[1][1] == globalValue }); var relevantMultiTests = tests.multitest .map(function(test) { return normalizeTest("multitest", test) }) .filter(function(test) { // We only want multitests if there's exactly one occurrence of the // command we're testing for, and the value is correct, and that's // the last command we're testing. Some of these limitations could // be removed in the future. return test[test.length - 1][0] === command && test[test.length - 1][1] === globalValue; }); tests = manualTests.concat(relevantMultiTests); })(); //@} function clearCachedResults() { //@{ for (var key in localStorage) { if (key.indexOf(keyPrefix) === 0) { localStorage.removeItem(key); } } } //@} var numManualTests = 0; var currentTestIdx = null; // Make sure styleWithCss is always reset to false at the start of a test run // (I'm looking at you, Firefox) try { document.execCommand("stylewithcss", false, "false") } catch(e) {} function runTests() { //@{ // We don't ask the user to hit a key on all tests, so make sure not to // claim more tests are going to be run than actually are. for (var i = 0; i < tests.length; i++) { if (localStorage.getItem(keyPrefix + JSON.stringify(tests[i])) === null) { numManualTests++; } } currentTestIdx = 0; var runTestsButton = document.querySelector("#tests input[type=button]"); runTestsButton.parentNode.removeChild(runTestsButton); var addTestButton = document.querySelector("#tests input[type=button]"); var input = document.querySelector("#tests label input"); // This code actually focuses and clicks everything because for some // reason, anything else doesn't work in IE9 . . . input.value = JSON.stringify(tests[0]); input.focus(); addTestButton.click(); } //@} function addTest() { //@{ var tr = doSetup("#tests table", 0); var input = document.querySelector("#tests label input"); var test = JSON.parse(input.value); doInputCell(tr, test, test.length == 2 ? command : "multitest"); doSpecCell(tr, test, test.length == 2 ? command : "multitest"); if (localStorage.getItem(keyPrefix + JSON.stringify(test)) !== null) { // Yay, I get to cheat. Remove the overlay div so the user doesn't // keep hitting the key, in case it takes a while. var browserCell = document.createElement("td"); tr.appendChild(browserCell); browserCell.innerHTML = localStorage[keyPrefix + JSON.stringify(test)]; doBrowserCellButton(browserCell, test); document.getElementById("overlay").style.display = ""; doSameCell(tr); runNextTest(test); } else { doBrowserCell(tr, test, function() { doSameCell(tr); runNextTest(); }); } } //@} function runNextTest() { //@{ doTearDown(); var input = document.querySelector("#tests label input"); if (currentTestIdx === null || currentTestIdx + 1 >= tests.length) { currentTestIdx = null; document.getElementById("overlay").style.display = ""; input.value = ""; return; } currentTestIdx++; input.value = JSON.stringify(tests[currentTestIdx]); input.focus(); addTest(); } //@} function doBrowserCell(tr, test, callback) { //@{ var browserCell = document.createElement("td"); tr.appendChild(browserCell); try { var points = setupCell(browserCell, test[0]); var testDiv = browserCell.firstChild; // Work around weird Firefox bug: // https://bugzilla.mozilla.org/show_bug.cgi?id=649138 document.body.appendChild(testDiv); testDiv.onkeyup = function() { continueBrowserCell(test, testDiv, browserCell); callback(); }; testDiv.contentEditable = "true"; testDiv.spellcheck = false; if (currentTestIdx === null) { document.getElementById("testcount").style.display = "none"; } else { document.getElementById("testcount").style.display = ""; document.querySelector("#testcount > span").textContent = numManualTests; numManualTests--; } document.getElementById("overlay").style.display = "block"; testDiv.focus(); setSelection(points[0], points[1], points[2], points[3]); // Execute any extra commands beforehand, for multitests for (var i = 1; i < test.length - 1; i++) { document.execCommand(test[i][0], false, test[i][1]); } } catch (e) { browserCellException(e, testDiv, browserCell); callback(); } } //@} function continueBrowserCell(test, testDiv, browserCell) { //@{ try { testDiv.contentEditable = "inherit"; testDiv.removeAttribute("spellcheck"); var compareDiv1 = testDiv.cloneNode(true); if (getSelection().rangeCount) { addBrackets(getSelection().getRangeAt(0)); } browserCell.insertBefore(testDiv, browserCell.firstChild); if (!browserCell.childNodes.length == 2) { throw "The cell didn't have two children. Did something spill outside the test div?"; } compareDiv1.normalize(); // Sigh, Gecko is crazy var treeWalker = document.createTreeWalker(compareDiv1, NodeFilter.SHOW_ELEMENT, null, null); while (treeWalker.nextNode()) { var remove = [].filter.call(treeWalker.currentNode.attributes, function(attrib) { return /^_moz_/.test(attrib.name) || attrib.value == "_moz"; }); for (var i = 0; i < remove.length; i++) { treeWalker.currentNode.removeAttribute(remove[i].name); } } var compareDiv2 = compareDiv1.cloneNode(false); compareDiv2.innerHTML = compareDiv1.innerHTML; if (!compareDiv1.isEqualNode(compareDiv2) && compareDiv1.innerHTML != compareDiv2.innerHTML) { throw "DOM does not round-trip through serialization! " + compareDiv1.innerHTML + " vs. " + compareDiv2.innerHTML; } if (!compareDiv1.isEqualNode(compareDiv2)) { throw "DOM does not round-trip through serialization (although innerHTML is the same)! " + compareDiv1.innerHTML; } browserCell.lastChild.textContent = browserCell.firstChild.innerHTML; } catch (e) { browserCellException(e, testDiv, browserCell); } localStorage[keyPrefix + JSON.stringify(test)] = browserCell.innerHTML; doBrowserCellButton(browserCell, test); } //@} function doBrowserCellButton(browserCell, test) { //@{ var button = document.createElement("button"); browserCell.lastChild.appendChild(button); button.textContent = "Redo browser output"; button.onclick = function() { localStorage.removeItem(keyPrefix + JSON.stringify(test)); var tr = browserCell.parentNode; while (browserCell.nextSibling) { tr.removeChild(browserCell.nextSibling); } tr.removeChild(browserCell); doBrowserCell(tr, test, function() { doSameCell(tr); doTearDown(); document.getElementById("overlay").style.display = ""; tr.scrollIntoView(); }); }; } //@} // vim: foldmarker=@{,@} foldmethod=marker