RichInputConnectionAndTextRangeTests.java revision 494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3
12f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard/* 22f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * Copyright (C) 2012 The Android Open Source Project 32f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * 42f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * Licensed under the Apache License, Version 2.0 (the "License"); 52f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * you may not use this file except in compliance with the License. 62f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * You may obtain a copy of the License at 72f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * 82f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * http://www.apache.org/licenses/LICENSE-2.0 92f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * 102f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * Unless required by applicable law or agreed to in writing, software 112f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * distributed under the License is distributed on an "AS IS" BASIS, 122f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * See the License for the specific language governing permissions and 142f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * limitations under the License. 152f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard */ 162f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 172f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardpackage com.android.inputmethod.latin; 182f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 19494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaokaimport android.content.res.Resources; 202f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.inputmethodservice.InputMethodService; 212f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.os.Parcel; 222f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.test.AndroidTestCase; 232f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.test.MoreAsserts; 242f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.test.suitebuilder.annotation.SmallTest; 252f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.text.SpannableString; 262f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.text.TextUtils; 272f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.text.style.SuggestionSpan; 282f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.view.inputmethod.ExtractedText; 292f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.view.inputmethod.ExtractedTextRequest; 302f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.view.inputmethod.InputConnection; 312f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport android.view.inputmethod.InputConnectionWrapper; 322f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 33494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaokaimport com.android.inputmethod.latin.settings.SpacingAndPunctuations; 34494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.RunInLocale; 35494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.TextRange; 36494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka 372f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardimport java.util.Locale; 382f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 392f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard@SmallTest 402f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalardpublic class RichInputConnectionAndTextRangeTests extends AndroidTestCase { 412f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 422f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // The following is meant to be a reasonable default for 432f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // the "word_separators" resource. 44494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka private SpacingAndPunctuations mSpacingAndPunctuations; 452f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 462f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 472f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard protected void setUp() throws Exception { 482f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard super.setUp(); 49494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka final RunInLocale<SpacingAndPunctuations> job = new RunInLocale<SpacingAndPunctuations>() { 50494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka @Override 51494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka protected SpacingAndPunctuations job(final Resources res) { 52494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka return new SpacingAndPunctuations(res); 53494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka } 54494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka }; 55494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka final Resources res = getContext().getResources(); 56494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka mSpacingAndPunctuations = job.runInLocale(res, Locale.ENGLISH); 572f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 582f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 592f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard private class MockConnection extends InputConnectionWrapper { 602f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final CharSequence mTextBefore; 612f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final CharSequence mTextAfter; 622f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final ExtractedText mExtractedText; 632f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 642f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public MockConnection(final CharSequence text, final int cursorPosition) { 652f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard super(null, false); 662f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // Interaction of spans with Parcels is completely non-trivial, but in the actual case 672f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // the CharSequences do go through Parcels because they go through IPC. There 682f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // are some significant differences between the behavior of Spanned objects that 692f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // have and that have not gone through parceling, so it's much easier to simulate 702f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // the environment with Parcels than try to emulate things by hand. 712f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final Parcel p = Parcel.obtain(); 722f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard TextUtils.writeToParcel(text.subSequence(0, cursorPosition), p, 0 /* flags */); 732f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard TextUtils.writeToParcel(text.subSequence(cursorPosition, text.length()), p, 742f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 0 /* flags */); 752f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final byte[] marshalled = p.marshall(); 762f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard p.unmarshall(marshalled, 0, marshalled.length); 772f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard p.setDataPosition(0); 782f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mTextBefore = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p); 792f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mTextAfter = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p); 802f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mExtractedText = null; 812f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard p.recycle(); 822f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 832f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 842f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public MockConnection(String textBefore, String textAfter, ExtractedText extractedText) { 852f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard super(null, false); 862f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mTextBefore = textBefore; 872f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mTextAfter = textAfter; 882f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mExtractedText = extractedText; 892f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 902f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 912f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard /* (non-Javadoc) 922f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * @see android.view.inputmethod.InputConnectionWrapper#getTextBeforeCursor(int, int) 932f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard */ 942f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 952f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public CharSequence getTextBeforeCursor(int n, int flags) { 962f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard return mTextBefore; 972f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 982f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 992f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard /* (non-Javadoc) 1002f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * @see android.view.inputmethod.InputConnectionWrapper#getTextAfterCursor(int, int) 1012f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard */ 1022f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 1032f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public CharSequence getTextAfterCursor(int n, int flags) { 1042f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard return mTextAfter; 1052f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1062f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1072f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard /* (non-Javadoc) 1082f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * @see android.view.inputmethod.InputConnectionWrapper#getExtractedText( 1092f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * ExtractedTextRequest, int) 1102f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard */ 1112f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 1122f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { 1132f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard return mExtractedText; 1142f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1152f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1162f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 1172f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public boolean beginBatchEdit() { 1182f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard return true; 1192f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1202f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1212f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 1222f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public boolean endBatchEdit() { 1232f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard return true; 1242f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1252f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1262f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 1272f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public boolean finishComposingText() { 1282f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard return true; 1292f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1302f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1312f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1322f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard private class MockInputMethodService extends InputMethodService { 1332f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard InputConnection mInputConnection; 1342f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public void setInputConnection(final InputConnection inputConnection) { 1352f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mInputConnection = inputConnection; 1362f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1372f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard @Override 1382f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public InputConnection getCurrentInputConnection() { 1392f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard return mInputConnection; 1402f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1412f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1422f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1432f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard /************************** Tests ************************/ 1442f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1452f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard /** 1462f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * Test for getting previous word (for bigram suggestions) 1472f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard */ 1482f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public void testGetPreviousWord() { 1492f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // If one of the following cases breaks, the bigram suggestions won't work. 150494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertEquals(RichInputConnection.getNthPreviousWord( 151494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def", mSpacingAndPunctuations, 2), "abc"); 152494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertNull(RichInputConnection.getNthPreviousWord( 153494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc", mSpacingAndPunctuations, 2)); 154494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertNull(RichInputConnection.getNthPreviousWord( 155494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc. def", mSpacingAndPunctuations, 2)); 1562f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1572f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // The following tests reflect the current behavior of the function 1582f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // RichInputConnection#getNthPreviousWord. 1592f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // TODO: However at this time, the code does never go 1602f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // into such a path, so it should be safe to change the behavior of 1612f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // this function if needed - especially since it does not seem very 1622f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // logical. These tests are just there to catch any unintentional 1632f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // changes in the behavior of the RichInputConnection#getPreviousWord method. 164494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertEquals(RichInputConnection.getNthPreviousWord( 165494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def ", mSpacingAndPunctuations, 2), "abc"); 166494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertEquals(RichInputConnection.getNthPreviousWord( 167494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def.", mSpacingAndPunctuations, 2), "abc"); 168494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertEquals(RichInputConnection.getNthPreviousWord( 169494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def .", mSpacingAndPunctuations, 2), "def"); 170494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertNull(RichInputConnection.getNthPreviousWord( 171494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc ", mSpacingAndPunctuations, 2)); 172494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka 173494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertEquals(RichInputConnection.getNthPreviousWord( 174494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def", mSpacingAndPunctuations, 1), "def"); 175494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertEquals(RichInputConnection.getNthPreviousWord( 176494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def ", mSpacingAndPunctuations, 1), "def"); 177494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertNull(RichInputConnection.getNthPreviousWord( 178494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def.", mSpacingAndPunctuations, 1)); 179494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka assertNull(RichInputConnection.getNthPreviousWord( 180494e2d6c17cdbf27615a2fbc02b12d2562bf7cd3Tadashi G. Takaoka "abc def .", mSpacingAndPunctuations, 1)); 1812f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 1822f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1832f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard /** 1842f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * Test logic in getting the word range at the cursor. 1852f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard */ 1862f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public void testGetWordRangeAtCursor() { 1872f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ExtractedText et = new ExtractedText(); 1882f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final MockInputMethodService mockInputMethodService = new MockInputMethodService(); 1892f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final RichInputConnection ic = new RichInputConnection(mockInputMethodService); 1902f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection("word wo", "rd", et)); 1912f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard et.startOffset = 0; 1922f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard et.selectionStart = 7; 193675bcf191c3cdb5ba5af70efb9357ffceb389c2eJean Chalard TextRange r; 1942f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 1952f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.beginBatchEdit(); 1962f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // basic case 1972f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 0); 1982f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertTrue(TextUtils.equals("word", r.mWord)); 1992f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2002f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // more than one word 2012f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 1); 2022f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertTrue(TextUtils.equals("word word", r.mWord)); 2032f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.endBatchEdit(); 2042f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2052f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // tab character instead of space 2062f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et)); 2072f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.beginBatchEdit(); 2082f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor("\t", 1); 2092f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.endBatchEdit(); 2102f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertTrue(TextUtils.equals("word\tword", r.mWord)); 2112f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2122f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // only one word doesn't go too far 2132f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et)); 2142f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.beginBatchEdit(); 2152f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor("\t", 1); 2162f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.endBatchEdit(); 2172f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertTrue(TextUtils.equals("word\tword", r.mWord)); 2182f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2192f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // tab or space 2202f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection("one word\two", "rd", et)); 2212f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.beginBatchEdit(); 2222f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" \t", 1); 2232f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.endBatchEdit(); 2242f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertTrue(TextUtils.equals("word\tword", r.mWord)); 2252f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2262f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // tab or space multiword 2272f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection("one word\two", "rd", et)); 2282f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.beginBatchEdit(); 2292f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" \t", 2); 2302f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.endBatchEdit(); 2312f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertTrue(TextUtils.equals("one word\tword", r.mWord)); 2322f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2332f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // splitting on supplementary character 2342f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final String supplementaryChar = "\uD840\uDC8A"; 2352f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection( 2362f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard new MockConnection("one word" + supplementaryChar + "wo", "rd", et)); 2372f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.beginBatchEdit(); 2382f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(supplementaryChar, 0); 2392f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard ic.endBatchEdit(); 2402f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertTrue(TextUtils.equals("word", r.mWord)); 2412f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 2422f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2432f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard /** 2442f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard * Test logic in getting the word range at the cursor. 2452f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard */ 2462f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard public void testGetSuggestionSpansAtWord() { 2472f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard helpTestGetSuggestionSpansAtWord(10); 2482f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard helpTestGetSuggestionSpansAtWord(12); 2492f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard helpTestGetSuggestionSpansAtWord(15); 2502f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard helpTestGetSuggestionSpansAtWord(16); 2512f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 2522f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2532f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard private void helpTestGetSuggestionSpansAtWord(final int cursorPos) { 2542f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final MockInputMethodService mockInputMethodService = new MockInputMethodService(); 2552f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final RichInputConnection ic = new RichInputConnection(mockInputMethodService); 2562f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2572f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final String[] SUGGESTIONS1 = { "swing", "strong" }; 2582f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard final String[] SUGGESTIONS2 = { "storing", "strung" }; 2592f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2602f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // Test the usual case. 2612f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard SpannableString text = new SpannableString("This is a string for test"); 2622f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 2632f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 10 /* start */, 16 /* end */, 0 /* flags */); 2642f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 265675bcf191c3cdb5ba5af70efb9357ffceb389c2eJean Chalard TextRange r; 2662f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard SuggestionSpan[] suggestions; 2672f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2682f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 0); 2692f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard suggestions = r.getSuggestionSpansAtWord(); 2702f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertEquals(suggestions.length, 1); 2712f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 2722f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2732f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // Test the case with 2 suggestion spans in the same place. 2742f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text = new SpannableString("This is a string for test"); 2752f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 2762f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 10 /* start */, 16 /* end */, 0 /* flags */); 2772f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 2782f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 10 /* start */, 16 /* end */, 0 /* flags */); 2792f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 2802f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 0); 2812f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard suggestions = r.getSuggestionSpansAtWord(); 2822f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertEquals(suggestions.length, 2); 2832f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 2842f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard MoreAsserts.assertEquals(suggestions[1].getSuggestions(), SUGGESTIONS2); 2852f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2862f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // Test a case with overlapping spans, 2nd extending past the start of the word 2872f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text = new SpannableString("This is a string for test"); 2882f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 2892f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 10 /* start */, 16 /* end */, 0 /* flags */); 2902f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 2912f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 5 /* start */, 16 /* end */, 0 /* flags */); 2922f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 2932f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 0); 2942f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard suggestions = r.getSuggestionSpansAtWord(); 2952f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertEquals(suggestions.length, 1); 2962f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 2972f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 2982f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // Test a case with overlapping spans, 2nd extending past the end of the word 2992f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text = new SpannableString("This is a string for test"); 3002f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 3012f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 10 /* start */, 16 /* end */, 0 /* flags */); 3022f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 3032f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 10 /* start */, 20 /* end */, 0 /* flags */); 3042f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 3052f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 0); 3062f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard suggestions = r.getSuggestionSpansAtWord(); 3072f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertEquals(suggestions.length, 1); 3082f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 3092f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 3102f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // Test a case with overlapping spans, 2nd extending past both ends of the word 3112f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text = new SpannableString("This is a string for test"); 3122f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 3132f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 10 /* start */, 16 /* end */, 0 /* flags */); 3142f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 3152f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 5 /* start */, 20 /* end */, 0 /* flags */); 3162f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 3172f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 0); 3182f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard suggestions = r.getSuggestionSpansAtWord(); 3192f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertEquals(suggestions.length, 1); 3202f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 3212f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 3222f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard // Test a case with overlapping spans, none right on the word 3232f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text = new SpannableString("This is a string for test"); 3242f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 3252f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 5 /* start */, 16 /* end */, 0 /* flags */); 3262f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 3272f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard 5 /* start */, 20 /* end */, 0 /* flags */); 3282f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 3292f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard r = ic.getWordRangeAtCursor(" ", 0); 3302f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard suggestions = r.getSuggestionSpansAtWord(); 3312f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard assertEquals(suggestions.length, 0); 3322f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard } 3332f7f6257b66fc1ed19b600f3d55902fd0de2e338Jean Chalard} 334