2 * Copyright (C) 2016 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android.text.method;
19 import android.app.Activity;
20 import android.test.suitebuilder.annotation.SmallTest;
21 import android.test.suitebuilder.annotation.Suppress;
22 import android.text.InputType;
23 import android.text.method.BaseKeyListener;
24 import android.text.method.KeyListenerTestCase;
25 import android.view.KeyEvent;
26 import android.widget.EditText;
27 import android.widget.TextView.BufferType;
30 * Test backspace key handling of {@link android.text.method.BaseKeyListner}.
32 * Only contains edge cases. For normal cases, see {@see android.text.method.cts.BackspaceTest}.
33 * TODO: introduce test cases for surrogate pairs and replacement span.
35 public class BackspaceTest extends KeyListenerTestCase {
36 private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
37 public int getInputType() {
38 return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
42 // Sync the state to the TextView and call onKeyDown with KEYCODE_DEL key event.
43 // Then update the state to the result of TextView.
44 private void backspace(final EditorState state, int modifiers) {
45 mActivity.runOnUiThread(new Runnable() {
47 mTextView.setText(state.mText, BufferType.EDITABLE);
48 mTextView.setKeyListener(mKeyListener);
49 mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
52 mInstrumentation.waitForIdleSync();
53 assertTrue(mTextView.hasWindowFocus());
55 final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_DEL, modifiers);
56 mActivity.runOnUiThread(new Runnable() {
58 mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
61 mInstrumentation.waitForIdleSync();
63 state.mText = mTextView.getText();
64 state.mSelectionStart = mTextView.getSelectionStart();
65 state.mSelectionEnd = mTextView.getSelectionEnd();
69 public void testCombiningEnclosingKeycaps() {
70 EditorState state = new EditorState();
72 state.setByString("'1' U+E0101 U+20E3 |");
74 state.assertEquals("|");
76 // multiple COMBINING ENCLOSING KEYCAP
77 state.setByString("'1' U+20E3 U+20E3 |");
79 state.assertEquals("'1' U+20E3 |");
81 state.assertEquals("|");
83 // Isolated COMBINING ENCLOSING KEYCAP
84 state.setByString("U+20E3 |");
86 state.assertEquals("|");
88 // Isolated multiple COMBINING ENCLOSING KEYCAP
89 state.setByString("U+20E3 U+20E3 |");
91 state.assertEquals("U+20E3 |");
93 state.assertEquals("|");
97 public void testVariationSelector() {
98 EditorState state = new EditorState();
100 // Isolated variation selector
101 state.setByString("U+FE0F |");
103 state.assertEquals("|");
105 state.setByString("U+E0100 |");
107 state.assertEquals("|");
109 // Isolated multiple variation selectors
110 state.setByString("U+FE0F U+FE0F |");
112 state.assertEquals("U+FE0F |");
114 state.assertEquals("|");
116 state.setByString("U+FE0F U+E0100 |");
118 state.assertEquals("U+FE0F |");
120 state.assertEquals("|");
122 state.setByString("U+E0100 U+FE0F |");
124 state.assertEquals("U+E0100 |");
126 state.assertEquals("|");
128 state.setByString("U+E0100 U+E0100 |");
130 state.assertEquals("U+E0100 |");
132 state.assertEquals("|");
134 // Multiple variation selectors
135 state.setByString("'#' U+FE0F U+FE0F |");
137 state.assertEquals("'#' U+FE0F |");
139 state.assertEquals("|");
141 state.setByString("'#' U+FE0F U+E0100 |");
143 state.assertEquals("'#' U+FE0F |");
145 state.assertEquals("|");
147 state.setByString("U+845B U+E0100 U+FE0F |");
149 state.assertEquals("U+845B U+E0100 |");
151 state.assertEquals("|");
153 state.setByString("U+845B U+E0100 U+E0100 |");
155 state.assertEquals("U+845B U+E0100 |");
157 state.assertEquals("|");
161 public void testEmojiZWJSequence() {
162 EditorState state = new EditorState();
164 // U+200D is ZERO WIDTH JOINER.
165 state.setByString("U+1F441 U+200D U+1F5E8 |");
167 state.assertEquals("|");
169 state.setByString("U+1F441 U+200D U+1F5E8 U+FE0E |");
171 state.assertEquals("|");
173 state.setByString("U+1F469 U+200D U+1F373 |");
175 state.assertEquals("|");
177 state.setByString("U+1F487 U+200D U+2640 |");
179 state.assertEquals("|");
181 state.setByString("U+1F487 U+200D U+2640 U+FE0F |");
183 state.assertEquals("|");
185 state.setByString("U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 |");
187 state.assertEquals("|");
189 // Emoji modifier can be appended to the first emoji.
190 state.setByString("U+1F469 U+1F3FB U+200D U+1F4BC |");
192 state.assertEquals("|");
194 // End with ZERO WIDTH JOINER
195 state.setByString("U+1F441 U+200D |");
197 state.assertEquals("U+1F441 |");
199 state.assertEquals("|");
201 // Start with ZERO WIDTH JOINER
202 state.setByString("U+200D U+1F5E8 |");
204 state.assertEquals("U+200D |");
206 state.assertEquals("|");
208 state.setByString("U+FE0E U+200D U+1F5E8 |");
210 state.assertEquals("U+FE0E U+200D |");
212 state.assertEquals("U+FE0E |");
214 state.assertEquals("|");
216 // Multiple ZERO WIDTH JOINER
217 state.setByString("U+1F441 U+200D U+200D U+1F5E8 |");
219 state.assertEquals("U+1F441 U+200D U+200D |");
221 state.assertEquals("U+1F441 U+200D |");
223 state.assertEquals("U+1F441 |");
225 state.assertEquals("|");
227 // Isolated ZERO WIDTH JOINER
228 state.setByString("U+200D |");
230 state.assertEquals("|");
232 // Isolated multiple ZERO WIDTH JOINER
233 state.setByString("U+200D U+200D |");
235 state.assertEquals("U+200D |");
237 state.assertEquals("|");
241 public void testFlags() {
242 EditorState state = new EditorState();
244 // Isolated regional indicator symbol
245 state.setByString("U+1F1FA |");
247 state.assertEquals("|");
249 // Odd numbered regional indicator symbols
250 state.setByString("U+1F1FA U+1F1F8 U+1F1FA |");
252 state.assertEquals("U+1F1FA U+1F1F8 |");
254 state.assertEquals("|");
258 public void testEmojiModifier() {
259 EditorState state = new EditorState();
261 // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
262 state.setByString("U+1F466 U+1F3FB |");
264 state.assertEquals("|");
266 // Isolated emoji modifier
267 state.setByString("U+1F3FB |");
269 state.assertEquals("|");
271 // Isolated multiple emoji modifier
272 state.setByString("U+1F3FB U+1F3FB |");
274 state.assertEquals("U+1F3FB |");
276 state.assertEquals("|");
278 // Multiple emoji modifiers
279 state.setByString("U+1F466 U+1F3FB U+1F3FB |");
281 state.assertEquals("U+1F466 U+1F3FB |");
283 state.assertEquals("|");
287 public void testMixedEdgeCases() {
288 EditorState state = new EditorState();
290 // COMBINING ENCLOSING KEYCAP + variation selector
291 state.setByString("'1' U+20E3 U+FE0F |");
293 state.assertEquals("'1' |");
295 state.assertEquals("|");
297 // Variation selector + COMBINING ENCLOSING KEYCAP
298 state.setByString("U+2665 U+FE0F U+20E3 |");
300 state.assertEquals("U+2665 U+FE0F |");
302 state.assertEquals("|");
304 // COMBINING ENCLOSING KEYCAP + ending with ZERO WIDTH JOINER
305 state.setByString("'1' U+20E3 U+200D |");
307 state.assertEquals("'1' U+20E3 |");
309 state.assertEquals("|");
311 // COMBINING ENCLOSING KEYCAP + ZERO WIDTH JOINER
312 state.setByString("'1' U+20E3 U+200D U+1F5E8 |");
314 state.assertEquals("'1' U+20E3 U+200D |");
316 state.assertEquals("'1' U+20E3 |");
318 state.assertEquals("|");
320 // Start with ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
321 state.setByString("U+200D U+20E3 |");
323 state.assertEquals("U+200D |");
325 state.assertEquals("|");
327 // ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
328 state.setByString("U+1F441 U+200D U+20E3 |");
330 state.assertEquals("U+1F441 U+200D |");
332 state.assertEquals("U+1F441 |");
334 state.assertEquals("|");
336 // COMBINING ENCLOSING KEYCAP + regional indicator symbol
337 state.setByString("'1' U+20E3 U+1F1FA |");
339 state.assertEquals("'1' U+20E3 |");
341 state.assertEquals("|");
343 // Regional indicator symbol + COMBINING ENCLOSING KEYCAP
344 state.setByString("U+1F1FA U+20E3 |");
346 state.assertEquals("U+1F1FA |");
348 state.assertEquals("|");
350 // COMBINING ENCLOSING KEYCAP + emoji modifier
351 state.setByString("'1' U+20E3 U+1F3FB |");
353 state.assertEquals("'1' U+20E3 |");
355 state.assertEquals("|");
357 // Emoji modifier + COMBINING ENCLOSING KEYCAP
358 state.setByString("U+1F466 U+1F3FB U+20E3 |");
360 state.assertEquals("U+1f466 U+1F3FB |");
362 state.assertEquals("|");
364 // Variation selector + end with ZERO WIDTH JOINER
365 state.setByString("U+2665 U+FE0F U+200D |");
367 state.assertEquals("U+2665 U+FE0F |");
369 state.assertEquals("|");
371 // Variation selector + ZERO WIDTH JOINER
372 state.setByString("U+1F469 U+200D U+2764 U+FE0F U+200D U+1F469 |");
374 state.assertEquals("|");
376 // Start with ZERO WIDTH JOINER + variation selector
377 state.setByString("U+200D U+FE0F |");
379 state.assertEquals("|");
381 // ZERO WIDTH JOINER + variation selector
382 state.setByString("U+1F469 U+200D U+FE0F |");
384 state.assertEquals("U+1F469 |");
386 state.assertEquals("|");
388 // Variation selector + regional indicator symbol
389 state.setByString("U+2665 U+FE0F U+1F1FA |");
391 state.assertEquals("U+2665 U+FE0F |");
393 state.assertEquals("|");
395 // Regional indicator symbol + variation selector
396 state.setByString("U+1F1FA U+FE0F |");
398 state.assertEquals("|");
400 // Variation selector + emoji modifier
401 state.setByString("U+2665 U+FE0F U+1F3FB |");
403 state.assertEquals("U+2665 U+FE0F |");
405 state.assertEquals("|");
407 // Emoji modifier + variation selector
408 state.setByString("U+1F466 U+1F3FB U+FE0F |");
410 state.assertEquals("U+1F466 |");
412 state.assertEquals("|");
414 // Start withj ZERO WIDTH JOINER + regional indicator symbol
415 state.setByString("U+200D U+1F1FA |");
417 state.assertEquals("U+200D |");
419 state.assertEquals("|");
421 // ZERO WIDTH JOINER + Regional indicator symbol
422 state.setByString("U+1F469 U+200D U+1F1FA |");
424 state.assertEquals("U+1F469 U+200D |");
426 state.assertEquals("U+1F469 |");
428 state.assertEquals("|");
430 // Regional indicator symbol + end with ZERO WIDTH JOINER
431 state.setByString("U+1F1FA U+200D |");
433 state.assertEquals("U+1F1FA |");
435 state.assertEquals("|");
437 // Regional indicator symbol + ZERO WIDTH JOINER
438 state.setByString("U+1F1FA U+200D U+1F469 |");
440 state.assertEquals("|");
442 // Start with ZERO WIDTH JOINER + emoji modifier
443 state.setByString("U+200D U+1F3FB |");
445 state.assertEquals("U+200D |");
447 state.assertEquals("|");
449 // ZERO WIDTH JOINER + emoji modifier
450 state.setByString("U+1F469 U+200D U+1F3FB |");
452 state.assertEquals("U+1F469 U+200D |");
454 state.assertEquals("U+1F469 |");
456 state.assertEquals("|");
458 // Emoji modifier + end with ZERO WIDTH JOINER
459 state.setByString("U+1F466 U+1F3FB U+200D |");
461 state.assertEquals("U+1F466 U+1F3FB |");
463 state.assertEquals("|");
465 // Regional indicator symbol + Emoji modifier
466 state.setByString("U+1F1FA U+1F3FB |");
468 state.assertEquals("U+1F1FA |");
470 state.assertEquals("|");
472 // Emoji modifier + regional indicator symbol
473 state.setByString("U+1F466 U+1F3FB U+1F1FA |");
475 state.assertEquals("U+1F466 U+1F3FB |");
477 state.assertEquals("|");