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