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