test_backspace_delete.xhtml (12777B)
1 <?xml version="1.0"?> 2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?> 3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> 4 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 5 xmlns:html="http://www.w3.org/1999/xhtml" 6 title="Test BackSpace/Delete Keys"> 7 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 8 9 <script class="testbody" type="application/javascript"> 10 <![CDATA[ 11 12 function execTests() { 13 var e = document.getElementById("edit"); 14 var doc = e.contentDocument; 15 var win = e.contentWindow; 16 var root = doc.documentElement; 17 var editor = doc.body; 18 var sel = win.getSelection(); 19 win.focus(); 20 21 function setupTest(html, firstChildOffsetForCaret, node) { 22 // Work around bug 474255 --- we need to have nonempty content before we turn on 23 // editing, or the tests below break because the editor doesn't notice when we 24 // insert non-empty content using innerHTML. 25 doc.designMode = 'off'; 26 editor.innerHTML = html; 27 doc.designMode = 'on'; 28 var n = editor.firstChild; 29 if (node) { 30 n = node(); 31 } 32 sel.collapse(n, firstChildOffsetForCaret); 33 } 34 35 var eatSpace; 36 var deleteImmediately; 37 38 function getPrefs(branch) { 39 const prefSvcContractID = "@mozilla.org/preferences-service;1"; 40 const prefSvcIID = Ci.nsIPrefService; 41 return Cc[prefSvcContractID].getService(prefSvcIID) 42 .getBranch(branch); 43 } 44 45 function setPref(branch, pref, newValue) { 46 getPrefs(branch).setBoolPref(pref, newValue); 47 return newValue; 48 } 49 50 function restorePref(branch, pref, newValue) { 51 try { 52 getPrefs(branch).clearUserPref(pref); 53 } catch(ex) {} 54 } 55 56 function setEatSpace(newValue) { 57 eatSpace = setPref("layout.word_select.", "eat_space_to_next_word", newValue); 58 } 59 60 function restoreEatSpace() { 61 restorePref("layout.word_select.", "eat_space_to_next_word"); 62 } 63 64 function setDeleteImmediately(newValue) { 65 deleteImmediately = setPref("bidi.edit.", "delete_immediately", newValue); 66 } 67 68 function restoreDeleteImmediately() { 69 restorePref("bidi.edit.", "delete_immediately"); 70 } 71 72 function doCommand(cmd) { 73 var controller = document.commandDispatcher.getControllerForCommand(cmd); 74 if (controller) { 75 try { 76 controller.doCommand(cmd); 77 ok(true, 'doCommand(' + cmd + ') succeeded'); 78 } catch(ex) { 79 ok(false, 'exception in doCommand(' + cmd + '): ', ex.message); 80 } 81 } 82 } 83 84 function testRight(node, offset) { 85 doCommand("cmd_charNext"); 86 var msg = "Right movement broken in \"" + editor.innerHTML + "\", offset " + offset; 87 is(sel.anchorNode, node, msg); 88 is(sel.anchorOffset, offset, msg); 89 } 90 91 function selErrString(dir) { 92 return dir + " selection broken with eatSpace=" + eatSpace + " in \"" + editor.innerHTML + "\""; 93 } 94 95 function testWordSelRight(startNode, startOffset, endNode, endOffset) { 96 doCommand("cmd_selectWordNext"); 97 var selRange = sel.getRangeAt(0); 98 is(selRange.startContainer, startNode, selErrString("Word right")); 99 is(selRange.startOffset, startOffset, selErrString("Word right")); 100 is(selRange.endContainer, endNode, selErrString("Word right")); 101 is(selRange.endOffset, endOffset, selErrString("Word right")); 102 } 103 104 function testDelete(node, offset, text, richtext) { 105 doCommand("cmd_deleteCharForward"); 106 var msg = "Delete broken in \"" + editor.innerHTML + "\", offset " + offset + " with deleteImmediately=" + deleteImmediately; 107 if(typeof node == 'function'){ 108 node = node(); 109 } 110 is(sel.anchorNode, node, msg); 111 112 is(sel.anchorOffset, offset, msg); 113 let text_result = richtext ? editor.innerHTML : editor.textContent; 114 is(text_result, text, msg); 115 } 116 117 function testBackspace(node, offset, text) { 118 doCommand("cmd_deleteCharBackward"); 119 var msg = "Backspace broken in \"" + editor.innerHTML + "\", offset " + offset + " with deleteImmediately=" + deleteImmediately; 120 is(sel.anchorNode, node, msg); 121 122 is(sel.anchorOffset, offset, msg); 123 is(editor.textContent, text, msg); 124 } 125 126 function testDeletePrevWord(node, offset, text) { 127 doCommand("cmd_deleteWordBackward"); 128 var msg = "Delete previous word broken in \"" + editor.innerHTML + "\", offset " + offset; 129 is(sel.anchorNode, node, msg); 130 is(sel.anchorOffset, offset, msg); 131 is(editor.textContent, text, msg); 132 } 133 134 function testDeleteNextWord(node, offset, text) { 135 doCommand("cmd_deleteWordForward"); 136 var msg = "Delete next word broken in \"" + editor.innerHTML + "\", offset " + offset; 137 is(sel.anchorNode, node, msg); 138 is(sel.anchorOffset, offset, msg); 139 todo_is(editor.textContent, text, msg); 140 } 141 142 // Test cell-wise deletion of Delete 143 setupTest("สวัสดีพ่อแม่พี่น้อง", 0); 144 testRight(editor.firstChild, 1); 145 testDelete(editor.firstChild, 1, "สสดีพ่อแม่พี่น้อง"); 146 testRight(editor.firstChild, 2); 147 testDelete(editor.firstChild, 2, "สสพ่อแม่พี่น้อง"); 148 testRight(editor.firstChild, 4); 149 testDelete(editor.firstChild, 4, "สสพ่แม่พี่น้อง"); 150 testRight(editor.firstChild, 5); 151 testDelete(editor.firstChild, 5, "สสพ่แพี่น้อง", false); 152 testRight(editor.firstChild, 8); 153 testDelete(editor.firstChild, 8, "สสพ่แพี่อง", false); 154 testRight(editor.firstChild, 9); 155 testDelete(editor.firstChild, 9, "สสพ่แพี่อ", false); 156 157 // Test character-wise deletion of Backspace 158 setupTest("สวัสดีพ่อแม่พี่น้อง", 0); 159 testRight(editor.firstChild, 1); 160 testBackspace(editor.firstChild, 0, "วัสดีพ่อแม่พี่น้อง"); 161 testRight(editor.firstChild, 2); 162 testBackspace(editor.firstChild, 1, "วสดีพ่อแม่พี่น้อง"); 163 testRight(editor.firstChild, 2); 164 testBackspace(editor.firstChild, 1, "วดีพ่อแม่พี่น้อง"); 165 testRight(editor.firstChild, 3); 166 testBackspace(editor.firstChild, 2, "วดพ่อแม่พี่น้อง"); 167 testRight(editor.firstChild, 4); 168 testBackspace(editor.firstChild, 3, "วดพอแม่พี่น้อง"); 169 testRight(editor.firstChild, 4); 170 testBackspace(editor.firstChild, 3, "วดพแม่พี่น้อง"); 171 testRight(editor.firstChild, 4); 172 testBackspace(editor.firstChild, 3, "วดพม่พี่น้อง"); 173 testRight(editor.firstChild, 5); 174 testBackspace(editor.firstChild, 4, "วดพมพี่น้อง"); 175 testRight(editor.firstChild, 7); 176 testBackspace(editor.firstChild, 6, "วดพมพีน้อง"); 177 testRight(editor.firstChild, 8); 178 testBackspace(editor.firstChild, 7, "วดพมพีนอง"); 179 testRight(editor.firstChild, 8); 180 testBackspace(editor.firstChild, 7, "วดพมพีนง"); 181 testRight(editor.firstChild, 8); 182 testBackspace(editor.firstChild, 7, "วดพมพีน"); 183 184 // Tests for Bug 417745 185 186 setEatSpace(true); 187 188 setupTest("Quick yellow fox", 0); 189 testWordSelRight(editor.firstChild, 0, editor.firstChild, 6); 190 testDelete(editor.firstChild, 0, "yellow fox"); 191 testWordSelRight(editor.firstChild, 0, editor.firstChild, 7); 192 testDelete(editor.firstChild, 0, "fox"); 193 194 setEatSpace(false); 195 196 setupTest("Quick yellow fox", 0); 197 testWordSelRight(editor.firstChild, 0, editor.firstChild, 5); 198 // editor converts the leading space to an , otherwise it 199 // wouldn't show up which would confuse users 200 testDelete(editor.firstChild, 0, "\u00A0yellow fox"); 201 testWordSelRight(editor.firstChild, 0, editor.firstChild, 7); 202 testDelete(editor.firstChild, 0, "\u00A0fox"); 203 testWordSelRight(editor.firstChild, 0, editor.firstChild, 4); 204 testDelete(editor, 0, ""); 205 206 restoreEatSpace(); 207 208 // Tests for Bug 419217 209 210 setupTest("foo<div>bar</div>", 3); 211 testDelete(function(){return editor.firstChild;}, 3, "foobar", true); 212 213 // Tests for Bug 419406 214 var s = "helloשלום"; 215 216 setDeleteImmediately(true); 217 218 setupTest(s, 4); 219 testRight(editor.firstChild, 5); 220 testDelete(editor.firstChild, 5, "helloלום"); 221 222 setDeleteImmediately(false); 223 224 setupTest(s, 4); 225 testRight(editor.firstChild, 5); 226 testDelete(editor.firstChild, 5, "helloשלום"); 227 228 // Tests for bug 1034337 229 s = "اهلاhello"; 230 231 setDeleteImmediately(true); 232 233 setupTest(s, 4); 234 // first delete an ltr character to make sure that the caret is ltr 235 testDelete(editor.firstChild, 4, "اهلاello"); 236 testBackspace(editor.firstChild, 3, "اهلello"); 237 238 setDeleteImmediately(false); 239 240 setupTest(s, 4); 241 // first delete an ltr character to make sure that the caret is ltr 242 testDelete(editor.firstChild, 4, "اهلاello"); 243 testBackspace(editor.firstChild, 4, "اهلاello"); 244 245 restoreDeleteImmediately(); 246 247 // Tests for Bug 462188 248 setupTest("You should not see this text.", 29); 249 testDeletePrevWord(editor.firstChild, 24, "You should not see this "); 250 testDeletePrevWord(editor.firstChild, 19, "You should not see "); 251 testDeletePrevWord(editor.firstChild, 15, "You should not "); 252 testDeletePrevWord(editor.firstChild, 11, "You should "); 253 testDeletePrevWord(editor.firstChild, 4, "You "); 254 testDeletePrevWord(editor, 0, ""); 255 256 setupTest("You should not see this text.", 0); 257 testDeleteNextWord(editor.firstChild, 0, "\u00A0should not see this text."); 258 testDeleteNextWord(editor.firstChild, 0, "\u00A0not see this text."); 259 testDeleteNextWord(editor.firstChild, 0, "\u00A0see this text."); 260 testDeleteNextWord(editor.firstChild, 0, "\u00A0this text."); 261 testDeleteNextWord(editor.firstChild, 0, "\u00A0text."); 262 // testDeleteNextWord(editor, 0, ""); 263 264 // Tests for Bug 502259 265 setupTest("<p>Bug</p>\n<p>502259</p>", 1); 266 testDelete(function(){return editor.firstChild.firstChild;}, 3, "<p>Bug502259</p>", true); 267 268 // Tests for Bug 507936 269 var nodecallback = function(){return editor.firstChild.firstChild.lastChild.firstChild.lastChild;}; 270 setupTest("<ol><li>one<ol><li>two</li></ol></li></ol>\n<p>three</p>", 3, nodecallback); 271 testDelete(nodecallback, 0, "<ol><li>one<ol><li>twothree</li></ol></li></ol>", true); 272 273 setupTest("<ol><li>one<ol><li>two</li></ol></li></ol>\n<hr>\n<p>three</p>", 3, nodecallback); 274 testDelete(nodecallback, 3, 275 "<ol><li>one<ol><li>two</li></ol></li></ol><p>three</p>", true); 276 277 // Tests for Bug 519751 278 var nodecallback = function(){return editor.firstChild.lastChild;}; 279 setupTest("<p>one</p><ol><li>two</li><li>three</li></ol>", 3, nodecallback); 280 testDelete(nodecallback, 0, "<p>onetwo</p><ol><li>three</li></ol>", true); 281 282 nodecallback = function(){return editor.firstChild.childNodes[1].firstChild;}; 283 setupTest("<ol><li>one</li><li>two</li></ol><ol><li>three</li><li>four</li></ol>", 3, nodecallback); 284 testDelete(function(){return editor.firstChild.childNodes[2].firstChild;}, 285 0, "<ol><li>one</li><li>two</li><li>three</li><li>four</li></ol>", true); 286 /*todo_is(false, true, 'The above testDelete should use the same nodecallback' + 287 'as in the proceeding setupTest: the cursor should stay at the end of "two", while currently it is at the beginning of "three" after delete');*/ 288 289 // More Tests for Bug 507936 290 nodecallback = function(){return editor.firstChild.firstChild.firstChild;} 291 setupTest("<div><div>abcdef</div><div>bar</div><div>ghi</div></div>", 5, nodecallback); 292 sel.extend(editor.lastChild.lastChild.lastChild, 1); 293 testDelete(editor.lastChild.lastChild.lastChild, 5, "<div><div>abcdehi</div></div>", true); 294 295 setupTest("<div><div>abcdef</div><div>ghi</div></div>", 5, nodecallback); 296 sel.extend(editor.lastChild.lastChild.lastChild, 1); 297 testDelete(editor.lastChild.lastChild.lastChild, 5, "<div><div>abcdehi</div></div>", true); 298 299 nodecallback = function(){return editor.firstChild.firstChild;} 300 setupTest("<div>abcdef<div><div>bar</div>ghi</div></div>", 5, nodecallback); 301 sel.extend(editor.lastChild.lastChild.lastChild, 1); 302 expectednodecallback = function(){return editor.lastChild.lastChild;} 303 testDelete(expectednodecallback, 0, "<div>abcdehi</div>", true); 304 305 setupTest("<div>abcdef<div>ghi</div></div>", 5, nodecallback); 306 sel.extend(editor.lastChild.lastChild.lastChild, 1); 307 testDelete(expectednodecallback, 0, "<div>abcdehi</div>", true); 308 309 SimpleTest.finish(); 310 } 311 312 SimpleTest.waitForExplicitFinish(); 313 addLoadEvent(execTests); 314 ]]> 315 </script> 316 317 <body id="html_body" xmlns="http://www.w3.org/1999/xhtml"> 318 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=462188">Mozilla Bug 462188</a> 319 <p id="display"></p> 320 321 <pre id="test"> 322 </pre> 323 <iframe id="edit" width="200" height="100" src="about:blank"/> 324 </body> 325 </window>