1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 package android.text.method.cts; 18 19 import static org.junit.Assert.assertTrue; 20 21 import android.support.test.filters.MediumTest; 22 import android.support.test.runner.AndroidJUnit4; 23 import android.text.InputType; 24 import android.text.method.BaseKeyListener; 25 import android.view.KeyEvent; 26 import android.widget.TextView.BufferType; 27 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 31 /** 32 * Test forward delete key handling of {@link android.text.method.BaseKeyListener}. 33 */ 34 @MediumTest 35 @RunWith(AndroidJUnit4.class) 36 public class ForwardDeleteTest extends KeyListenerTestCase { 37 private static final BaseKeyListener mKeyListener = new BaseKeyListener() { 38 public int getInputType() { 39 return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL; 40 } 41 }; 42 43 // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event. 44 // Then update the state to the result of TextView. 45 private void forwardDelete(final EditorState state, int modifiers) throws Throwable { 46 mActivityRule.runOnUiThread(() -> { 47 mTextView.setText(state.mText, BufferType.EDITABLE); 48 mTextView.setKeyListener(mKeyListener); 49 mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd); 50 }); 51 mInstrumentation.waitForIdleSync(); 52 assertTrue(mTextView.hasWindowFocus()); 53 54 final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers); 55 mActivity.runOnUiThread(() -> mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent)); 56 mInstrumentation.waitForIdleSync(); 57 58 state.mText = mTextView.getText(); 59 state.mSelectionStart = mTextView.getSelectionStart(); 60 state.mSelectionEnd = mTextView.getSelectionEnd(); 61 } 62 63 @Test 64 public void testCRLF() throws Throwable { 65 EditorState state = new EditorState(); 66 67 // U+000A is LINE FEED. 68 state.setByString("| U+000A"); 69 forwardDelete(state, 0); 70 state.assertEquals("|"); 71 72 // U+000D is CARRIAGE RETURN. 73 state.setByString("| U+000D"); 74 forwardDelete(state, 0); 75 state.assertEquals("|"); 76 77 state.setByString("| U+000D U+000A"); 78 forwardDelete(state, 0); 79 state.assertEquals("|"); 80 81 state.setByString("| U+000A U+000D"); 82 forwardDelete(state, 0); 83 state.assertEquals("| U+000D"); 84 forwardDelete(state, 0); 85 } 86 87 @Test 88 public void testSurrogatePairs() throws Throwable { 89 EditorState state = new EditorState(); 90 91 // U+1F441 is EYE 92 state.setByString("| U+1F441"); 93 forwardDelete(state, 0); 94 state.assertEquals("|"); 95 96 // U+1F5E8 is LEFT SPEECH BUBBLE 97 state.setByString("| U+1F441 U+1F5E8"); 98 forwardDelete(state, 0); 99 state.assertEquals("| U+1F5E8"); 100 forwardDelete(state, 0); 101 state.assertEquals("|"); 102 } 103 104 @Test 105 public void testReplacementSpan() throws Throwable { 106 EditorState state = new EditorState(); 107 108 state.setByString("| 'abc' ( 'de' ) 'fg'"); 109 forwardDelete(state, 0); 110 state.assertEquals("| 'bc' ( 'de' ) 'fg'"); 111 forwardDelete(state, 0); 112 state.assertEquals("| 'c' ( 'de' ) 'fg'"); 113 forwardDelete(state, 0); 114 state.assertEquals("| ( 'de' ) 'fg'"); 115 forwardDelete(state, 0); 116 state.assertEquals("| 'fg'"); 117 forwardDelete(state, 0); 118 state.assertEquals("| 'g'"); 119 forwardDelete(state, 0); 120 state.assertEquals("|"); 121 122 state.setByString("'abc' [ ( 'de' ) ] 'fg'"); 123 forwardDelete(state, 0); 124 state.assertEquals("'abc' | 'fg'"); 125 forwardDelete(state, 0); 126 state.assertEquals("'abc' | 'g'"); 127 forwardDelete(state, 0); 128 state.assertEquals("'abc' |"); 129 forwardDelete(state, 0); 130 state.assertEquals("'abc' |"); 131 132 state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'"); 133 forwardDelete(state, 0); 134 state.assertEquals("'ab' | 'g'"); 135 forwardDelete(state, 0); 136 state.assertEquals("'ab' |"); 137 forwardDelete(state, 0); 138 state.assertEquals("'ab' |"); 139 } 140 141 @Test 142 public void testCombiningEnclosingKeycaps() throws Throwable { 143 EditorState state = new EditorState(); 144 145 // U+20E3 is COMBINING ENCLOSING KEYCAP. 146 state.setByString("| '1' U+20E3"); 147 forwardDelete(state, 0); 148 state.assertEquals("|"); 149 150 state.setByString("| '1' U+FE0F U+20E3"); 151 forwardDelete(state, 0); 152 state.assertEquals("|"); 153 } 154 155 @Test 156 public void testVariationSelector() throws Throwable { 157 EditorState state = new EditorState(); 158 159 // U+FE0F is VARIATION SELECTOR-16. 160 state.setByString("| '#' U+FE0F"); 161 forwardDelete(state, 0); 162 state.assertEquals("|"); 163 164 // U+E0100 is VARIATION SELECTOR-17. 165 state.setByString("| U+845B U+E0100"); 166 forwardDelete(state, 0); 167 state.assertEquals("|"); 168 } 169 170 @Test 171 public void testFlags() throws Throwable { 172 EditorState state = new EditorState(); 173 174 // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U. 175 // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S. 176 state.setByString("| U+1F1FA U+1F1F8"); 177 forwardDelete(state, 0); 178 state.assertEquals("|"); 179 180 state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8"); 181 forwardDelete(state, 0); 182 state.assertEquals("| U+1F1FA U+1F1F8"); 183 forwardDelete(state, 0); 184 state.assertEquals("|"); 185 186 // Single tag_base character 187 // U+1F3F4 is WAVING BLACK FLAG. This can be a tag_base character. 188 state.setByString("| 'a' U+1F3F4 U+1F3F4 'b'"); 189 forwardDelete(state, 0); 190 state.assertEquals("| U+1F3F4 U+1F3F4 'b'"); 191 forwardDelete(state, 0); 192 state.assertEquals("| U+1F3F4 'b'"); 193 forwardDelete(state, 0); 194 state.assertEquals("| 'b'"); 195 196 // U+E0067 is TAG LATIN SMALL LETTER G. This can be a part of tag_spec. 197 // U+E0062 is TAG LATIN SMALL LETTER B. This can be a part of tag_spec. 198 // U+E0073 is TAG LATIN SMALL LETTER S. This can be a part of tag_spec. 199 // U+E0063 is TAG LATIN SMALL LETTER C. This can be a part of tag_spec. 200 // U+E0074 is TAG LATIN SMALL LETTER T. This can be a part of tag_spec. 201 // U+E007F is CANCEL TAG. This is a tag_term character. 202 final String scotland = "U+1F3F4 U+E0067 U+E0062 U+E0073 U+E0063 U+E0074 U+E007F "; 203 204 state.setByString("| 'a' " + scotland + scotland + "'b'"); 205 forwardDelete(state, 0); 206 state.assertEquals("| " + scotland + scotland + "'b'"); 207 forwardDelete(state, 0); 208 state.assertEquals("| " + scotland + "'b'"); 209 forwardDelete(state, 0); 210 state.assertEquals("| 'b'"); 211 } 212 } 213