delete.html (5204B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>Deletion tests</title> 4 <script src=/resources/testharness.js></script> 5 <script src=/resources/testharnessreport.js></script> 6 <div contenteditable></div> 7 <script> 8 var div = document.querySelector("div"); 9 10 // Format: [start html, start pos, expected html, expected pos, command] 11 // Positions are a sequence of offsets starting from div, e.g., "1,2,0" 12 // translates to node = div.childNodes[1].childNodes[2], offset = 0. For a 13 // non-collapsed selection, use a hyphen, like "0,0-1,0". The selections are 14 // created with collapse() followed by extend() to allow reverse selections, so 15 // order is significant. 16 // 17 // Expected values can be arrays, in which case any is acceptable. 18 var tests = [ 19 ["<p><br></p><p><br></p>", "1,0", "<p><br></p>", "0,0", "delete"], 20 ["<p><br></p><p><br></p>", "0,0", "<p><br></p>", "0,0", "forwarddelete"], 21 22 // Range 23 ["<p><br></p><p><br></p>", "0,0-1,0", "<p><br></p>", "0,0", "delete"], 24 ["<p><br></p><p><br></p>", "0,0-1,0", "<p><br></p>", "0,0", "forwarddelete"], 25 ["<p><br></p><p><br></p>", "1,0-0,0", "<p><br></p>", "0,0", "delete"], 26 ["<p><br></p><p><br></p>", "1,0-0,0", "<p><br></p>", "0,0", "forwarddelete"], 27 28 // Different start values 29 ["<p>x<br></p><p><br></p>", "1,0", 30 // WebKit/Blink like to get rid of the extra <br> 31 ["<p>x<br></p>", "<p>x</p>"], 32 // The selection should really be collapsed inside the text node, but in the 33 // parent is close enough. 34 ["0,0,1", "0,1"], "delete"], 35 ["<p><br><br></p><p><br></p>", "1,0", "<p><br><br></p>", "0,1", "delete"], 36 ["<p><br></p><p><br><br></p>", "1,1", 37 "<p><br></p><p><br></p>", "1,0", "delete"], 38 ["<p><br><br><br></p>", "0,2", "<p><br><br></p>", "0,1", "delete"], 39 ["<p><br></p><p><br><br><br></p>", "1,2", 40 "<p><br></p><p><br><br></p>", "1,1", "delete"], 41 ["<p><br><br></p><p><br><br></p>", "1,1", 42 "<p><br><br></p><p><br></p>", "1,0", "delete"], 43 ["<p><br></p><br>", "1", "<p><br></p>", "0,0", "delete"], 44 45 // The trailing \n in these cases is actually significant, because it was 46 // necessary to trigger an actual Gecko bug (somehow!). 47 // NOTE: It's fine to delete surrounding white-spaces of the deleting block. 48 ["<p><br></p><p><br></p>\n", "1,0", 49 ["<p><br></p>\n", "<p><br></p>"], "0,0", "delete"], 50 ["<p><br></p><p><br></p>\n", "0,0", 51 ["<p><br></p>\n", "<p><br></p>"], "0,0", "forwarddelete"], 52 ["\n<p><tt>x</tt></p><p><tt><br></tt></p><p><tt><br></tt></p>\n", "3,0,0", 53 ["\n<p><tt>x</tt></p><p><tt><br></tt></p>\n", "\n<p><tt>x</tt></p><p><tt><br></tt></p>"], "2,0,0", "delete"], 54 ]; 55 56 div.focus(); 57 58 for (var i = 0; i < tests.length; i++) { 59 test(function() { 60 var test = tests[i]; 61 div.innerHTML = test[0]; 62 setSelection(test[1]); 63 64 document.execCommand(test[4], false, ""); 65 66 if (typeof test[2] == "string") { 67 assert_equals(div.innerHTML, test[2], "innerHTML"); 68 } else { 69 assert_in_array(div.innerHTML, test[2], "innerHTML"); 70 } 71 72 var actualSel = recordSelection(); 73 var expectedSel = []; 74 if (typeof test[3] == "string") { 75 test[3] = [test[3]]; 76 } 77 for (var j = 0; j < test[3].length; j++) { 78 setSelection(test[3][j]); 79 expectedSel.push(recordSelection()); 80 } 81 assertSelectionEquals(actualSel, expectedSel, test[2]); 82 }, i + ": " + format_value(tests[i][0]) + " " + tests[i][1] + 83 " " + tests[i][4]); 84 } 85 86 function setSelection(selstr) { 87 var parts = selstr.split("-"); 88 var collapsePoint = getPointFromArray(parts[0].split(",")); 89 getSelection().collapse(collapsePoint[0], collapsePoint[1]); 90 91 if (parts[1]) { 92 var extendPoint = getPointFromArray(parts[1].split(",")); 93 getSelection().extend(extendPoint[0], extendPoint[1]); 94 } 95 } 96 97 function getPointFromArray(offsets) { 98 var retNode = div, retOffset; 99 var offset; 100 while (offset = offsets.shift()) { 101 if (!offsets.length) { 102 retOffset = offset; 103 } else { 104 retNode = retNode.childNodes[offset]; 105 } 106 } 107 return [retNode, retOffset]; 108 } 109 110 function recordSelection() { 111 return [getSelection().anchorNode, getSelection().anchorOffset, 112 getSelection().focusNode, getSelection().focusOffset]; 113 } 114 115 function assertSelectionEquals(actual, expected, html) { 116 if (typeof expected == "string") { 117 expected = [expected]; 118 } 119 var pass = false; 120 for (var i = 0; i < expected.length; i++) { 121 if (expected[i][0] === actual[0] && 122 expected[i][1] === actual[1] && 123 expected[i][2] === actual[2] && 124 expected[i][3] === actual[3]) { 125 pass = true; 126 break; 127 } 128 } 129 130 assert_true(pass, "Wrong selection, expected " + formatSel(expected) + 131 ", got " + formatSel(actual) + 132 " (in HTML " + format_value(html) + ")"); 133 } 134 135 function formatSel(arr) { 136 if (arr.length == 1) { 137 arr = arr[0]; 138 } 139 if (Array.isArray(arr[0])) { 140 var ret = []; 141 for (var i = 0; i < arr.length; i++) { 142 ret.push(formatSel(arr[i])); 143 } 144 return ret.join(" or "); 145 } 146 if (arr[0] == arr[2] && arr[1] == arr[3]) { 147 return "collapsed (" + format_value(arr[0]) + ", " + arr[1] + ")"; 148 } 149 return "(" + format_value(arr[0]) + ", " + arr[1] + 150 ")-(" + format_value(arr[2]) + ", " + arr[3] + ")"; 151 } 152 </script>