OLD | NEW |
(Empty) | |
| 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 ["<p><br></p><p><br></p>\n", "1,0", "<p><br></p>\n", "0,0", "delete"], |
| 48 ["<p><br></p><p><br></p>\n", "0,0", "<p><br></p>\n", "0,0", "forwarddelete"], |
| 49 ["\n<p><tt>x</tt></p><p><tt><br></tt></p><p><tt><br></tt></p>\n", "3,0,0", |
| 50 "\n<p><tt>x</tt></p><p><tt><br></tt></p>\n", "2,0,0", "delete"], |
| 51 ]; |
| 52 |
| 53 div.focus(); |
| 54 |
| 55 for (var i = 0; i < tests.length; i++) { |
| 56 test(function() { |
| 57 var test = tests[i]; |
| 58 div.innerHTML = test[0]; |
| 59 setSelection(test[1]); |
| 60 |
| 61 document.execCommand(test[4], false, ""); |
| 62 |
| 63 if (typeof test[2] == "string") { |
| 64 assert_equals(div.innerHTML, test[2], "innerHTML"); |
| 65 } else { |
| 66 assert_in_array(div.innerHTML, test[2], "innerHTML"); |
| 67 } |
| 68 |
| 69 var actualSel = recordSelection(); |
| 70 var expectedSel = []; |
| 71 if (typeof test[3] == "string") { |
| 72 test[3] = [test[3]]; |
| 73 } |
| 74 for (var j = 0; j < test[3].length; j++) { |
| 75 setSelection(test[3][j]); |
| 76 expectedSel.push(recordSelection()); |
| 77 } |
| 78 assertSelectionEquals(actualSel, expectedSel, test[2]); |
| 79 }, i + ": " + format_value(tests[i][0]) + " " + tests[i][1] + |
| 80 " " + tests[i][4]); |
| 81 } |
| 82 |
| 83 function setSelection(selstr) { |
| 84 var parts = selstr.split("-"); |
| 85 var collapsePoint = getPointFromArray(parts[0].split(",")); |
| 86 getSelection().collapse(collapsePoint[0], collapsePoint[1]); |
| 87 |
| 88 if (parts[1]) { |
| 89 var extendPoint = getPointFromArray(parts[1].split(",")); |
| 90 getSelection().extend(extendPoint[0], extendPoint[1]); |
| 91 } |
| 92 } |
| 93 |
| 94 function getPointFromArray(offsets) { |
| 95 var retNode = div, retOffset; |
| 96 var offset; |
| 97 while (offset = offsets.shift()) { |
| 98 if (!offsets.length) { |
| 99 retOffset = offset; |
| 100 } else { |
| 101 retNode = retNode.childNodes[offset]; |
| 102 } |
| 103 } |
| 104 return [retNode, retOffset]; |
| 105 } |
| 106 |
| 107 function recordSelection() { |
| 108 return [getSelection().anchorNode, getSelection().anchorOffset, |
| 109 getSelection().focusNode, getSelection().focusOffset]; |
| 110 } |
| 111 |
| 112 function assertSelectionEquals(actual, expected, html) { |
| 113 if (typeof expected == "string") { |
| 114 expected = [expected]; |
| 115 } |
| 116 var pass = false; |
| 117 for (var i = 0; i < expected.length; i++) { |
| 118 if (expected[i][0] === actual[0] && |
| 119 expected[i][1] === actual[1] && |
| 120 expected[i][2] === actual[2] && |
| 121 expected[i][3] === actual[3]) { |
| 122 pass = true; |
| 123 break; |
| 124 } |
| 125 } |
| 126 |
| 127 assert_true(pass, "Wrong selection, expected " + formatSel(expected) + |
| 128 ", got " + formatSel(actual) + |
| 129 " (in HTML " + format_value(html) + ")"); |
| 130 } |
| 131 |
| 132 function formatSel(arr) { |
| 133 if (arr.length == 1) { |
| 134 arr = arr[0]; |
| 135 } |
| 136 if (Array.isArray(arr[0])) { |
| 137 var ret = []; |
| 138 for (var i = 0; i < arr.length; i++) { |
| 139 ret.push(formatSel(arr[i])); |
| 140 } |
| 141 return ret.join(" or "); |
| 142 } |
| 143 if (arr[0] == arr[2] && arr[1] == arr[3]) { |
| 144 return "collapsed (" + format_value(arr[0]) + ", " + arr[1] + ")"; |
| 145 } |
| 146 return "(" + format_value(arr[0]) + ", " + arr[1] + |
| 147 ")-(" + format_value(arr[2]) + ", " + arr[3] + ")"; |
| 148 } |
| 149 </script> |
OLD | NEW |