1 /* 2 * Copyright (C) 2012 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 com.android.inputmethod.latin; 18 19 import android.test.suitebuilder.annotation.LargeTest; 20 import android.view.inputmethod.BaseInputConnection; 21 22 @LargeTest 23 public class InputLogicTests extends InputTestsBase { 24 25 public void testTypeWord() { 26 final String WORD_TO_TYPE = "abcd"; 27 type(WORD_TO_TYPE); 28 assertEquals("type word", WORD_TO_TYPE, mEditText.getText().toString()); 29 } 30 31 public void testPickSuggestionThenBackspace() { 32 final String WORD_TO_TYPE = "this"; 33 final String EXPECTED_RESULT = "thi"; 34 type(WORD_TO_TYPE); 35 pickSuggestionManually(0, WORD_TO_TYPE); 36 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 37 type(Constants.CODE_DELETE); 38 assertEquals("press suggestion then backspace", EXPECTED_RESULT, 39 mEditText.getText().toString()); 40 } 41 42 public void testPickAutoCorrectionThenBackspace() { 43 final String WORD_TO_TYPE = "tgis"; 44 final String WORD_TO_PICK = "this"; 45 final String EXPECTED_RESULT = "thi"; 46 type(WORD_TO_TYPE); 47 // Choose the auto-correction, which is always in position 0. For "tgis", the 48 // auto-correction should be "this". 49 pickSuggestionManually(0, WORD_TO_PICK); 50 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 51 assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK, 52 mEditText.getText().toString()); 53 type(Constants.CODE_DELETE); 54 assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, 55 mEditText.getText().toString()); 56 } 57 58 public void testPickTypedWordOverAutoCorrectionThenBackspace() { 59 final String WORD_TO_TYPE = "tgis"; 60 final String EXPECTED_RESULT = "tgi"; 61 type(WORD_TO_TYPE); 62 // Choose the typed word, which should be in position 1 (because position 0 should 63 // be occupied by the "this" auto-correction, as checked by testAutoCorrect()) 64 pickSuggestionManually(1, WORD_TO_TYPE); 65 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 66 assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE, 67 mEditText.getText().toString()); 68 type(Constants.CODE_DELETE); 69 assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, 70 mEditText.getText().toString()); 71 } 72 73 public void testPickDifferentSuggestionThenBackspace() { 74 final String WORD_TO_TYPE = "tgis"; 75 final String WORD_TO_PICK = "thus"; 76 final String EXPECTED_RESULT = "thu"; 77 type(WORD_TO_TYPE); 78 // Choose the second suggestion, which should be in position 2 and should be "thus" 79 // when "tgis is typed. 80 pickSuggestionManually(2, WORD_TO_PICK); 81 mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); 82 assertEquals("pick different suggestion then backspace", WORD_TO_PICK, 83 mEditText.getText().toString()); 84 type(Constants.CODE_DELETE); 85 assertEquals("pick different suggestion then backspace", EXPECTED_RESULT, 86 mEditText.getText().toString()); 87 } 88 89 public void testDeleteSelection() { 90 final String STRING_TO_TYPE = "some text delete me some text"; 91 final int typedLength = STRING_TO_TYPE.length(); 92 final int SELECTION_START = 10; 93 final int SELECTION_END = 19; 94 final String EXPECTED_RESULT = "some text some text"; 95 type(STRING_TO_TYPE); 96 // There is no IMF to call onUpdateSelection for us so we must do it by hand. 97 // Send once to simulate the cursor actually responding to the move caused by typing. 98 // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor 99 // move with a move triggered by LatinIME inputting stuff. 100 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 101 mInputConnection.setSelection(SELECTION_START, SELECTION_END); 102 // And now we simulate the user actually selecting some text. 103 mLatinIME.onUpdateSelection(typedLength, typedLength, 104 SELECTION_START, SELECTION_END, -1, -1); 105 type(Constants.CODE_DELETE); 106 assertEquals("delete selection", EXPECTED_RESULT, mEditText.getText().toString()); 107 } 108 109 public void testDeleteSelectionTwice() { 110 final String STRING_TO_TYPE = "some text delete me some text"; 111 final int typedLength = STRING_TO_TYPE.length(); 112 final int SELECTION_START = 10; 113 final int SELECTION_END = 19; 114 final String EXPECTED_RESULT = "some text some text"; 115 type(STRING_TO_TYPE); 116 // There is no IMF to call onUpdateSelection for us so we must do it by hand. 117 // Send once to simulate the cursor actually responding to the move caused by typing. 118 // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor 119 // move with a move triggered by LatinIME inputting stuff. 120 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 121 mInputConnection.setSelection(SELECTION_START, SELECTION_END); 122 // And now we simulate the user actually selecting some text. 123 mLatinIME.onUpdateSelection(typedLength, typedLength, 124 SELECTION_START, SELECTION_END, -1, -1); 125 type(Constants.CODE_DELETE); 126 type(Constants.CODE_DELETE); 127 assertEquals("delete selection twice", EXPECTED_RESULT, mEditText.getText().toString()); 128 } 129 130 public void testAutoCorrect() { 131 final String STRING_TO_TYPE = "tgis "; 132 final String EXPECTED_RESULT = "this "; 133 type(STRING_TO_TYPE); 134 assertEquals("simple auto-correct", EXPECTED_RESULT, mEditText.getText().toString()); 135 } 136 137 public void testAutoCorrectWithQuote() { 138 final String STRING_TO_TYPE = "didn' "; 139 final String EXPECTED_RESULT = "didn't "; 140 type(STRING_TO_TYPE); 141 assertEquals("auto-correct with quote", EXPECTED_RESULT, mEditText.getText().toString()); 142 } 143 144 public void testAutoCorrectWithPeriod() { 145 final String STRING_TO_TYPE = "tgis."; 146 final String EXPECTED_RESULT = "this."; 147 type(STRING_TO_TYPE); 148 assertEquals("auto-correct with period", EXPECTED_RESULT, mEditText.getText().toString()); 149 } 150 151 public void testAutoCorrectWithPeriodThenRevert() { 152 final String STRING_TO_TYPE = "tgis."; 153 final String EXPECTED_RESULT = "tgis."; 154 type(STRING_TO_TYPE); 155 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 156 type(Constants.CODE_DELETE); 157 assertEquals("auto-correct with period then revert", EXPECTED_RESULT, 158 mEditText.getText().toString()); 159 } 160 161 public void testAutoCorrectWithSpaceThenRevert() { 162 final String STRING_TO_TYPE = "tgis "; 163 final String EXPECTED_RESULT = "tgis "; 164 type(STRING_TO_TYPE); 165 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 166 type(Constants.CODE_DELETE); 167 assertEquals("auto-correct with space then revert", EXPECTED_RESULT, 168 mEditText.getText().toString()); 169 } 170 171 public void testAutoCorrectToSelfDoesNotRevert() { 172 final String STRING_TO_TYPE = "this "; 173 final String EXPECTED_RESULT = "this"; 174 type(STRING_TO_TYPE); 175 mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); 176 type(Constants.CODE_DELETE); 177 assertEquals("auto-correct with space does not revert", EXPECTED_RESULT, 178 mEditText.getText().toString()); 179 } 180 181 public void testDoubleSpace() { 182 // U+1F607 is an emoji 183 final String[] STRINGS_TO_TYPE = 184 new String[] { "this ", "a+ ", "\u1F607 ", ".. ", ") ", "( ", "% " }; 185 final String[] EXPECTED_RESULTS = 186 new String[] { "this. ", "a+. ", "\u1F607. ", ".. ", "). ", "( ", "%. " }; 187 for (int i = 0; i < STRINGS_TO_TYPE.length; ++i) { 188 mEditText.setText(""); 189 type(STRINGS_TO_TYPE[i]); 190 assertEquals("double space processing", EXPECTED_RESULTS[i], 191 mEditText.getText().toString()); 192 } 193 } 194 195 public void testCancelDoubleSpace() { 196 final String STRING_TO_TYPE = "this "; 197 final String EXPECTED_RESULT = "this "; 198 type(STRING_TO_TYPE); 199 type(Constants.CODE_DELETE); 200 assertEquals("double space make a period", EXPECTED_RESULT, mEditText.getText().toString()); 201 } 202 203 public void testBackspaceAtStartAfterAutocorrect() { 204 final String STRING_TO_TYPE = "tgis "; 205 final int typedLength = STRING_TO_TYPE.length(); 206 final String EXPECTED_RESULT = "this "; 207 final int NEW_CURSOR_POSITION = 0; 208 type(STRING_TO_TYPE); 209 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 210 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 211 mLatinIME.onUpdateSelection(typedLength, typedLength, 212 NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); 213 type(Constants.CODE_DELETE); 214 assertEquals("auto correct then move cursor to start of line then backspace", 215 EXPECTED_RESULT, mEditText.getText().toString()); 216 } 217 218 public void testAutoCorrectThenMoveCursorThenBackspace() { 219 final String STRING_TO_TYPE = "and tgis "; 220 final int typedLength = STRING_TO_TYPE.length(); 221 final String EXPECTED_RESULT = "andthis "; 222 final int NEW_CURSOR_POSITION = STRING_TO_TYPE.indexOf('t'); 223 type(STRING_TO_TYPE); 224 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 225 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 226 mLatinIME.onUpdateSelection(typedLength, typedLength, 227 NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); 228 type(Constants.CODE_DELETE); 229 assertEquals("auto correct then move cursor then backspace", 230 EXPECTED_RESULT, mEditText.getText().toString()); 231 } 232 233 public void testNoSpaceAfterManualPick() { 234 final String WORD_TO_TYPE = "this"; 235 final String EXPECTED_RESULT = WORD_TO_TYPE; 236 type(WORD_TO_TYPE); 237 pickSuggestionManually(0, WORD_TO_TYPE); 238 assertEquals("no space after manual pick", EXPECTED_RESULT, 239 mEditText.getText().toString()); 240 } 241 242 public void testManualPickThenType() { 243 final String WORD1_TO_TYPE = "this"; 244 final String WORD2_TO_TYPE = "is"; 245 final String EXPECTED_RESULT = "this is"; 246 type(WORD1_TO_TYPE); 247 pickSuggestionManually(0, WORD1_TO_TYPE); 248 type(WORD2_TO_TYPE); 249 assertEquals("manual pick then type", EXPECTED_RESULT, mEditText.getText().toString()); 250 } 251 252 public void testManualPickThenSeparator() { 253 final String WORD1_TO_TYPE = "this"; 254 final String WORD2_TO_TYPE = "!"; 255 final String EXPECTED_RESULT = "this!"; 256 type(WORD1_TO_TYPE); 257 pickSuggestionManually(0, WORD1_TO_TYPE); 258 type(WORD2_TO_TYPE); 259 assertEquals("manual pick then separator", EXPECTED_RESULT, mEditText.getText().toString()); 260 } 261 262 public void testManualPickThenStripperThenPick() { 263 final String WORD_TO_TYPE = "this"; 264 final String STRIPPER = "\n"; 265 final String EXPECTED_RESULT = "this\nthis"; 266 type(WORD_TO_TYPE); 267 pickSuggestionManually(0, WORD_TO_TYPE); 268 type(STRIPPER); 269 type(WORD_TO_TYPE); 270 pickSuggestionManually(0, WORD_TO_TYPE); 271 assertEquals("manual pick then \\n then manual pick", EXPECTED_RESULT, 272 mEditText.getText().toString()); 273 } 274 275 public void testManualPickThenSpaceThenType() { 276 final String WORD1_TO_TYPE = "this"; 277 final String WORD2_TO_TYPE = " is"; 278 final String EXPECTED_RESULT = "this is"; 279 type(WORD1_TO_TYPE); 280 pickSuggestionManually(0, WORD1_TO_TYPE); 281 type(WORD2_TO_TYPE); 282 assertEquals("manual pick then space then type", EXPECTED_RESULT, 283 mEditText.getText().toString()); 284 } 285 286 public void testManualPickThenManualPick() { 287 final String WORD1_TO_TYPE = "this"; 288 final String WORD2_TO_PICK = "is"; 289 final String EXPECTED_RESULT = "this is"; 290 type(WORD1_TO_TYPE); 291 pickSuggestionManually(0, WORD1_TO_TYPE); 292 // Here we fake picking a word through bigram prediction. This test is taking 293 // advantage of the fact that Latin IME blindly trusts the caller of #pickSuggestionManually 294 // to actually pass the right string. 295 pickSuggestionManually(1, WORD2_TO_PICK); 296 assertEquals("manual pick then manual pick", EXPECTED_RESULT, 297 mEditText.getText().toString()); 298 } 299 300 public void testDeleteWholeComposingWord() { 301 final String WORD_TO_TYPE = "this"; 302 type(WORD_TO_TYPE); 303 for (int i = 0; i < WORD_TO_TYPE.length(); ++i) { 304 type(Constants.CODE_DELETE); 305 } 306 assertEquals("delete whole composing word", "", mEditText.getText().toString()); 307 } 308 309 public void testResumeSuggestionOnBackspace() { 310 final String WORD_TO_TYPE = "and this "; 311 type(WORD_TO_TYPE); 312 assertEquals("resume suggestion on backspace", -1, 313 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 314 assertEquals("resume suggestion on backspace", -1, 315 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 316 type(Constants.CODE_DELETE); 317 assertEquals("resume suggestion on backspace", 4, 318 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 319 assertEquals("resume suggestion on backspace", 8, 320 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 321 } 322 323 private void helperTestComposing(final String wordToType, final boolean shouldBeComposing) { 324 mEditText.setText(""); 325 type(wordToType); 326 assertEquals("start composing inside text", shouldBeComposing ? 0 : -1, 327 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 328 assertEquals("start composing inside text", shouldBeComposing ? wordToType.length() : -1, 329 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 330 } 331 332 public void testStartComposing() { 333 // Should start composing on a letter 334 helperTestComposing("a", true); 335 type(" "); // To reset the composing state 336 // Should not start composing on quote 337 helperTestComposing("'", false); 338 type(" "); 339 helperTestComposing("'-", false); 340 type(" "); 341 // Should not start composing on dash 342 helperTestComposing("-", false); 343 type(" "); 344 helperTestComposing("-'", false); 345 type(" "); 346 helperTestComposing("a-", true); 347 type(" "); 348 helperTestComposing("a'", true); 349 } 350 // TODO: Add some tests for non-BMP characters 351 } 352