|
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 type="application/javascript" 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 |
|
37 function getPrefs() { |
|
38 const prefSvcContractID = "@mozilla.org/preferences-service;1"; |
|
39 const prefSvcIID = Components.interfaces.nsIPrefService; |
|
40 return Components.classes[prefSvcContractID].getService(prefSvcIID) |
|
41 .getBranch("layout.word_select."); |
|
42 } |
|
43 |
|
44 function setEatSpace(newValue) { |
|
45 getPrefs().setBoolPref("eat_space_to_next_word", newValue); |
|
46 eatSpace = newValue; |
|
47 } |
|
48 |
|
49 function restoreEatSpace() { |
|
50 try { |
|
51 getPrefs().clearUserPref("eat_space_to_next_word"); |
|
52 } catch(ex) {} |
|
53 } |
|
54 |
|
55 function doCommand(cmd) { |
|
56 var controller = document.commandDispatcher.getControllerForCommand(cmd); |
|
57 if (controller) { |
|
58 try { |
|
59 controller.doCommand(cmd); |
|
60 ok(true, 'doCommand(' + cmd + ') succeeded'); |
|
61 } catch(ex) { |
|
62 ok(false, 'exception in doCommand(' + cmd + '): ', ex.message); |
|
63 } |
|
64 } |
|
65 } |
|
66 |
|
67 function testRight(node, offset) { |
|
68 doCommand("cmd_charNext"); |
|
69 var msg = "Right movement broken in \"" + editor.innerHTML + "\", offset " + offset; |
|
70 is(sel.anchorNode, node, msg); |
|
71 is(sel.anchorOffset, offset, msg); |
|
72 } |
|
73 |
|
74 function selErrString(dir) { |
|
75 return dir + " selection broken with eatSpace=" + eatSpace + " in \"" + editor.innerHTML + "\""; |
|
76 } |
|
77 |
|
78 function testWordSelRight(startNode, startOffset, endNode, endOffset) { |
|
79 doCommand("cmd_selectWordNext"); |
|
80 var selRange = sel.getRangeAt(0); |
|
81 is(selRange.startContainer, startNode, selErrString("Word right")); |
|
82 is(selRange.startOffset, startOffset, selErrString("Word right")); |
|
83 is(selRange.endContainer, endNode, selErrString("Word right")); |
|
84 is(selRange.endOffset, endOffset, selErrString("Word right")); |
|
85 } |
|
86 |
|
87 function testDelete(node, offset, text, richtext) { |
|
88 doCommand("cmd_deleteCharForward"); |
|
89 var msg = "Delete broken in \"" + editor.innerHTML + "\", offset " + offset; |
|
90 if(typeof node == 'function'){ |
|
91 node = node(); |
|
92 } |
|
93 is(sel.anchorNode, node, msg); |
|
94 |
|
95 is(sel.anchorOffset, offset, msg); |
|
96 let text_result = richtext ? editor.innerHTML : editor.textContent; |
|
97 is(text_result, text, msg); |
|
98 } |
|
99 |
|
100 function testBackspace(node, offset, text) { |
|
101 doCommand("cmd_deleteCharBackward"); |
|
102 var msg = "Backspace broken in \"" + editor.innerHTML + "\", offset " + offset; |
|
103 is(sel.anchorNode, node, msg); |
|
104 |
|
105 is(sel.anchorOffset, offset, msg); |
|
106 is(editor.textContent, text, msg); |
|
107 } |
|
108 |
|
109 function testDeletePrevWord(node, offset, text) { |
|
110 doCommand("cmd_deleteWordBackward"); |
|
111 var msg = "Delete previous word broken in \"" + editor.innerHTML + "\", offset " + offset; |
|
112 is(sel.anchorNode, node, msg); |
|
113 is(sel.anchorOffset, offset, msg); |
|
114 is(editor.textContent, text, msg); |
|
115 } |
|
116 |
|
117 function testDeleteNextWord(node, offset, text) { |
|
118 doCommand("cmd_deleteWordForward"); |
|
119 var msg = "Delete next word broken in \"" + editor.innerHTML + "\", offset " + offset; |
|
120 is(sel.anchorNode, node, msg); |
|
121 is(sel.anchorOffset, offset, msg); |
|
122 todo_is(editor.textContent, text, msg); |
|
123 } |
|
124 |
|
125 // Test cell-wise deletion of Delete |
|
126 setupTest("สวัสดีพ่อแม่พี่น้อง", 0); |
|
127 testRight(editor.firstChild, 1); |
|
128 testDelete(editor.firstChild, 1, "สสดีพ่อแม่พี่น้อง"); |
|
129 testRight(editor.firstChild, 2); |
|
130 testDelete(editor.firstChild, 2, "สสพ่อแม่พี่น้อง"); |
|
131 testRight(editor.firstChild, 4); |
|
132 testDelete(editor.firstChild, 4, "สสพ่แม่พี่น้อง"); |
|
133 testRight(editor.firstChild, 5); |
|
134 testDelete(editor.firstChild, 5, "สสพ่แพี่น้อง", false); |
|
135 testRight(editor.firstChild, 8); |
|
136 testDelete(editor.firstChild, 8, "สสพ่แพี่อง", false); |
|
137 testRight(editor.firstChild, 9); |
|
138 testDelete(editor.firstChild, 9, "สสพ่แพี่อ", false); |
|
139 |
|
140 // Test character-wise deletion of Backspace |
|
141 setupTest("สวัสดีพ่อแม่พี่น้อง", 0); |
|
142 testRight(editor.firstChild, 1); |
|
143 testBackspace(editor.firstChild, 0, "วัสดีพ่อแม่พี่น้อง"); |
|
144 testRight(editor.firstChild, 2); |
|
145 testBackspace(editor.firstChild, 1, "วสดีพ่อแม่พี่น้อง"); |
|
146 testRight(editor.firstChild, 2); |
|
147 testBackspace(editor.firstChild, 1, "วดีพ่อแม่พี่น้อง"); |
|
148 testRight(editor.firstChild, 3); |
|
149 testBackspace(editor.firstChild, 2, "วดพ่อแม่พี่น้อง"); |
|
150 testRight(editor.firstChild, 4); |
|
151 testBackspace(editor.firstChild, 3, "วดพอแม่พี่น้อง"); |
|
152 testRight(editor.firstChild, 4); |
|
153 testBackspace(editor.firstChild, 3, "วดพแม่พี่น้อง"); |
|
154 testRight(editor.firstChild, 4); |
|
155 testBackspace(editor.firstChild, 3, "วดพม่พี่น้อง"); |
|
156 testRight(editor.firstChild, 5); |
|
157 testBackspace(editor.firstChild, 4, "วดพมพี่น้อง"); |
|
158 testRight(editor.firstChild, 7); |
|
159 testBackspace(editor.firstChild, 6, "วดพมพีน้อง"); |
|
160 testRight(editor.firstChild, 8); |
|
161 testBackspace(editor.firstChild, 7, "วดพมพีนอง"); |
|
162 testRight(editor.firstChild, 8); |
|
163 testBackspace(editor.firstChild, 7, "วดพมพีนง"); |
|
164 testRight(editor.firstChild, 8); |
|
165 testBackspace(editor.firstChild, 7, "วดพมพีน"); |
|
166 |
|
167 // Tests for Bug 417745 |
|
168 |
|
169 setEatSpace(true); |
|
170 |
|
171 setupTest("Quick yellow fox", 0); |
|
172 testWordSelRight(editor.firstChild, 0, editor.firstChild, 6); |
|
173 testDelete(editor.firstChild, 0, "yellow fox"); |
|
174 testWordSelRight(editor.firstChild, 0, editor.firstChild, 7); |
|
175 testDelete(editor.firstChild, 0, "fox"); |
|
176 |
|
177 setEatSpace(false); |
|
178 |
|
179 setupTest("Quick yellow fox", 0); |
|
180 testWordSelRight(editor.firstChild, 0, editor.firstChild, 5); |
|
181 // editor converts the leading space to an , otherwise it |
|
182 // wouldn't show up which would confuse users |
|
183 testDelete(editor.firstChild, 0, "\u00A0yellow fox"); |
|
184 testWordSelRight(editor.firstChild, 0, editor.firstChild, 7); |
|
185 testDelete(editor.firstChild, 0, "\u00A0fox"); |
|
186 testWordSelRight(editor.firstChild, 0, editor.firstChild, 4); |
|
187 testDelete(editor, 0, ""); |
|
188 |
|
189 restoreEatSpace(); |
|
190 |
|
191 // Tests for Bug 419217 |
|
192 |
|
193 setupTest("foo<div>bar</div>", 3); |
|
194 testDelete(function(){return editor.firstChild;}, 3, "foobar", true); |
|
195 |
|
196 // Tests for Bug 419406 |
|
197 var s = "helloשלום"; |
|
198 setupTest(s, 4); |
|
199 testRight(editor.firstChild, 5); |
|
200 testDelete(editor.firstChild, 5, "helloשלום"); |
|
201 |
|
202 // Tests for Bug 462188 |
|
203 setupTest("You should not see this text.", 29); |
|
204 testDeletePrevWord(editor.firstChild, 24, "You should not see this "); |
|
205 testDeletePrevWord(editor.firstChild, 19, "You should not see "); |
|
206 testDeletePrevWord(editor.firstChild, 15, "You should not "); |
|
207 testDeletePrevWord(editor.firstChild, 11, "You should "); |
|
208 testDeletePrevWord(editor.firstChild, 4, "You "); |
|
209 testDeletePrevWord(editor, 0, ""); |
|
210 |
|
211 setupTest("You should not see this text.", 0); |
|
212 testDeleteNextWord(editor.firstChild, 0, "\u00A0should not see this text."); |
|
213 testDeleteNextWord(editor.firstChild, 0, "\u00A0not see this text."); |
|
214 testDeleteNextWord(editor.firstChild, 0, "\u00A0see this text."); |
|
215 testDeleteNextWord(editor.firstChild, 0, "\u00A0this text."); |
|
216 testDeleteNextWord(editor.firstChild, 0, "\u00A0text."); |
|
217 // testDeleteNextWord(editor, 0, ""); |
|
218 |
|
219 // Tests for Bug 502259 |
|
220 setupTest("<p>Bug</p>\n<p>502259</p>", 1); |
|
221 testDelete(function(){return editor.firstChild.firstChild;}, 3, "<p>Bug502259</p>", true); |
|
222 |
|
223 // Tests for Bug 507936 |
|
224 var nodecallback = function(){return editor.firstChild.firstChild.lastChild.firstChild.lastChild;}; |
|
225 setupTest("<ol><li>one<ol><li>two</li></ol></li></ol>\n<p>three</p>", 3, nodecallback); |
|
226 testDelete(nodecallback, 0, "<ol><li>one<ol><li>twothree</li></ol></li></ol>", true); |
|
227 |
|
228 setupTest("<ol><li>one<ol><li>two</li></ol></li></ol>\n<hr>\n<p>three</p>", 3, nodecallback); |
|
229 testDelete(nodecallback, 3, |
|
230 "<ol><li>one<ol><li>two</li></ol></li></ol><p>three</p>", true); |
|
231 |
|
232 // Tests for Bug 519751 |
|
233 var nodecallback = function(){return editor.firstChild.lastChild;}; |
|
234 setupTest("<p>one</p><ol><li>two</li><li>three</li></ol>", 3, nodecallback); |
|
235 testDelete(nodecallback, 0, "<p>onetwo</p><ol><li>three</li></ol>", true); |
|
236 |
|
237 nodecallback = function(){return editor.firstChild.childNodes[1].firstChild;}; |
|
238 setupTest("<ol><li>one</li><li>two</li></ol><ol><li>three</li><li>four</li></ol>", 3, nodecallback); |
|
239 testDelete(function(){return editor.firstChild.childNodes[2].firstChild;}, |
|
240 0, "<ol><li>one</li><li>two</li><li>three</li><li>four</li></ol>", true); |
|
241 /*todo_is(false, true, 'The above testDelete should use the same nodecallback' + |
|
242 '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');*/ |
|
243 |
|
244 // More Tests for Bug 507936 |
|
245 nodecallback = function(){return editor.firstChild.firstChild.firstChild;} |
|
246 setupTest("<div><div>abcdef</div><div>bar</div><div>ghi</div></div>", 5, nodecallback); |
|
247 sel.extend(editor.lastChild.lastChild.lastChild, 1); |
|
248 testDelete(editor.lastChild.lastChild.lastChild, 5, "<div><div>abcdehi</div></div>", true); |
|
249 |
|
250 setupTest("<div><div>abcdef</div><div>ghi</div></div>", 5, nodecallback); |
|
251 sel.extend(editor.lastChild.lastChild.lastChild, 1); |
|
252 testDelete(editor.lastChild.lastChild.lastChild, 5, "<div><div>abcdehi</div></div>", true); |
|
253 |
|
254 nodecallback = function(){return editor.firstChild.firstChild;} |
|
255 setupTest("<div>abcdef<div><div>bar</div>ghi</div></div>", 5, nodecallback); |
|
256 sel.extend(editor.lastChild.lastChild.lastChild, 1); |
|
257 expectednodecallback = function(){return editor.lastChild.lastChild;} |
|
258 testDelete(expectednodecallback, 0, "<div>abcdehi</div>", true); |
|
259 |
|
260 setupTest("<div>abcdef<div>ghi</div></div>", 5, nodecallback); |
|
261 sel.extend(editor.lastChild.lastChild.lastChild, 1); |
|
262 testDelete(expectednodecallback, 0, "<div>abcdehi</div>", true); |
|
263 |
|
264 SimpleTest.finish(); |
|
265 } |
|
266 |
|
267 SimpleTest.waitForExplicitFinish(); |
|
268 addLoadEvent(execTests); |
|
269 ]]> |
|
270 </script> |
|
271 |
|
272 <body id="html_body" xmlns="http://www.w3.org/1999/xhtml"> |
|
273 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=462188">Mozilla Bug 462188</a> |
|
274 <p id="display"></p> |
|
275 |
|
276 <pre id="test"> |
|
277 </pre> |
|
278 <iframe id="edit" width="200" height="100" src="about:blank"/> |
|
279 </body> |
|
280 </window> |