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 static android.test.MoreAsserts.assertNotEqual; 20 21 import android.text.TextUtils; 22 import android.view.inputmethod.BaseInputConnection; 23 24 import androidx.test.filters.LargeTest; 25 26 import com.android.inputmethod.latin.common.Constants; 27 import com.android.inputmethod.latin.define.DecoderSpecificConstants; 28 import com.android.inputmethod.latin.settings.Settings; 29 30 @LargeTest 31 public class InputLogicTests extends InputTestsBase { 32 33 private boolean mNextWordPrediction; 34 35 @Override setUp()36 public void setUp() throws Exception { 37 super.setUp(); 38 mNextWordPrediction = getBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, true); 39 } 40 41 @Override tearDown()42 public void tearDown() throws Exception { 43 setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, mNextWordPrediction, true); 44 super.tearDown(); 45 } 46 testTypeWord()47 public void testTypeWord() { 48 final String WORD_TO_TYPE = "abcd"; 49 type(WORD_TO_TYPE); 50 assertEquals("type word", WORD_TO_TYPE, mEditText.getText().toString()); 51 } 52 testPickSuggestionThenBackspace()53 public void testPickSuggestionThenBackspace() { 54 final String WORD_TO_TYPE = "this"; 55 final String EXPECTED_RESULT = "thi"; 56 type(WORD_TO_TYPE); 57 pickSuggestionManually(WORD_TO_TYPE); 58 sendUpdateForCursorMoveTo(WORD_TO_TYPE.length()); 59 type(Constants.CODE_DELETE); 60 assertEquals("press suggestion then backspace", EXPECTED_RESULT, 61 mEditText.getText().toString()); 62 } 63 testPickAutoCorrectionThenBackspace()64 public void testPickAutoCorrectionThenBackspace() { 65 final String WORD_TO_TYPE = "tgis"; 66 final String WORD_TO_PICK = "this"; 67 final String EXPECTED_RESULT = "thi"; 68 type(WORD_TO_TYPE); 69 // Choose the auto-correction. For "tgis", the auto-correction should be "this". 70 pickSuggestionManually(WORD_TO_PICK); 71 sendUpdateForCursorMoveTo(WORD_TO_TYPE.length()); 72 assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK, 73 mEditText.getText().toString()); 74 type(Constants.CODE_DELETE); 75 assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, 76 mEditText.getText().toString()); 77 } 78 testPickTypedWordOverAutoCorrectionThenBackspace()79 public void testPickTypedWordOverAutoCorrectionThenBackspace() { 80 final String WORD_TO_TYPE = "tgis"; 81 final String EXPECTED_RESULT = "tgi"; 82 type(WORD_TO_TYPE); 83 // Choose the typed word. 84 pickSuggestionManually(WORD_TO_TYPE); 85 sendUpdateForCursorMoveTo(WORD_TO_TYPE.length()); 86 assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE, 87 mEditText.getText().toString()); 88 type(Constants.CODE_DELETE); 89 assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, 90 mEditText.getText().toString()); 91 } 92 testPickDifferentSuggestionThenBackspace()93 public void testPickDifferentSuggestionThenBackspace() { 94 final String WORD_TO_TYPE = "tgis"; 95 final String WORD_TO_PICK = "thus"; 96 final String EXPECTED_RESULT = "thu"; 97 type(WORD_TO_TYPE); 98 // Choose the second suggestion, which should be "thus" when "tgis" is typed. 99 pickSuggestionManually(WORD_TO_PICK); 100 sendUpdateForCursorMoveTo(WORD_TO_TYPE.length()); 101 assertEquals("pick different suggestion then backspace", WORD_TO_PICK, 102 mEditText.getText().toString()); 103 type(Constants.CODE_DELETE); 104 assertEquals("pick different suggestion then backspace", EXPECTED_RESULT, 105 mEditText.getText().toString()); 106 } 107 testDeleteSelection()108 public void testDeleteSelection() { 109 final String STRING_TO_TYPE = "some text delete me some text"; 110 final int typedLength = STRING_TO_TYPE.length(); 111 final int SELECTION_START = 10; 112 final int SELECTION_END = 19; 113 final String EXPECTED_RESULT = "some text some text"; 114 type(STRING_TO_TYPE); 115 // Don't use the sendUpdateForCursorMove* family of methods here because they 116 // don't handle selections. 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 assertEquals("delete selection", EXPECTED_RESULT, mEditText.getText().toString()); 127 } 128 testDeleteSelectionTwice()129 public void testDeleteSelectionTwice() { 130 final String STRING_TO_TYPE = "some text delete me some text"; 131 final int typedLength = STRING_TO_TYPE.length(); 132 final int SELECTION_START = 10; 133 final int SELECTION_END = 19; 134 final String EXPECTED_RESULT = "some text some text"; 135 type(STRING_TO_TYPE); 136 // Don't use the sendUpdateForCursorMove* family of methods here because they 137 // don't handle selections. 138 // Send once to simulate the cursor actually responding to the move caused by typing. 139 // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor 140 // move with a move triggered by LatinIME inputting stuff. 141 mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1); 142 mInputConnection.setSelection(SELECTION_START, SELECTION_END); 143 // And now we simulate the user actually selecting some text. 144 mLatinIME.onUpdateSelection(typedLength, typedLength, 145 SELECTION_START, SELECTION_END, -1, -1); 146 type(Constants.CODE_DELETE); 147 type(Constants.CODE_DELETE); 148 assertEquals("delete selection twice", EXPECTED_RESULT, mEditText.getText().toString()); 149 } 150 testAutoCorrect()151 public void testAutoCorrect() { 152 final String STRING_TO_TYPE = "tgis "; 153 final String EXPECTED_RESULT = "this "; 154 type(STRING_TO_TYPE); 155 assertEquals("simple auto-correct", EXPECTED_RESULT, mEditText.getText().toString()); 156 } 157 testAutoCorrectWithQuote()158 public void testAutoCorrectWithQuote() { 159 final String STRING_TO_TYPE = "didn' "; 160 final String EXPECTED_RESULT = "didn't "; 161 type(STRING_TO_TYPE); 162 assertEquals("auto-correct with quote", EXPECTED_RESULT, mEditText.getText().toString()); 163 } 164 testAutoCorrectWithPeriod()165 public void testAutoCorrectWithPeriod() { 166 final String STRING_TO_TYPE = "tgis."; 167 final String EXPECTED_RESULT = "this."; 168 type(STRING_TO_TYPE); 169 assertEquals("auto-correct with period", EXPECTED_RESULT, mEditText.getText().toString()); 170 } 171 testAutoCorrectWithPeriodThenRevert()172 public void testAutoCorrectWithPeriodThenRevert() { 173 final String STRING_TO_TYPE = "tgis."; 174 final String EXPECTED_RESULT = "tgis."; 175 type(STRING_TO_TYPE); 176 sendUpdateForCursorMoveTo(STRING_TO_TYPE.length()); 177 type(Constants.CODE_DELETE); 178 assertEquals("auto-correct with period then revert", EXPECTED_RESULT, 179 mEditText.getText().toString()); 180 } 181 testAutoCorrectWithSpaceThenRevert()182 public void testAutoCorrectWithSpaceThenRevert() { 183 // Backspacing to cancel the "tgis"->"this" autocorrection should result in 184 // a "phantom space": if the user presses space immediately after, 185 // only one space will be inserted in total. 186 final String STRING_TO_TYPE = "tgis "; 187 final String EXPECTED_RESULT = "tgis"; 188 type(STRING_TO_TYPE); 189 sendUpdateForCursorMoveTo(STRING_TO_TYPE.length()); 190 type(Constants.CODE_DELETE); 191 assertEquals("auto-correct with space then revert", EXPECTED_RESULT, 192 mEditText.getText().toString()); 193 } 194 testAutoCorrectWithSpaceThenRevertThenTypeMore()195 public void testAutoCorrectWithSpaceThenRevertThenTypeMore() { 196 final String STRING_TO_TYPE_FIRST = "tgis "; 197 final String STRING_TO_TYPE_SECOND = "a"; 198 final String EXPECTED_RESULT = "tgis a"; 199 type(STRING_TO_TYPE_FIRST); 200 sendUpdateForCursorMoveTo(STRING_TO_TYPE_FIRST.length()); 201 type(Constants.CODE_DELETE); 202 203 type(STRING_TO_TYPE_SECOND); 204 sendUpdateForCursorMoveTo(STRING_TO_TYPE_FIRST.length() - 1 205 + STRING_TO_TYPE_SECOND.length()); 206 assertEquals("auto-correct with space then revert then type more", EXPECTED_RESULT, 207 mEditText.getText().toString()); 208 } 209 testAutoCorrectToSelfDoesNotRevert()210 public void testAutoCorrectToSelfDoesNotRevert() { 211 final String STRING_TO_TYPE = "this "; 212 final String EXPECTED_RESULT = "this"; 213 type(STRING_TO_TYPE); 214 sendUpdateForCursorMoveTo(STRING_TO_TYPE.length()); 215 type(Constants.CODE_DELETE); 216 assertEquals("auto-correct with space does not revert", EXPECTED_RESULT, 217 mEditText.getText().toString()); 218 } 219 testDoubleSpace()220 public void testDoubleSpace() { 221 // U+1F607 is an emoji 222 final String[] STRINGS_TO_TYPE = 223 new String[] { "this ", "a+ ", "\u1F607 ", ".. ", ") ", "( ", "% " }; 224 final String[] EXPECTED_RESULTS = 225 new String[] { "this. ", "a+. ", "\u1F607. ", ".. ", "). ", "( ", "%. " }; 226 verifyDoubleSpace(STRINGS_TO_TYPE, EXPECTED_RESULTS); 227 } 228 testDoubleSpaceHindi()229 public void testDoubleSpaceHindi() { 230 changeLanguage("hi"); 231 // U+1F607 is an emoji 232 final String[] STRINGS_TO_TYPE = 233 new String[] { "this ", "a+ ", "\u1F607 ", "|| ", ") ", "( ", "% " }; 234 final String[] EXPECTED_RESULTS = 235 new String[] { "this| ", "a+| ", "\u1F607| ", "|| ", ")| ", "( ", "%| " }; 236 verifyDoubleSpace(STRINGS_TO_TYPE, EXPECTED_RESULTS); 237 } 238 verifyDoubleSpace(String[] stringsToType, String[] expectedResults)239 private void verifyDoubleSpace(String[] stringsToType, String[] expectedResults) { 240 // Set default pref just in case 241 setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true); 242 for (int i = 0; i < stringsToType.length; ++i) { 243 mEditText.setText(""); 244 type(stringsToType[i]); 245 assertEquals("double space processing", expectedResults[i], 246 mEditText.getText().toString()); 247 } 248 } 249 testCancelDoubleSpaceEnglish()250 public void testCancelDoubleSpaceEnglish() { 251 final String STRING_TO_TYPE = "this "; 252 final String EXPECTED_RESULT = "this "; 253 type(STRING_TO_TYPE); 254 type(Constants.CODE_DELETE); 255 assertEquals("double space make a period", EXPECTED_RESULT, mEditText.getText().toString()); 256 } 257 testCancelDoubleSpaceHindi()258 public void testCancelDoubleSpaceHindi() { 259 changeLanguage("hi"); 260 final String STRING_TO_TYPE = "this "; 261 final String EXPECTED_RESULT = "this "; 262 type(STRING_TO_TYPE); 263 type(Constants.CODE_DELETE); 264 assertEquals("double space make a period", EXPECTED_RESULT, mEditText.getText().toString()); 265 } 266 testDoubleSpacePeriodWithSettings(final boolean expectsPeriod, final Object... settingsKeysValues)267 private void testDoubleSpacePeriodWithSettings(final boolean expectsPeriod, 268 final Object... settingsKeysValues) { 269 final Object[] oldSettings = new Object[settingsKeysValues.length / 2]; 270 final String STRING_WITHOUT_PERIOD = "this "; 271 final String STRING_WITH_PERIOD = "this. "; 272 final String EXPECTED_RESULT = expectsPeriod ? STRING_WITH_PERIOD : STRING_WITHOUT_PERIOD; 273 try { 274 for (int i = 0; i < settingsKeysValues.length; i += 2) { 275 if (settingsKeysValues[i + 1] instanceof String) { 276 oldSettings[i / 2] = setStringPreference((String)settingsKeysValues[i], 277 (String)settingsKeysValues[i + 1], "0"); 278 } else { 279 oldSettings[i / 2] = setBooleanPreference((String)settingsKeysValues[i], 280 (Boolean)settingsKeysValues[i + 1], false); 281 } 282 } 283 mLatinIME.loadSettings(); 284 mEditText.setText(""); 285 type(STRING_WITHOUT_PERIOD); 286 assertEquals("double-space-to-period with specific settings " 287 + TextUtils.join(" ", settingsKeysValues), 288 EXPECTED_RESULT, mEditText.getText().toString()); 289 } finally { 290 // Restore old settings 291 for (int i = 0; i < settingsKeysValues.length; i += 2) { 292 if (null == oldSettings[i / 2]) { 293 break; 294 } if (oldSettings[i / 2] instanceof String) { 295 setStringPreference((String)settingsKeysValues[i], (String)oldSettings[i / 2], 296 ""); 297 } else { 298 setBooleanPreference((String)settingsKeysValues[i], (Boolean)oldSettings[i / 2], 299 false); 300 } 301 } 302 } 303 } 304 testDoubleSpacePeriod()305 public void testDoubleSpacePeriod() { 306 // Reset settings to default, else these tests will go flaky. 307 setBooleanPreference(Settings.PREF_SHOW_SUGGESTIONS, true, true); 308 setBooleanPreference(Settings.PREF_AUTO_CORRECTION, true, true); 309 setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true); 310 testDoubleSpacePeriodWithSettings(true); 311 // "Suggestion visibility" to off 312 testDoubleSpacePeriodWithSettings(true, Settings.PREF_SHOW_SUGGESTIONS, false); 313 // "Suggestion visibility" to on 314 testDoubleSpacePeriodWithSettings(true, Settings.PREF_SHOW_SUGGESTIONS, true); 315 316 // "Double-space period" to "off" 317 testDoubleSpacePeriodWithSettings(false, Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, false); 318 319 // "Auto-correction" to "off" 320 testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION, false); 321 // "Auto-correction" to "on" 322 testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION, true); 323 324 // "Suggestion visibility" to "always hide" and "Auto-correction" to "off" 325 testDoubleSpacePeriodWithSettings(true, Settings.PREF_SHOW_SUGGESTIONS, false, 326 Settings.PREF_AUTO_CORRECTION, false); 327 // "Suggestion visibility" to "always hide" and "Auto-correction" to "off" 328 testDoubleSpacePeriodWithSettings(false, Settings.PREF_SHOW_SUGGESTIONS, false, 329 Settings.PREF_AUTO_CORRECTION, false, 330 Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, false); 331 } 332 testBackspaceAtStartAfterAutocorrect()333 public void testBackspaceAtStartAfterAutocorrect() { 334 final String STRING_TO_TYPE = "tgis "; 335 final int typedLength = STRING_TO_TYPE.length(); 336 final String EXPECTED_RESULT = "this "; 337 final int NEW_CURSOR_POSITION = 0; 338 type(STRING_TO_TYPE); 339 sendUpdateForCursorMoveTo(typedLength); 340 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 341 sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION); 342 type(Constants.CODE_DELETE); 343 assertEquals("auto correct then move cursor to start of line then backspace", 344 EXPECTED_RESULT, mEditText.getText().toString()); 345 } 346 testAutoCorrectThenMoveCursorThenBackspace()347 public void testAutoCorrectThenMoveCursorThenBackspace() { 348 final String STRING_TO_TYPE = "and tgis "; 349 final int typedLength = STRING_TO_TYPE.length(); 350 final String EXPECTED_RESULT = "andthis "; 351 final int NEW_CURSOR_POSITION = STRING_TO_TYPE.indexOf('t'); 352 type(STRING_TO_TYPE); 353 sendUpdateForCursorMoveTo(typedLength); 354 mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); 355 sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION); 356 type(Constants.CODE_DELETE); 357 assertEquals("auto correct then move cursor then backspace", 358 EXPECTED_RESULT, mEditText.getText().toString()); 359 } 360 testNoSpaceAfterManualPick()361 public void testNoSpaceAfterManualPick() { 362 final String WORD_TO_TYPE = "this"; 363 final String EXPECTED_RESULT = WORD_TO_TYPE; 364 type(WORD_TO_TYPE); 365 pickSuggestionManually(WORD_TO_TYPE); 366 assertEquals("no space after manual pick", EXPECTED_RESULT, 367 mEditText.getText().toString()); 368 } 369 testManualPickThenType()370 public void testManualPickThenType() { 371 final String WORD1_TO_TYPE = "this"; 372 final String WORD2_TO_TYPE = "is"; 373 final String EXPECTED_RESULT = "this is"; 374 type(WORD1_TO_TYPE); 375 pickSuggestionManually(WORD1_TO_TYPE); 376 type(WORD2_TO_TYPE); 377 assertEquals("manual pick then type", EXPECTED_RESULT, mEditText.getText().toString()); 378 } 379 testManualPickThenSeparator()380 public void testManualPickThenSeparator() { 381 final String WORD1_TO_TYPE = "this"; 382 final String WORD2_TO_TYPE = "!"; 383 final String EXPECTED_RESULT = "this!"; 384 type(WORD1_TO_TYPE); 385 pickSuggestionManually(WORD1_TO_TYPE); 386 type(WORD2_TO_TYPE); 387 assertEquals("manual pick then separator", EXPECTED_RESULT, mEditText.getText().toString()); 388 } 389 390 // This test matches testClusteringPunctuationForFrench. 391 // In some non-English languages, ! and ? are clustering punctuation signs. testClusteringPunctuation()392 public void testClusteringPunctuation() { 393 final String WORD1_TO_TYPE = "test"; 394 final String WORD2_TO_TYPE = "!!?!:!"; 395 final String EXPECTED_RESULT = "test!!?!:!"; 396 type(WORD1_TO_TYPE); 397 pickSuggestionManually(WORD1_TO_TYPE); 398 type(WORD2_TO_TYPE); 399 assertEquals("clustering punctuation", EXPECTED_RESULT, mEditText.getText().toString()); 400 } 401 testManualPickThenStripperThenPick()402 public void testManualPickThenStripperThenPick() { 403 final String WORD_TO_TYPE = "this"; 404 final String STRIPPER = "\n"; 405 final String EXPECTED_RESULT = "this\nthis"; 406 type(WORD_TO_TYPE); 407 pickSuggestionManually(WORD_TO_TYPE); 408 type(STRIPPER); 409 type(WORD_TO_TYPE); 410 pickSuggestionManually(WORD_TO_TYPE); 411 assertEquals("manual pick then \\n then manual pick", EXPECTED_RESULT, 412 mEditText.getText().toString()); 413 } 414 testManualPickThenSpaceThenType()415 public void testManualPickThenSpaceThenType() { 416 final String WORD1_TO_TYPE = "this"; 417 final String WORD2_TO_TYPE = " is"; 418 final String EXPECTED_RESULT = "this is"; 419 type(WORD1_TO_TYPE); 420 pickSuggestionManually(WORD1_TO_TYPE); 421 type(WORD2_TO_TYPE); 422 assertEquals("manual pick then space then type", EXPECTED_RESULT, 423 mEditText.getText().toString()); 424 } 425 testManualPickThenManualPick()426 public void testManualPickThenManualPick() { 427 final String WORD1_TO_TYPE = "this"; 428 final String WORD2_TO_PICK = "is"; 429 final String EXPECTED_RESULT = "this is"; 430 type(WORD1_TO_TYPE); 431 pickSuggestionManually(WORD1_TO_TYPE); 432 // Here we fake picking a word through bigram prediction. 433 pickSuggestionManually(WORD2_TO_PICK); 434 assertEquals("manual pick then manual pick", EXPECTED_RESULT, 435 mEditText.getText().toString()); 436 } 437 testDeleteWholeComposingWord()438 public void testDeleteWholeComposingWord() { 439 final String WORD_TO_TYPE = "this"; 440 type(WORD_TO_TYPE); 441 for (int i = 0; i < WORD_TO_TYPE.length(); ++i) { 442 type(Constants.CODE_DELETE); 443 } 444 assertEquals("delete whole composing word", "", mEditText.getText().toString()); 445 } 446 testResumeSuggestionOnBackspace()447 public void testResumeSuggestionOnBackspace() { 448 final String STRING_TO_TYPE = "and this "; 449 final int typedLength = STRING_TO_TYPE.length(); 450 type(STRING_TO_TYPE); 451 assertEquals("resume suggestion on backspace", -1, 452 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 453 assertEquals("resume suggestion on backspace", -1, 454 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 455 sendUpdateForCursorMoveTo(typedLength); 456 type(Constants.CODE_DELETE); 457 assertEquals("resume suggestion on backspace", 4, 458 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 459 assertEquals("resume suggestion on backspace", 8, 460 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 461 } 462 helperTestComposing(final String wordToType, final boolean shouldBeComposing)463 private void helperTestComposing(final String wordToType, final boolean shouldBeComposing) { 464 mEditText.setText(""); 465 type(wordToType); 466 assertEquals("start composing inside text", shouldBeComposing ? 0 : -1, 467 BaseInputConnection.getComposingSpanStart(mEditText.getText())); 468 assertEquals("start composing inside text", shouldBeComposing ? wordToType.length() : -1, 469 BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 470 } 471 testStartComposing()472 public void testStartComposing() { 473 // Should start composing on a letter 474 helperTestComposing("a", true); 475 type(" "); // To reset the composing state 476 // Should not start composing on quote 477 helperTestComposing("'", false); 478 type(" "); 479 helperTestComposing("'-", false); 480 type(" "); 481 // Should not start composing on dash 482 helperTestComposing("-", false); 483 type(" "); 484 helperTestComposing("-'", false); 485 type(" "); 486 helperTestComposing("a-", true); 487 type(" "); 488 helperTestComposing("a'", true); 489 } 490 491 // TODO: Add some tests for non-BMP characters 492 testAutoCorrectByUserHistory()493 public void testAutoCorrectByUserHistory() { 494 type("qpmz"); 495 type(Constants.CODE_SPACE); 496 497 int startIndex = mEditText.getText().length(); 498 type("qpmx"); 499 type(Constants.CODE_SPACE); 500 int endIndex = mEditText.getText().length(); 501 assertEquals("auto-corrected by user history", 502 "qpmz ", mEditText.getText().subSequence(startIndex, endIndex).toString()); 503 } 504 testPredictionsAfterSpace()505 public void testPredictionsAfterSpace() { 506 final String WORD_TO_TYPE = "Barack "; 507 type(WORD_TO_TYPE); 508 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 509 runMessages(); 510 // Test the first prediction is displayed 511 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 512 assertEquals("predictions after space", "Obama", 513 suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); 514 } 515 testPredictionsWithDoubleSpaceToPeriod()516 public void testPredictionsWithDoubleSpaceToPeriod() { 517 mLatinIME.clearPersonalizedDictionariesForTest(); 518 final String WORD_TO_TYPE = "Barack "; 519 type(WORD_TO_TYPE); 520 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 521 runMessages(); 522 523 type(Constants.CODE_DELETE); 524 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 525 runMessages(); 526 527 SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 528 suggestedWords = mLatinIME.getSuggestedWordsForTest(); 529 assertEquals("predictions after cancel double-space-to-period", "Obama", 530 mLatinIME.getSuggestedWordsForTest().getWord(0)); 531 } 532 testPredictionsAfterManualPick()533 public void testPredictionsAfterManualPick() { 534 final String WORD_TO_TYPE = "Barack"; 535 type(WORD_TO_TYPE); 536 // Choose the auto-correction. For "Barack", the auto-correction should be "Barack". 537 pickSuggestionManually(WORD_TO_TYPE); 538 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 539 runMessages(); 540 // Test the first prediction is displayed 541 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 542 assertEquals("predictions after manual pick", "Obama", 543 suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); 544 } 545 testPredictionsAfterPeriod()546 public void testPredictionsAfterPeriod() { 547 mLatinIME.clearPersonalizedDictionariesForTest(); 548 final String WORD_TO_TYPE = "Barack. "; 549 type(WORD_TO_TYPE); 550 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 551 runMessages(); 552 553 SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 554 assertFalse(mLatinIME.getSuggestedWordsForTest().isEmpty()); 555 } 556 testPredictionsAfterRecorrection()557 public void testPredictionsAfterRecorrection() { 558 final String PREFIX = "A "; 559 final String WORD_TO_TYPE = "Barack"; 560 final String FIRST_NON_TYPED_SUGGESTION = "Barrack"; 561 final int endOfPrefix = PREFIX.length(); 562 final int endOfWord = endOfPrefix + WORD_TO_TYPE.length(); 563 final int endOfSuggestion = endOfPrefix + FIRST_NON_TYPED_SUGGESTION.length(); 564 final int indexForManualCursor = endOfPrefix + 3; // +3 because it's after "Bar" in "Barack" 565 type(PREFIX); 566 sendUpdateForCursorMoveTo(endOfPrefix); 567 type(WORD_TO_TYPE); 568 pickSuggestionManually(FIRST_NON_TYPED_SUGGESTION); 569 sendUpdateForCursorMoveTo(endOfSuggestion); 570 runMessages(); 571 type(" "); 572 sendUpdateForCursorMoveBy(1); 573 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 574 runMessages(); 575 // Simulate a manual cursor move 576 mInputConnection.setSelection(indexForManualCursor, indexForManualCursor); 577 sendUpdateForCursorMoveTo(indexForManualCursor); 578 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 579 runMessages(); 580 pickSuggestionManually(WORD_TO_TYPE); 581 sendUpdateForCursorMoveTo(endOfWord); 582 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 583 runMessages(); 584 // Test the first prediction is displayed 585 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 586 assertEquals("predictions after recorrection", "Obama", 587 suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); 588 } 589 testComposingMultipleBackspace()590 public void testComposingMultipleBackspace() { 591 final String WORD_TO_TYPE = "radklro"; 592 final int TIMES_TO_TYPE = 3; 593 final int TIMES_TO_BACKSPACE = 8; 594 type(WORD_TO_TYPE); 595 type(Constants.CODE_DELETE); 596 type(Constants.CODE_DELETE); 597 type(Constants.CODE_DELETE); 598 type(WORD_TO_TYPE); 599 type(Constants.CODE_DELETE); 600 type(Constants.CODE_DELETE); 601 type(WORD_TO_TYPE); 602 type(Constants.CODE_DELETE); 603 type(Constants.CODE_DELETE); 604 type(Constants.CODE_DELETE); 605 assertEquals("composing with multiple backspace", 606 WORD_TO_TYPE.length() * TIMES_TO_TYPE - TIMES_TO_BACKSPACE, 607 mEditText.getText().length()); 608 } 609 testManySingleQuotes()610 public void testManySingleQuotes() { 611 final String WORD_TO_AUTOCORRECT = "i"; 612 final String WORD_AUTOCORRECTED = "I"; 613 final String QUOTES = "''''''''''''''''''''"; 614 final String WORD_TO_TYPE = WORD_TO_AUTOCORRECT + QUOTES + " "; 615 final String EXPECTED_RESULT = WORD_AUTOCORRECTED + QUOTES + " "; 616 type(WORD_TO_TYPE); 617 assertEquals("auto-correct with many trailing single quotes", EXPECTED_RESULT, 618 mEditText.getText().toString()); 619 } 620 testManySingleQuotesOneByOne()621 public void testManySingleQuotesOneByOne() { 622 final String WORD_TO_AUTOCORRECT = "i"; 623 final String WORD_AUTOCORRECTED = "I"; 624 final String QUOTES = "''''''''''''''''''''"; 625 final String WORD_TO_TYPE = WORD_TO_AUTOCORRECT + QUOTES + " "; 626 final String EXPECTED_RESULT = WORD_AUTOCORRECTED + QUOTES + " "; 627 628 for (int i = 0; i < WORD_TO_TYPE.length(); ++i) { 629 type(WORD_TO_TYPE.substring(i, i+1)); 630 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 631 runMessages(); 632 } 633 assertEquals("type many trailing single quotes one by one", EXPECTED_RESULT, 634 mEditText.getText().toString()); 635 } 636 testTypingSingleQuotesOneByOne()637 public void testTypingSingleQuotesOneByOne() { 638 final String WORD_TO_TYPE = "it's "; 639 final String EXPECTED_RESULT = WORD_TO_TYPE; 640 for (int i = 0; i < WORD_TO_TYPE.length(); ++i) { 641 type(WORD_TO_TYPE.substring(i, i+1)); 642 sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS); 643 runMessages(); 644 } 645 assertEquals("type words letter by letter", EXPECTED_RESULT, 646 mEditText.getText().toString()); 647 } 648 testBasicGesture()649 public void testBasicGesture() { 650 gesture("this"); 651 assertEquals("this", mEditText.getText().toString()); 652 } 653 testGestureGesture()654 public void testGestureGesture() { 655 gesture("got"); 656 gesture("milk"); 657 assertEquals("got milk", mEditText.getText().toString()); 658 } 659 testGestureBackspaceGestureAgain()660 public void testGestureBackspaceGestureAgain() { 661 gesture("this"); 662 type(Constants.CODE_DELETE); 663 assertEquals("gesture then backspace", "", mEditText.getText().toString()); 664 gesture("this"); 665 if (DecoderSpecificConstants.SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION) { 666 assertNotEqual("this", mEditText.getText().toString()); 667 } else { 668 assertEquals("this", mEditText.getText().toString()); 669 } 670 } 671 typeOrGestureWordAndPutCursorInside(final boolean gesture, final String word, final int startPos)672 private void typeOrGestureWordAndPutCursorInside(final boolean gesture, final String word, 673 final int startPos) { 674 final int END_OF_WORD = startPos + word.length(); 675 final int NEW_CURSOR_POSITION = startPos + word.length() / 2; 676 if (gesture) { 677 gesture(word); 678 } else { 679 type(word); 680 } 681 sendUpdateForCursorMoveTo(END_OF_WORD); 682 runMessages(); 683 sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION); 684 sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS); 685 runMessages(); 686 } 687 typeWordAndPutCursorInside(final String word, final int startPos)688 private void typeWordAndPutCursorInside(final String word, final int startPos) { 689 typeOrGestureWordAndPutCursorInside(false /* gesture */, word, startPos); 690 } 691 gestureWordAndPutCursorInside(final String word, final int startPos)692 private void gestureWordAndPutCursorInside(final String word, final int startPos) { 693 typeOrGestureWordAndPutCursorInside(true /* gesture */, word, startPos); 694 } 695 ensureComposingSpanPos(final String message, final int from, final int to)696 private void ensureComposingSpanPos(final String message, final int from, final int to) { 697 assertEquals(message, from, BaseInputConnection.getComposingSpanStart(mEditText.getText())); 698 assertEquals(message, to, BaseInputConnection.getComposingSpanEnd(mEditText.getText())); 699 } 700 testTypeWithinComposing()701 public void testTypeWithinComposing() { 702 final String WORD_TO_TYPE = "something"; 703 final String EXPECTED_RESULT = "some thing"; 704 typeWordAndPutCursorInside(WORD_TO_TYPE, 0 /* startPos */); 705 type(" "); 706 ensureComposingSpanPos("space while in the middle of a word cancels composition", -1, -1); 707 assertEquals("space in the middle of a composing word", EXPECTED_RESULT, 708 mEditText.getText().toString()); 709 int cursorPos = sendUpdateForCursorMoveToEndOfLine(); 710 runMessages(); 711 type(" "); 712 assertEquals("mbo", "some thing ", mEditText.getText().toString()); 713 typeWordAndPutCursorInside(WORD_TO_TYPE, cursorPos + 1 /* startPos */); 714 type(Constants.CODE_DELETE); 715 ensureComposingSpanPos("delete while in the middle of a word cancels composition", -1, -1); 716 } 717 testTypeWithinGestureComposing()718 public void testTypeWithinGestureComposing() { 719 final String WORD_TO_TYPE = "something"; 720 final String EXPECTED_RESULT = "some thing"; 721 gestureWordAndPutCursorInside(WORD_TO_TYPE, 0 /* startPos */); 722 type(" "); 723 ensureComposingSpanPos("space while in the middle of a word cancels composition", -1, -1); 724 assertEquals("space in the middle of a composing word", EXPECTED_RESULT, 725 mEditText.getText().toString()); 726 int cursorPos = sendUpdateForCursorMoveToEndOfLine(); 727 runMessages(); 728 type(" "); 729 typeWordAndPutCursorInside(WORD_TO_TYPE, cursorPos + 1 /* startPos */); 730 type(Constants.CODE_DELETE); 731 sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS); 732 ensureComposingSpanPos("delete while in the middle of a word cancels composition", -1, -1); 733 } 734 testManualPickThenSeparatorForFrench()735 public void testManualPickThenSeparatorForFrench() { 736 final String WORD1_TO_TYPE = "test"; 737 final String WORD2_TO_TYPE = "!"; 738 final String EXPECTED_RESULT = "test !"; 739 changeLanguage("fr"); 740 type(WORD1_TO_TYPE); 741 pickSuggestionManually(WORD1_TO_TYPE); 742 type(WORD2_TO_TYPE); 743 assertEquals("manual pick then separator for French", EXPECTED_RESULT, 744 mEditText.getText().toString()); 745 } 746 testClusteringPunctuationForFrench()747 public void testClusteringPunctuationForFrench() { 748 final String WORD1_TO_TYPE = "test"; 749 final String WORD2_TO_TYPE = "!!?!:!"; 750 // In English, the expected result would be "test!!?!:!" 751 final String EXPECTED_RESULT = "test !!?! : !"; 752 changeLanguage("fr"); 753 type(WORD1_TO_TYPE); 754 pickSuggestionManually(WORD1_TO_TYPE); 755 type(WORD2_TO_TYPE); 756 assertEquals("clustering punctuation for French", EXPECTED_RESULT, 757 mEditText.getText().toString()); 758 } 759 testWordThenSpaceThenPunctuationFromStripTwice()760 public void testWordThenSpaceThenPunctuationFromStripTwice() { 761 setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, false, true); 762 763 final String WORD_TO_TYPE = "test "; 764 final String PUNCTUATION_FROM_STRIP = "!"; 765 final String EXPECTED_RESULT = "test!! "; 766 type(WORD_TO_TYPE); 767 sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS); 768 runMessages(); 769 assertTrue("type word then type space should display punctuation strip", 770 mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions()); 771 pickSuggestionManually(PUNCTUATION_FROM_STRIP); 772 pickSuggestionManually(PUNCTUATION_FROM_STRIP); 773 assertEquals(EXPECTED_RESULT, mEditText.getText().toString()); 774 } 775 testWordThenSpaceDisplaysPredictions()776 public void testWordThenSpaceDisplaysPredictions() { 777 final String WORD_TO_TYPE = "Barack "; 778 final String EXPECTED_RESULT = "Obama"; 779 type(WORD_TO_TYPE); 780 sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS); 781 runMessages(); 782 final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest(); 783 assertEquals("type word then type space yields predictions for French", 784 EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null); 785 } 786 } 787