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