| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser.input; | 5 package org.chromium.content.browser.input; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | |
| 8 import android.app.Activity; | |
| 9 import android.content.ClipData; | 7 import android.content.ClipData; |
| 10 import android.content.ClipboardManager; | 8 import android.content.ClipboardManager; |
| 11 import android.content.Context; | 9 import android.content.Context; |
| 12 import android.content.res.Configuration; | 10 import android.content.res.Configuration; |
| 13 import android.os.Handler; | |
| 14 import android.support.test.filters.MediumTest; | 11 import android.support.test.filters.MediumTest; |
| 15 import android.support.test.filters.SmallTest; | 12 import android.support.test.filters.SmallTest; |
| 16 import android.text.InputType; | 13 import android.text.InputType; |
| 17 import android.text.TextUtils; | |
| 18 import android.util.Pair; | |
| 19 import android.view.KeyEvent; | 14 import android.view.KeyEvent; |
| 20 import android.view.View; | |
| 21 import android.view.inputmethod.BaseInputConnection; | 15 import android.view.inputmethod.BaseInputConnection; |
| 22 import android.view.inputmethod.EditorInfo; | 16 import android.view.inputmethod.EditorInfo; |
| 23 import android.view.inputmethod.InputConnection; | 17 |
| 18 import org.junit.Assert; |
| 19 import org.junit.Before; |
| 20 import org.junit.Rule; |
| 21 import org.junit.Test; |
| 22 import org.junit.runner.RunWith; |
| 24 | 23 |
| 25 import org.chromium.base.ThreadUtils; | 24 import org.chromium.base.ThreadUtils; |
| 26 import org.chromium.base.test.util.DisabledTest; | 25 import org.chromium.base.test.util.DisabledTest; |
| 27 import org.chromium.base.test.util.Feature; | 26 import org.chromium.base.test.util.Feature; |
| 28 import org.chromium.base.test.util.UrlUtils; | 27 import org.chromium.base.test.util.UrlUtils; |
| 29 import org.chromium.content.browser.ContentViewCore; | 28 import org.chromium.content.browser.test.ContentJUnit4ClassRunner; |
| 30 import org.chromium.content.browser.SelectionPopupController; | |
| 31 import org.chromium.content.browser.test.util.Criteria; | 29 import org.chromium.content.browser.test.util.Criteria; |
| 32 import org.chromium.content.browser.test.util.CriteriaHelper; | 30 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 33 import org.chromium.content.browser.test.util.DOMUtils; | 31 import org.chromium.content.browser.test.util.DOMUtils; |
| 34 import org.chromium.content.browser.test.util.JavaScriptUtils; | 32 import org.chromium.content.browser.test.util.JavaScriptUtils; |
| 35 import org.chromium.content.browser.test.util.TestCallbackHelperContainer; | |
| 36 import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper; | |
| 37 import org.chromium.content_public.browser.WebContents; | |
| 38 import org.chromium.content_shell_apk.ContentShellTestBase; | |
| 39 import org.chromium.ui.base.ime.TextInputType; | 33 import org.chromium.ui.base.ime.TextInputType; |
| 40 | 34 |
| 41 import java.util.ArrayList; | |
| 42 import java.util.Arrays; | |
| 43 import java.util.List; | |
| 44 import java.util.concurrent.Callable; | 35 import java.util.concurrent.Callable; |
| 45 import java.util.concurrent.ExecutionException; | |
| 46 import java.util.concurrent.TimeoutException; | |
| 47 | 36 |
| 48 /** | 37 /** |
| 49 * IME (input method editor) and text input tests. | 38 * IME (input method editor) and text input tests. |
| 50 */ | 39 */ |
| 51 public class ImeTest extends ContentShellTestBase { | 40 @RunWith(ContentJUnit4ClassRunner.class) |
| 52 protected ChromiumBaseInputConnection mConnection; | 41 public class ImeTest { |
| 53 private TestInputConnectionFactory mConnectionFactory; | 42 @Rule |
| 54 private ImeAdapter mImeAdapter; | 43 public ImeActivityTestRule mRule = new ImeActivityTestRule(); |
| 55 | 44 |
| 56 private static final String INPUT_FORM_HTML = | 45 @Before |
| 57 "content/test/data/android/input/input_forms.html"; | |
| 58 | |
| 59 private ContentViewCore mContentViewCore; | |
| 60 private WebContents mWebContents; | |
| 61 private SelectionPopupController mSelectionPopupController; | |
| 62 private TestCallbackHelperContainer mCallbackContainer; | |
| 63 protected TestInputMethodManagerWrapper mInputMethodManagerWrapper; | |
| 64 | |
| 65 @Override | |
| 66 public void setUp() throws Exception { | 46 public void setUp() throws Exception { |
| 67 super.setUp(); | 47 mRule.setUp(); |
| 68 startActivityWithTestUrl(INPUT_FORM_HTML); | 48 } |
| 69 mContentViewCore = getContentViewCore(); | 49 |
| 70 mSelectionPopupController = mContentViewCore.getSelectionPopupController
ForTesting(); | 50 @Test |
| 71 mWebContents = getWebContents(); | |
| 72 | |
| 73 mInputMethodManagerWrapper = new TestInputMethodManagerWrapper(mContentV
iewCore) { | |
| 74 private boolean mExpectsSelectionOutsideComposition; | |
| 75 | |
| 76 @Override | |
| 77 public void expectsSelectionOutsideComposition() { | |
| 78 mExpectsSelectionOutsideComposition = true; | |
| 79 } | |
| 80 | |
| 81 @Override | |
| 82 public void onUpdateSelection( | |
| 83 Range oldSel, Range oldComp, Range newSel, Range newComp) { | |
| 84 // We expect that selection will be outside composition in some
cases. Keyboard | |
| 85 // app will not finish composition in this case. | |
| 86 if (mExpectsSelectionOutsideComposition) { | |
| 87 mExpectsSelectionOutsideComposition = false; | |
| 88 return; | |
| 89 } | |
| 90 if (oldComp == null || oldComp.start() == oldComp.end() | |
| 91 || newComp.start() == newComp.end()) { | |
| 92 return; | |
| 93 } | |
| 94 // This emulates keyboard app's behavior that finishes compositi
on when | |
| 95 // selection is outside composition. | |
| 96 if (!newSel.intersects(newComp)) { | |
| 97 try { | |
| 98 finishComposingText(); | |
| 99 } catch (Exception e) { | |
| 100 e.printStackTrace(); | |
| 101 fail(); | |
| 102 } | |
| 103 } | |
| 104 } | |
| 105 }; | |
| 106 getImeAdapter().setInputMethodManagerWrapperForTest(mInputMethodManagerW
rapper); | |
| 107 assertEquals(0, mInputMethodManagerWrapper.getShowSoftInputCounter()); | |
| 108 mConnectionFactory = | |
| 109 new TestInputConnectionFactory(getImeAdapter().getInputConnectio
nFactoryForTest()); | |
| 110 getImeAdapter().setInputConnectionFactory(mConnectionFactory); | |
| 111 | |
| 112 mCallbackContainer = new TestCallbackHelperContainer(mContentViewCore); | |
| 113 DOMUtils.waitForNonZeroNodeBounds(mWebContents, "input_text"); | |
| 114 boolean result = DOMUtils.clickNode(mContentViewCore, "input_text"); | |
| 115 | |
| 116 assertEquals("Failed to dispatch touch event.", true, result); | |
| 117 assertWaitForKeyboardStatus(true); | |
| 118 | |
| 119 mConnection = getInputConnection(); | |
| 120 mImeAdapter = getImeAdapter(); | |
| 121 | |
| 122 waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT}); | |
| 123 assertEquals(0, mConnectionFactory.getOutAttrs().initialSelStart); | |
| 124 assertEquals(0, mConnectionFactory.getOutAttrs().initialSelEnd); | |
| 125 | |
| 126 waitForEventLogs("selectionchange"); | |
| 127 clearEventLogs(); | |
| 128 | |
| 129 waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); | |
| 130 resetAllStates(); | |
| 131 } | |
| 132 | |
| 133 private void fullyLoadUrl(final String url) throws Throwable { | |
| 134 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 135 @Override | |
| 136 public void run() { | |
| 137 getActivity().getActiveShell().loadUrl(url); | |
| 138 } | |
| 139 }); | |
| 140 waitForActiveShellToBeDoneLoading(); | |
| 141 } | |
| 142 | |
| 143 @MediumTest | 51 @MediumTest |
| 144 @Feature({"TextInput", "Main"}) | 52 @Feature({"TextInput", "Main"}) |
| 145 public void testKeyboardDismissedWhenNavigating() throws Throwable { | 53 public void testKeyboardDismissedWhenNavigating() throws Throwable { |
| 146 assertWaitForKeyboardStatus(true); | 54 mRule.assertWaitForKeyboardStatus(true); |
| 147 | 55 |
| 148 // Hide keyboard when loading a new Url. | 56 // Hide keyboard when loading a new Url. |
| 149 fullyLoadUrl(UrlUtils.getIsolatedTestFileUrl(INPUT_FORM_HTML)); | 57 mRule.fullyLoadUrl(UrlUtils.getIsolatedTestFileUrl(ImeActivityTestRule.I
NPUT_FORM_HTML)); |
| 150 assertWaitForKeyboardStatus(false); | 58 mRule.assertWaitForKeyboardStatus(false); |
| 151 | 59 |
| 152 DOMUtils.clickNode(mContentViewCore, "input_text"); | 60 DOMUtils.clickNode(mRule.getContentViewCore(), "input_text"); |
| 153 assertWaitForKeyboardStatus(true); | 61 mRule.assertWaitForKeyboardStatus(true); |
| 154 | 62 |
| 155 // Hide keyboard when navigating. | 63 // Hide keyboard when navigating. |
| 156 final String code = "document.getElementById(\"link\").click()"; | 64 final String code = "document.getElementById(\"link\").click()"; |
| 157 JavaScriptUtils.executeJavaScriptAndWaitForResult( | 65 JavaScriptUtils.executeJavaScriptAndWaitForResult( |
| 158 getContentViewCore().getWebContents(), code); | 66 mRule.getContentViewCore().getWebContents(), code); |
| 159 assertWaitForKeyboardStatus(false); | 67 mRule.assertWaitForKeyboardStatus(false); |
| 160 } | 68 } |
| 161 | 69 |
| 70 @Test |
| 162 @MediumTest | 71 @MediumTest |
| 163 @Feature({"TextInput", "Main"}) | 72 @Feature({"TextInput", "Main"}) |
| 164 public void testKeyboardDismissedAfterClickingGo() throws Throwable { | 73 public void testKeyboardDismissedAfterClickingGo() throws Throwable { |
| 165 setComposingText("hello", 1); | 74 mRule.setComposingText("hello", 1); |
| 166 waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); | 75 mRule.waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); |
| 167 | 76 |
| 168 performGo(mCallbackContainer); | 77 mRule.performGo(mRule.getTestCallBackHelperContainer()); |
| 169 | 78 |
| 170 assertWaitForKeyboardStatus(false); | 79 mRule.assertWaitForKeyboardStatus(false); |
| 171 } | 80 } |
| 172 | 81 |
| 82 @Test |
| 173 @MediumTest | 83 @MediumTest |
| 174 @Feature({"TextInput", "Main"}) | 84 @Feature({"TextInput", "Main"}) |
| 175 public void testDoesNotHang_getTextAfterKeyboardHides() throws Throwable { | 85 public void testDoesNotHang_getTextAfterKeyboardHides() throws Throwable { |
| 176 setComposingText("hello", 1); | 86 mRule.setComposingText("hello", 1); |
| 177 waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); | 87 mRule.waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); |
| 178 | 88 |
| 179 performGo(mCallbackContainer); | 89 mRule.performGo(mRule.getTestCallBackHelperContainer()); |
| 180 | 90 |
| 181 // This may time out if we do not get the information on time. | 91 // This may time out if we do not get the information on time. |
| 182 // TODO(changwan): find a way to remove the loop. | 92 // TODO(changwan): find a way to remove the loop. |
| 183 for (int i = 0; i < 100; ++i) { | 93 for (int i = 0; i < 100; ++i) { |
| 184 getTextBeforeCursor(10, 0); | 94 mRule.getTextBeforeCursor(10, 0); |
| 185 } | 95 } |
| 186 | 96 |
| 187 assertWaitForKeyboardStatus(false); | 97 mRule.assertWaitForKeyboardStatus(false); |
| 188 } | 98 } |
| 189 | 99 |
| 190 // crbug.com/643519 | 100 // crbug.com/643519 |
| 101 @Test |
| 191 @SmallTest | 102 @SmallTest |
| 192 @Feature({"TextInput", "Main"}) | 103 @Feature({"TextInput", "Main"}) |
| 193 public void testCompositionWithNullTextNotCrash() throws Throwable { | 104 public void testCompositionWithNullTextNotCrash() throws Throwable { |
| 194 commitText(null, 1); | 105 mRule.commitText(null, 1); |
| 195 assertTextsAroundCursor("", null, ""); | 106 mRule.assertTextsAroundCursor("", null, ""); |
| 196 | 107 |
| 197 setComposingText(null, 1); | 108 mRule.setComposingText(null, 1); |
| 198 assertTextsAroundCursor("", null, ""); | 109 mRule.assertTextsAroundCursor("", null, ""); |
| 199 } | 110 } |
| 200 | 111 |
| 112 @Test |
| 201 @SmallTest | 113 @SmallTest |
| 202 @Feature({"TextInput", "Main"}) | 114 @Feature({"TextInput", "Main"}) |
| 203 public void testDeleteSurroundingTextWithRangeSelection() throws Throwable { | 115 public void testDeleteSurroundingTextWithRangeSelection() throws Throwable { |
| 204 commitText("hello", 1); | 116 mRule.commitText("hello", 1); |
| 205 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 117 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 206 | 118 |
| 207 setSelection(1, 4); | 119 mRule.setSelection(1, 4); |
| 208 waitAndVerifyUpdateSelection(1, 1, 4, -1, -1); | 120 mRule.waitAndVerifyUpdateSelection(1, 1, 4, -1, -1); |
| 209 | 121 |
| 210 deleteSurroundingText(0, 0); | 122 mRule.deleteSurroundingText(0, 0); |
| 211 assertTextsAroundCursor("h", "ell", "o"); | 123 mRule.assertTextsAroundCursor("h", "ell", "o"); |
| 212 | 124 |
| 213 deleteSurroundingText(1, 1); | 125 mRule.deleteSurroundingText(1, 1); |
| 214 assertTextsAroundCursor("", "ell", ""); | 126 mRule.assertTextsAroundCursor("", "ell", ""); |
| 215 | 127 |
| 216 deleteSurroundingText(1, 0); | 128 mRule.deleteSurroundingText(1, 0); |
| 217 assertTextsAroundCursor("", "ell", ""); | 129 mRule.assertTextsAroundCursor("", "ell", ""); |
| 218 | 130 |
| 219 deleteSurroundingText(0, 1); | 131 mRule.deleteSurroundingText(0, 1); |
| 220 assertTextsAroundCursor("", "ell", ""); | 132 mRule.assertTextsAroundCursor("", "ell", ""); |
| 221 } | 133 } |
| 222 | 134 |
| 135 @Test |
| 223 @SmallTest | 136 @SmallTest |
| 224 @Feature({"TextInput", "Main"}) | 137 @Feature({"TextInput", "Main"}) |
| 225 public void testDeleteSurroundingTextWithCursorSelection() throws Throwable
{ | 138 public void testDeleteSurroundingTextWithCursorSelection() throws Throwable
{ |
| 226 commitText("hello", 1); | 139 mRule.commitText("hello", 1); |
| 227 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 140 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 228 | 141 |
| 229 setSelection(2, 2); | 142 mRule.setSelection(2, 2); |
| 230 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 143 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 231 | 144 |
| 232 deleteSurroundingText(0, 0); | 145 mRule.deleteSurroundingText(0, 0); |
| 233 assertTextsAroundCursor("he", null, "llo"); | 146 mRule.assertTextsAroundCursor("he", null, "llo"); |
| 234 | 147 |
| 235 deleteSurroundingText(1, 1); | 148 mRule.deleteSurroundingText(1, 1); |
| 236 assertTextsAroundCursor("h", null, "lo"); | 149 mRule.assertTextsAroundCursor("h", null, "lo"); |
| 237 | 150 |
| 238 deleteSurroundingText(1, 0); | 151 mRule.deleteSurroundingText(1, 0); |
| 239 assertTextsAroundCursor("", null, "lo"); | 152 mRule.assertTextsAroundCursor("", null, "lo"); |
| 240 | 153 |
| 241 deleteSurroundingText(0, 10); | 154 mRule.deleteSurroundingText(0, 10); |
| 242 assertTextsAroundCursor("", null, ""); | 155 mRule.assertTextsAroundCursor("", null, ""); |
| 243 | 156 |
| 244 deleteSurroundingText(10, 10); | 157 mRule.deleteSurroundingText(10, 10); |
| 245 assertTextsAroundCursor("", null, ""); | 158 mRule.assertTextsAroundCursor("", null, ""); |
| 246 } | 159 } |
| 247 | 160 |
| 161 @Test |
| 248 @SmallTest | 162 @SmallTest |
| 249 @Feature({"TextInput", "Main"}) | 163 @Feature({"TextInput", "Main"}) |
| 250 public void testKeyboardAppFinishesCompositionOnUnexpectedSelectionChange()
throws Throwable { | 164 public void testKeyboardAppFinishesCompositionOnUnexpectedSelectionChange()
throws Throwable { |
| 251 focusElementAndWaitForStateUpdate("textarea2"); | 165 mRule.focusElementAndWaitForStateUpdate("textarea2"); |
| 252 commitText("12345", 1); | 166 mRule.commitText("12345", 1); |
| 253 setSelection(3, 3); | 167 mRule.setSelection(3, 3); |
| 254 setComposingRegion(2, 3); | 168 mRule.setComposingRegion(2, 3); |
| 255 | 169 |
| 256 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 170 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 257 waitAndVerifyUpdateSelection(1, 3, 3, -1, -1); | 171 mRule.waitAndVerifyUpdateSelection(1, 3, 3, -1, -1); |
| 258 waitAndVerifyUpdateSelection(2, 3, 3, 2, 3); | 172 mRule.waitAndVerifyUpdateSelection(2, 3, 3, 2, 3); |
| 259 | 173 |
| 260 // Unexpected selection change occurs, e.g., the user clicks on an area. | 174 // Unexpected selection change occurs, e.g., the user clicks on an area. |
| 261 DOMUtils.clickNode(mContentViewCore, "textarea2"); | 175 DOMUtils.clickNode(mRule.getContentViewCore(), "textarea2"); |
| 262 waitAndVerifyUpdateSelection(3, 5, 5, 2, 3); | 176 mRule.waitAndVerifyUpdateSelection(3, 5, 5, 2, 3); |
| 263 // Keyboard app finishes composition. We emulate this in TestInputMethod
ManagerWrapper. | 177 // Keyboard app finishes composition. We emulate this in TestInputMethod
ManagerWrapper. |
| 264 waitAndVerifyUpdateSelection(4, 5, 5, -1, -1); | 178 mRule.waitAndVerifyUpdateSelection(4, 5, 5, -1, -1); |
| 265 } | 179 } |
| 266 | 180 |
| 181 @Test |
| 267 @SmallTest | 182 @SmallTest |
| 268 @Feature({"TextInput", "Main"}) | 183 @Feature({"TextInput", "Main"}) |
| 269 public void testDeleteSurroundingTextInCodePointsWithRangeSelection() throws
Throwable { | 184 public void testDeleteSurroundingTextInCodePointsWithRangeSelection() throws
Throwable { |
| 270 final String trophy = "\uD83C\uDFC6"; | 185 final String trophy = "\uD83C\uDFC6"; |
| 271 commitText("ab" + trophy + "cdef" + trophy + "gh", 1); | 186 mRule.commitText("ab" + trophy + "cdef" + trophy + "gh", 1); |
| 272 waitAndVerifyUpdateSelection(0, 12, 12, -1, -1); | 187 mRule.waitAndVerifyUpdateSelection(0, 12, 12, -1, -1); |
| 273 | 188 |
| 274 setSelection(6, 8); | 189 mRule.setSelection(6, 8); |
| 275 waitAndVerifyUpdateSelection(1, 6, 8, -1, -1); | 190 mRule.waitAndVerifyUpdateSelection(1, 6, 8, -1, -1); |
| 276 assertTextsAroundCursor("ab" + trophy + "cd", "ef", trophy + "gh"); | 191 mRule.assertTextsAroundCursor("ab" + trophy + "cd", "ef", trophy + "gh")
; |
| 277 | 192 |
| 278 deleteSurroundingTextInCodePoints(2, 2); | 193 mRule.deleteSurroundingTextInCodePoints(2, 2); |
| 279 waitAndVerifyUpdateSelection(2, 4, 6, -1, -1); | 194 mRule.waitAndVerifyUpdateSelection(2, 4, 6, -1, -1); |
| 280 assertTextsAroundCursor("ab" + trophy, "ef", "h"); | 195 mRule.assertTextsAroundCursor("ab" + trophy, "ef", "h"); |
| 281 } | 196 } |
| 282 | 197 |
| 198 @Test |
| 283 @SmallTest | 199 @SmallTest |
| 284 @Feature({"TextInput", "Main"}) | 200 @Feature({"TextInput", "Main"}) |
| 285 public void testDeleteSurroundingTextInCodePointsWithCursorSelection() throw
s Throwable { | 201 public void testDeleteSurroundingTextInCodePointsWithCursorSelection() throw
s Throwable { |
| 286 final String trophy = "\uD83C\uDFC6"; | 202 final String trophy = "\uD83C\uDFC6"; |
| 287 commitText("ab" + trophy + "cd" + trophy, 1); | 203 mRule.commitText("ab" + trophy + "cd" + trophy, 1); |
| 288 waitAndVerifyUpdateSelection(0, 8, 8, -1, -1); | 204 mRule.waitAndVerifyUpdateSelection(0, 8, 8, -1, -1); |
| 289 | 205 |
| 290 setSelection(4, 4); | 206 mRule.setSelection(4, 4); |
| 291 waitAndVerifyUpdateSelection(1, 4, 4, -1, -1); | 207 mRule.waitAndVerifyUpdateSelection(1, 4, 4, -1, -1); |
| 292 assertTextsAroundCursor("ab" + trophy, null, "cd" + trophy); | 208 mRule.assertTextsAroundCursor("ab" + trophy, null, "cd" + trophy); |
| 293 | 209 |
| 294 deleteSurroundingTextInCodePoints(2, 2); | 210 mRule.deleteSurroundingTextInCodePoints(2, 2); |
| 295 waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); | 211 mRule.waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); |
| 296 assertTextsAroundCursor("a", null, trophy); | 212 mRule.assertTextsAroundCursor("a", null, trophy); |
| 297 } | 213 } |
| 298 | 214 |
| 215 @Test |
| 299 @SmallTest | 216 @SmallTest |
| 300 @Feature({"TextInput", "Main"}) | 217 @Feature({"TextInput", "Main"}) |
| 301 public void testSetComposingTextForNewCursorPositions() throws Throwable { | 218 public void testSetComposingTextForNewCursorPositions() throws Throwable { |
| 302 // Cursor is on the right of composing text when newCursorPosition > 0. | 219 // Cursor is on the right of composing text when newCursorPosition > 0. |
| 303 setComposingText("ab", 1); | 220 mRule.setComposingText("ab", 1); |
| 304 waitAndVerifyUpdateSelection(0, 2, 2, 0, 2); | 221 mRule.waitAndVerifyUpdateSelection(0, 2, 2, 0, 2); |
| 305 | 222 |
| 306 finishComposingText(); | 223 mRule.finishComposingText(); |
| 307 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 224 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 308 | 225 |
| 309 // Cursor exceeds the left boundary. | 226 // Cursor exceeds the left boundary. |
| 310 setComposingText("cdef", -100); | 227 mRule.setComposingText("cdef", -100); |
| 311 waitAndVerifyUpdateSelection(2, 0, 0, 2, 6); | 228 mRule.waitAndVerifyUpdateSelection(2, 0, 0, 2, 6); |
| 312 | 229 |
| 313 // Cursor is on the left boundary. | 230 // Cursor is on the left boundary. |
| 314 mInputMethodManagerWrapper.expectsSelectionOutsideComposition(); | 231 mRule.getInputMethodManagerWrapper().expectsSelectionOutsideComposition(
); |
| 315 setComposingText("cd", -2); | 232 mRule.setComposingText("cd", -2); |
| 316 waitAndVerifyUpdateSelection(3, 0, 0, 2, 4); | 233 mRule.waitAndVerifyUpdateSelection(3, 0, 0, 2, 4); |
| 317 | 234 |
| 318 mInputMethodManagerWrapper.expectsSelectionOutsideComposition(); | 235 mRule.getInputMethodManagerWrapper().expectsSelectionOutsideComposition(
); |
| 319 // Cursor is between the left boundary and the composing text. | 236 // Cursor is between the left boundary and the composing text. |
| 320 setComposingText("cd", -1); | 237 mRule.setComposingText("cd", -1); |
| 321 waitAndVerifyUpdateSelection(4, 1, 1, 2, 4); | 238 mRule.waitAndVerifyUpdateSelection(4, 1, 1, 2, 4); |
| 322 | 239 |
| 323 // Cursor is on the left of composing text. | 240 // Cursor is on the left of composing text. |
| 324 setComposingText("cd", 0); | 241 mRule.setComposingText("cd", 0); |
| 325 waitAndVerifyUpdateSelection(5, 2, 2, 2, 4); | 242 mRule.waitAndVerifyUpdateSelection(5, 2, 2, 2, 4); |
| 326 | 243 |
| 327 finishComposingText(); | 244 mRule.finishComposingText(); |
| 328 waitAndVerifyUpdateSelection(6, 2, 2, -1, -1); | 245 mRule.waitAndVerifyUpdateSelection(6, 2, 2, -1, -1); |
| 329 | 246 |
| 330 // Cursor is on the right of composing text. | 247 // Cursor is on the right of composing text. |
| 331 setComposingText("ef", 1); | 248 mRule.setComposingText("ef", 1); |
| 332 waitAndVerifyUpdateSelection(7, 4, 4, 2, 4); | 249 mRule.waitAndVerifyUpdateSelection(7, 4, 4, 2, 4); |
| 333 | 250 |
| 334 mInputMethodManagerWrapper.expectsSelectionOutsideComposition(); | 251 mRule.getInputMethodManagerWrapper().expectsSelectionOutsideComposition(
); |
| 335 // Cursor is between the composing text and the right boundary. | 252 // Cursor is between the composing text and the right boundary. |
| 336 setComposingText("ef", 2); | 253 mRule.setComposingText("ef", 2); |
| 337 waitAndVerifyUpdateSelection(8, 5, 5, 2, 4); | 254 mRule.waitAndVerifyUpdateSelection(8, 5, 5, 2, 4); |
| 338 | 255 |
| 339 mInputMethodManagerWrapper.expectsSelectionOutsideComposition(); | 256 mRule.getInputMethodManagerWrapper().expectsSelectionOutsideComposition(
); |
| 340 // Cursor is on the right boundary. | 257 // Cursor is on the right boundary. |
| 341 setComposingText("ef", 3); | 258 mRule.setComposingText("ef", 3); |
| 342 waitAndVerifyUpdateSelection(9, 6, 6, 2, 4); | 259 mRule.waitAndVerifyUpdateSelection(9, 6, 6, 2, 4); |
| 343 | 260 |
| 344 mInputMethodManagerWrapper.expectsSelectionOutsideComposition(); | 261 mRule.getInputMethodManagerWrapper().expectsSelectionOutsideComposition(
); |
| 345 // Cursor exceeds the right boundary. | 262 // Cursor exceeds the right boundary. |
| 346 setComposingText("efgh", 100); | 263 mRule.setComposingText("efgh", 100); |
| 347 waitAndVerifyUpdateSelection(10, 8, 8, 2, 6); | 264 mRule.waitAndVerifyUpdateSelection(10, 8, 8, 2, 6); |
| 348 } | 265 } |
| 349 | 266 |
| 267 @Test |
| 350 @SmallTest | 268 @SmallTest |
| 351 @Feature({"TextInput", "Main"}) | 269 @Feature({"TextInput", "Main"}) |
| 352 public void testCommitTextForNewCursorPositions() throws Throwable { | 270 public void testCommitTextForNewCursorPositions() throws Throwable { |
| 353 // Cursor is on the left of committing text. | 271 // Cursor is on the left of committing text. |
| 354 commitText("ab", 0); | 272 mRule.commitText("ab", 0); |
| 355 waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); | 273 mRule.waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); |
| 356 | 274 |
| 357 // Cursor is on the right of committing text. | 275 // Cursor is on the right of committing text. |
| 358 commitText("cd", 1); | 276 mRule.commitText("cd", 1); |
| 359 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 277 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 360 | 278 |
| 361 // Cursor is between the committing text and the right boundary. | 279 // Cursor is between the committing text and the right boundary. |
| 362 commitText("ef", 2); | 280 mRule.commitText("ef", 2); |
| 363 waitAndVerifyUpdateSelection(2, 5, 5, -1, -1); | 281 mRule.waitAndVerifyUpdateSelection(2, 5, 5, -1, -1); |
| 364 | 282 |
| 365 // Cursor is between the left boundary and the committing text. | 283 // Cursor is between the left boundary and the committing text. |
| 366 commitText("gh", -3); | 284 mRule.commitText("gh", -3); |
| 367 waitAndVerifyUpdateSelection(3, 2, 2, -1, -1); | 285 mRule.waitAndVerifyUpdateSelection(3, 2, 2, -1, -1); |
| 368 | 286 |
| 369 // Cursor is on the right boundary. | 287 // Cursor is on the right boundary. |
| 370 commitText("ij", 7); | 288 mRule.commitText("ij", 7); |
| 371 waitAndVerifyUpdateSelection(4, 10, 10, -1, -1); | 289 mRule.waitAndVerifyUpdateSelection(4, 10, 10, -1, -1); |
| 372 | 290 |
| 373 // Cursor is on the left boundary. | 291 // Cursor is on the left boundary. |
| 374 commitText("kl", -10); | 292 mRule.commitText("kl", -10); |
| 375 waitAndVerifyUpdateSelection(5, 0, 0, -1, -1); | 293 mRule.waitAndVerifyUpdateSelection(5, 0, 0, -1, -1); |
| 376 | 294 |
| 377 // Cursor exceeds the right boundary. | 295 // Cursor exceeds the right boundary. |
| 378 commitText("mn", 100); | 296 mRule.commitText("mn", 100); |
| 379 waitAndVerifyUpdateSelection(6, 14, 14, -1, -1); | 297 mRule.waitAndVerifyUpdateSelection(6, 14, 14, -1, -1); |
| 380 | 298 |
| 381 // Cursor exceeds the left boundary. | 299 // Cursor exceeds the left boundary. |
| 382 commitText("op", -100); | 300 mRule.commitText("op", -100); |
| 383 waitAndVerifyUpdateSelection(7, 0, 0, -1, -1); | 301 mRule.waitAndVerifyUpdateSelection(7, 0, 0, -1, -1); |
| 384 } | 302 } |
| 385 | 303 |
| 304 @Test |
| 386 @SmallTest | 305 @SmallTest |
| 387 @Feature({"TextInput", "Main"}) | 306 @Feature({"TextInput", "Main"}) |
| 388 public void testSetComposingTextWithEmptyText() throws Throwable { | 307 public void testSetComposingTextWithEmptyText() throws Throwable { |
| 389 commitText("hello", 1); | 308 mRule.commitText("hello", 1); |
| 390 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 309 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 391 | 310 |
| 392 setComposingText("AB", 1); | 311 mRule.setComposingText("AB", 1); |
| 393 waitAndVerifyUpdateSelection(1, 7, 7, 5, 7); | 312 mRule.waitAndVerifyUpdateSelection(1, 7, 7, 5, 7); |
| 394 | 313 |
| 395 // With previous composition. | 314 // With previous composition. |
| 396 setComposingText("", -3); | 315 mRule.setComposingText("", -3); |
| 397 waitAndVerifyUpdateSelection(2, 2, 2, -1, -1); | 316 mRule.waitAndVerifyUpdateSelection(2, 2, 2, -1, -1); |
| 398 assertTextsAroundCursor("he", null, "llo"); | 317 mRule.assertTextsAroundCursor("he", null, "llo"); |
| 399 | 318 |
| 400 // Without previous composition. | 319 // Without previous composition. |
| 401 setComposingText("", 3); | 320 mRule.setComposingText("", 3); |
| 402 waitAndVerifyUpdateSelection(3, 4, 4, -1, -1); | 321 mRule.waitAndVerifyUpdateSelection(3, 4, 4, -1, -1); |
| 403 assertTextsAroundCursor("hell", null, "o"); | 322 mRule.assertTextsAroundCursor("hell", null, "o"); |
| 404 } | 323 } |
| 405 | 324 |
| 325 @Test |
| 406 @SmallTest | 326 @SmallTest |
| 407 @Feature({"TextInput", "Main"}) | 327 @Feature({"TextInput", "Main"}) |
| 408 public void testCommitTextWithEmptyText() throws Throwable { | 328 public void testCommitTextWithEmptyText() throws Throwable { |
| 409 commitText("hello", 1); | 329 mRule.commitText("hello", 1); |
| 410 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 330 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 411 setSelection(2, 2); | 331 mRule.setSelection(2, 2); |
| 412 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 332 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 413 | 333 |
| 414 setComposingText("world", 1); | 334 mRule.setComposingText("world", 1); |
| 415 waitAndVerifyUpdateSelection(2, 7, 7, 2, 7); | 335 mRule.waitAndVerifyUpdateSelection(2, 7, 7, 2, 7); |
| 416 // With previous composition. | 336 // With previous composition. |
| 417 commitText("", 2); | 337 mRule.commitText("", 2); |
| 418 waitAndVerifyUpdateSelection(3, 3, 3, -1, -1); | 338 mRule.waitAndVerifyUpdateSelection(3, 3, 3, -1, -1); |
| 419 | 339 |
| 420 // Without previous composition. | 340 // Without previous composition. |
| 421 commitText("", -1); | 341 mRule.commitText("", -1); |
| 422 waitAndVerifyUpdateSelection(4, 2, 2, -1, -1); | 342 mRule.waitAndVerifyUpdateSelection(4, 2, 2, -1, -1); |
| 423 } | 343 } |
| 424 | 344 |
| 345 @Test |
| 425 @SmallTest | 346 @SmallTest |
| 426 @Feature({"TextInput", "Main"}) | 347 @Feature({"TextInput", "Main"}) |
| 427 public void testCommitWhileComposingText() throws Throwable { | 348 public void testCommitWhileComposingText() throws Throwable { |
| 428 setComposingText("h", 1); | 349 mRule.setComposingText("h", 1); |
| 429 waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); | 350 mRule.waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); |
| 430 | 351 |
| 431 setComposingText("he", 1); | 352 mRule.setComposingText("he", 1); |
| 432 waitAndVerifyUpdateSelection(1, 2, 2, 0, 2); | 353 mRule.waitAndVerifyUpdateSelection(1, 2, 2, 0, 2); |
| 433 | 354 |
| 434 setComposingText("hel", 1); | 355 mRule.setComposingText("hel", 1); |
| 435 waitAndVerifyUpdateSelection(2, 3, 3, 0, 3); | 356 mRule.waitAndVerifyUpdateSelection(2, 3, 3, 0, 3); |
| 436 | 357 |
| 437 commitText("hel", 1); | 358 mRule.commitText("hel", 1); |
| 438 waitAndVerifyUpdateSelection(3, 3, 3, -1, -1); | 359 mRule.waitAndVerifyUpdateSelection(3, 3, 3, -1, -1); |
| 439 | 360 |
| 440 setComposingText("lo", 1); | 361 mRule.setComposingText("lo", 1); |
| 441 waitAndVerifyUpdateSelection(4, 5, 5, 3, 5); | 362 mRule.waitAndVerifyUpdateSelection(4, 5, 5, 3, 5); |
| 442 | 363 |
| 443 commitText("", 1); | 364 mRule.commitText("", 1); |
| 444 waitAndVerifyUpdateSelection(5, 3, 3, -1, -1); | 365 mRule.waitAndVerifyUpdateSelection(5, 3, 3, -1, -1); |
| 445 | 366 |
| 446 assertTextsAroundCursor("hel", null, ""); | 367 mRule.assertTextsAroundCursor("hel", null, ""); |
| 447 } | 368 } |
| 448 | 369 |
| 370 @Test |
| 449 @SmallTest | 371 @SmallTest |
| 450 @Feature({"TextInput", "Main"}) | 372 @Feature({"TextInput", "Main"}) |
| 451 public void testCommitEnterKeyWhileComposingText() throws Throwable { | 373 public void testCommitEnterKeyWhileComposingText() throws Throwable { |
| 452 focusElementAndWaitForStateUpdate("textarea"); | 374 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 453 | 375 |
| 454 setComposingText("hello", 1); | 376 mRule.setComposingText("hello", 1); |
| 455 waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); | 377 mRule.waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); |
| 456 | 378 |
| 457 // Cancel the current composition and replace it with enter. | 379 // Cancel the current composition and replace it with enter. |
| 458 commitText("\n", 1); | 380 mRule.commitText("\n", 1); |
| 459 waitAndVerifyUpdateSelection(1, 1, 1, -1, -1); | 381 mRule.waitAndVerifyUpdateSelection(1, 1, 1, -1, -1); |
| 460 // The second new line is not a user visible/editable one, it is a side-
effect of Blink | 382 // The second new line is not a user visible/editable one, it is a side-
effect of Blink |
| 461 // using <br> internally. This only happens when \n is at the end. | 383 // using <br> internally. This only happens when \n is at the end. |
| 462 assertTextsAroundCursor("\n", null, "\n"); | 384 mRule.assertTextsAroundCursor("\n", null, "\n"); |
| 463 | 385 |
| 464 commitText("world", 1); | 386 mRule.commitText("world", 1); |
| 465 waitAndVerifyUpdateSelection(2, 6, 6, -1, -1); | 387 mRule.waitAndVerifyUpdateSelection(2, 6, 6, -1, -1); |
| 466 assertTextsAroundCursor("\nworld", null, ""); | 388 mRule.assertTextsAroundCursor("\nworld", null, ""); |
| 467 } | 389 } |
| 468 | 390 |
| 391 @Test |
| 469 @SmallTest | 392 @SmallTest |
| 470 @Feature({"TextInput"}) | 393 @Feature({"TextInput"}) |
| 471 public void testImeCopy() throws Exception { | 394 public void testImeCopy() throws Exception { |
| 472 commitText("hello", 1); | 395 mRule.commitText("hello", 1); |
| 473 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 396 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 474 | 397 |
| 475 setSelection(2, 5); | 398 mRule.setSelection(2, 5); |
| 476 waitAndVerifyUpdateSelection(1, 2, 5, -1, -1); | 399 mRule.waitAndVerifyUpdateSelection(1, 2, 5, -1, -1); |
| 477 | 400 |
| 478 copy(); | 401 mRule.copy(); |
| 479 assertClipboardContents(getActivity(), "llo"); | 402 mRule.assertClipboardContents(mRule.getActivity(), "llo"); |
| 480 } | 403 } |
| 481 | 404 |
| 405 @Test |
| 482 @SmallTest | 406 @SmallTest |
| 483 @Feature({"TextInput"}) | 407 @Feature({"TextInput"}) |
| 484 public void testEnterTextAndRefocus() throws Exception { | 408 public void testEnterTextAndRefocus() throws Exception { |
| 485 commitText("hello", 1); | 409 mRule.commitText("hello", 1); |
| 486 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 410 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 487 restartInput(); | 411 mRule.restartInput(); |
| 488 DOMUtils.clickNode(mContentViewCore, "input_text"); | 412 DOMUtils.clickNode(mRule.getContentViewCore(), "input_text"); |
| 489 assertWaitForKeyboardStatus(true); | 413 mRule.assertWaitForKeyboardStatus(true); |
| 490 | 414 |
| 491 assertEquals(5, mConnectionFactory.getOutAttrs().initialSelStart); | 415 Assert.assertEquals(5, mRule.getConnectionFactory().getOutAttrs().initia
lSelStart); |
| 492 assertEquals(5, mConnectionFactory.getOutAttrs().initialSelEnd); | 416 Assert.assertEquals(5, mRule.getConnectionFactory().getOutAttrs().initia
lSelEnd); |
| 493 } | 417 } |
| 494 | 418 |
| 419 @Test |
| 495 @SmallTest | 420 @SmallTest |
| 496 @DisabledTest(message = "crbug.com/694812") | 421 @DisabledTest(message = "crbug.com/694812") |
| 497 @Feature({"TextInput"}) | 422 @Feature({"TextInput"}) |
| 498 public void testShowAndHideSoftInput() throws Exception { | 423 public void testShowAndHideSoftInput() throws Exception { |
| 499 focusElement("input_radio", false); | 424 mRule.focusElement("input_radio", false); |
| 500 | 425 |
| 501 // hideSoftKeyboard(), restartInput() | 426 // hideSoftKeyboard(), mRule.restartInput() |
| 502 waitForKeyboardStates(0, 1, 1, new Integer[] {}); | 427 mRule.waitForKeyboardStates(0, 1, 1, new Integer[] {}); |
| 503 | 428 |
| 504 // When input connection is null, we still need to set flags to prevent
InputMethodService | 429 // When input connection is null, we still need to set flags to prevent
InputMethodService |
| 505 // from entering fullscreen mode and from opening custom UI. | 430 // from entering fullscreen mode and from opening custom UI. |
| 506 CriteriaHelper.pollUiThread(new Criteria() { | 431 CriteriaHelper.pollUiThread(new Criteria() { |
| 507 @Override | 432 @Override |
| 508 public boolean isSatisfied() { | 433 public boolean isSatisfied() { |
| 509 return getInputConnection() == null; | 434 return mRule.getInputConnection() == null; |
| 510 } | 435 } |
| 511 }); | 436 }); |
| 512 assertTrue( | 437 Assert.assertTrue( |
| 513 (mConnectionFactory.getOutAttrs().imeOptions | 438 (mRule.getConnectionFactory().getOutAttrs().imeOptions |
| 514 & (EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FL
AG_NO_EXTRACT_UI)) | 439 & (EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FL
AG_NO_EXTRACT_UI)) |
| 515 != 0); | 440 != 0); |
| 516 | 441 |
| 517 // showSoftInput(), restartInput() | 442 // showSoftInput(), mRule.restartInput() |
| 518 focusElement("input_number1"); | 443 mRule.focusElement("input_number1"); |
| 519 waitForKeyboardStates(1, 1, 2, new Integer[] {TextInputType.NUMBER}); | 444 mRule.waitForKeyboardStates(1, 1, 2, new Integer[] {TextInputType.NUMBER
}); |
| 520 assertNotNull(mInputMethodManagerWrapper.getInputConnection()); | 445 Assert.assertNotNull(mRule.getInputMethodManagerWrapper().getInputConnec
tion()); |
| 521 | 446 |
| 522 focusElement("input_number2"); | 447 mRule.focusElement("input_number2"); |
| 523 // Hide should never be called here. Otherwise we will see a flicker. Re
started to | 448 // Hide should never be called here. Otherwise we will see a flicker. Re
started to |
| 524 // reset internal states to handle the new input form. | 449 // reset internal states to handle the new input form. |
| 525 waitForKeyboardStates(2, 1, 3, new Integer[] {TextInputType.NUMBER, Text
InputType.NUMBER}); | 450 mRule.waitForKeyboardStates( |
| 526 | 451 2, 1, 3, new Integer[] {TextInputType.NUMBER, TextInputType.NUMB
ER}); |
| 527 focusElement("input_text"); | 452 |
| 528 // showSoftInput() on input_text. restartInput() on input_number1 due to
focus change, | 453 mRule.focusElement("input_text"); |
| 529 // and restartInput() on input_text later. | 454 // showSoftInput() on input_text. mRule.restartInput() on input_number1
due to focus change, |
| 530 waitForKeyboardStates(3, 1, 4, | 455 // and mRule.restartInput() on input_text later. |
| 456 mRule.waitForKeyboardStates(3, 1, 4, |
| 531 new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextI
nputType.TEXT}); | 457 new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextI
nputType.TEXT}); |
| 532 | 458 |
| 533 resetUpdateSelectionList(); | 459 mRule.resetUpdateSelectionList(); |
| 534 setComposingText("a", 1); | 460 mRule.setComposingText("a", 1); |
| 535 waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); | 461 mRule.waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); |
| 536 resetUpdateSelectionList(); | 462 mRule.resetUpdateSelectionList(); |
| 537 | 463 |
| 538 // JavaScript changes focus. | 464 // JavaScript changes focus. |
| 539 String code = "(function() { " | 465 String code = "(function() { " |
| 540 + "var textarea = document.getElementById('textarea');" | 466 + "var textarea = document.getElementById('textarea');" |
| 541 + "textarea.focus();" | 467 + "textarea.focus();" |
| 542 + "})();"; | 468 + "})();"; |
| 543 JavaScriptUtils.executeJavaScriptAndWaitForResult( | 469 JavaScriptUtils.executeJavaScriptAndWaitForResult( |
| 544 getContentViewCore().getWebContents(), code); | 470 mRule.getContentViewCore().getWebContents(), code); |
| 545 waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); | 471 mRule.waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); |
| 546 resetUpdateSelectionList(); | 472 mRule.resetUpdateSelectionList(); |
| 547 | 473 |
| 548 waitForKeyboardStates(4, 1, 5, new Integer[] { | 474 mRule.waitForKeyboardStates(4, 1, 5, |
| 549 TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.TEXT, | 475 new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextI
nputType.TEXT, |
| 550 TextInputType.TEXT_AREA}); | 476 TextInputType.TEXT_AREA}); |
| 551 assertEquals(0, mConnectionFactory.getOutAttrs().initialSelStart); | 477 Assert.assertEquals(0, mRule.getConnectionFactory().getOutAttrs().initia
lSelStart); |
| 552 assertEquals(0, mConnectionFactory.getOutAttrs().initialSelEnd); | 478 Assert.assertEquals(0, mRule.getConnectionFactory().getOutAttrs().initia
lSelEnd); |
| 553 | 479 |
| 554 setComposingText("aa", 1); | 480 mRule.setComposingText("aa", 1); |
| 555 waitAndVerifyUpdateSelection(0, 2, 2, 0, 2); | 481 mRule.waitAndVerifyUpdateSelection(0, 2, 2, 0, 2); |
| 556 | 482 |
| 557 focusElement("input_text"); | 483 mRule.focusElement("input_text"); |
| 558 waitForKeyboardStates(5, 1, 6, new Integer[] { | 484 mRule.waitForKeyboardStates(5, 1, 6, |
| 559 TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.TEXT, | 485 new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextI
nputType.TEXT, |
| 560 TextInputType.TEXT_AREA, TextInputType.TEXT}); | 486 TextInputType.TEXT_AREA, TextInputType.TEXT}); |
| 561 assertEquals(1, mConnectionFactory.getOutAttrs().initialSelStart); | 487 Assert.assertEquals(1, mRule.getConnectionFactory().getOutAttrs().initia
lSelStart); |
| 562 assertEquals(1, mConnectionFactory.getOutAttrs().initialSelEnd); | 488 Assert.assertEquals(1, mRule.getConnectionFactory().getOutAttrs().initia
lSelEnd); |
| 563 | 489 |
| 564 focusElement("input_radio", false); | 490 mRule.focusElement("input_radio", false); |
| 565 // hideSoftInput(), restartInput() | 491 // hideSoftInput(), mRule.restartInput() |
| 566 waitForKeyboardStates(5, 2, 7, new Integer[] { | 492 mRule.waitForKeyboardStates(5, 2, 7, |
| 567 TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.TEXT, | 493 new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER, TextI
nputType.TEXT, |
| 568 TextInputType.TEXT_AREA, TextInputType.TEXT}); | 494 TextInputType.TEXT_AREA, TextInputType.TEXT}); |
| 569 } | 495 } |
| 570 | 496 @Test |
| 571 private void assertTextsAroundCursor( | |
| 572 CharSequence before, CharSequence selected, CharSequence after) thro
ws Exception { | |
| 573 assertEquals(before, getTextBeforeCursor(100, 0)); | |
| 574 assertEquals(selected, getSelectedText(0)); | |
| 575 assertEquals(after, getTextAfterCursor(100, 0)); | |
| 576 } | |
| 577 | |
| 578 private void waitForKeyboardStates(int show, int hide, int restart, Integer[
] history) { | |
| 579 final String expected = stringifyKeyboardStates(show, hide, restart, his
tory); | |
| 580 CriteriaHelper.pollUiThread(Criteria.equals(expected, new Callable<Strin
g>() { | |
| 581 @Override | |
| 582 public String call() { | |
| 583 return getKeyboardStates(); | |
| 584 } | |
| 585 })); | |
| 586 } | |
| 587 | |
| 588 private void resetAllStates() { | |
| 589 mInputMethodManagerWrapper.reset(); | |
| 590 mConnectionFactory.clearTextInputTypeHistory(); | |
| 591 } | |
| 592 | |
| 593 private String getKeyboardStates() { | |
| 594 int showCount = mInputMethodManagerWrapper.getShowSoftInputCounter(); | |
| 595 int hideCount = mInputMethodManagerWrapper.getHideSoftInputCounter(); | |
| 596 int restartCount = mInputMethodManagerWrapper.getRestartInputCounter(); | |
| 597 Integer[] history = mConnectionFactory.getTextInputTypeHistory(); | |
| 598 return stringifyKeyboardStates(showCount, hideCount, restartCount, histo
ry); | |
| 599 } | |
| 600 | |
| 601 private String stringifyKeyboardStates(int show, int hide, int restart, Inte
ger[] history) { | |
| 602 return "show count: " + show + ", hide count: " + hide + ", restart coun
t: " + restart | |
| 603 + ", input type history: " + Arrays.deepToString(history); | |
| 604 } | |
| 605 | |
| 606 @SmallTest | 497 @SmallTest |
| 607 @Feature({"TextInput"}) | 498 @Feature({"TextInput"}) |
| 608 public void testKeyboardNotDismissedAfterCopySelection() throws Exception { | 499 public void testKeyboardNotDismissedAfterCopySelection() throws Exception { |
| 609 commitText("Sample Text", 1); | 500 mRule.commitText("Sample Text", 1); |
| 610 waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); | 501 mRule.waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); |
| 611 | 502 |
| 612 // Select 'text' part. | 503 // Select 'text' part. |
| 613 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 504 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 614 | 505 |
| 615 assertWaitForSelectActionBarStatus(true); | 506 mRule.assertWaitForSelectActionBarStatus(true); |
| 616 | 507 |
| 617 selectAll(); | 508 mRule.selectAll(); |
| 618 copy(); | 509 mRule.copy(); |
| 619 assertClipboardContents(getActivity(), "Sample Text"); | 510 mRule.assertClipboardContents(mRule.getActivity(), "Sample Text"); |
| 620 assertEquals(11, mInputMethodManagerWrapper.getSelection().end()); | 511 Assert.assertEquals(11, mRule.getInputMethodManagerWrapper().getSelectio
n().end()); |
| 621 assertWaitForKeyboardStatus(true); | 512 mRule.assertWaitForKeyboardStatus(true); |
| 622 } | 513 } |
| 623 | 514 |
| 515 @Test |
| 624 @SmallTest | 516 @SmallTest |
| 625 @Feature({"TextInput"}) | 517 @Feature({"TextInput"}) |
| 626 public void testImeNotDismissedAfterCutSelection() throws Exception { | 518 public void testImeNotDismissedAfterCutSelection() throws Exception { |
| 627 commitText("Sample Text", 1); | 519 mRule.commitText("Sample Text", 1); |
| 628 waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); | 520 mRule.waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); |
| 629 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 521 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 630 assertWaitForSelectActionBarStatus(true); | 522 mRule.assertWaitForSelectActionBarStatus(true); |
| 631 assertWaitForKeyboardStatus(true); | 523 mRule.assertWaitForKeyboardStatus(true); |
| 632 cut(); | 524 mRule.cut(); |
| 633 assertWaitForKeyboardStatus(true); | 525 mRule.assertWaitForKeyboardStatus(true); |
| 634 assertWaitForSelectActionBarStatus(false); | 526 mRule.assertWaitForSelectActionBarStatus(false); |
| 635 } | 527 } |
| 636 | 528 |
| 529 @Test |
| 637 @SmallTest | 530 @SmallTest |
| 638 @Feature({"TextInput"}) | 531 @Feature({"TextInput"}) |
| 639 public void testImeNotShownOnLongPressingEmptyInput() throws Exception { | 532 public void testImeNotShownOnLongPressingEmptyInput() throws Exception { |
| 640 DOMUtils.focusNode(mWebContents, "input_radio"); | 533 DOMUtils.focusNode(mRule.getWebContents(), "input_radio"); |
| 641 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 534 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 642 assertWaitForKeyboardStatus(false); | 535 mRule.assertWaitForKeyboardStatus(false); |
| 643 commitText("Sample Text", 1); | 536 mRule.commitText("Sample Text", 1); |
| 644 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 537 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 645 assertWaitForKeyboardStatus(true); | 538 mRule.assertWaitForKeyboardStatus(true); |
| 646 } | 539 } |
| 647 | 540 |
| 541 @Test |
| 648 @SmallTest | 542 @SmallTest |
| 649 @Feature({"TextInput"}) | 543 @Feature({"TextInput"}) |
| 650 public void testSelectActionBarShownOnLongPressingInput() throws Exception { | 544 public void testSelectActionBarShownOnLongPressingInput() throws Exception { |
| 651 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 545 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 652 assertWaitForSelectActionBarStatus(false); | 546 mRule.assertWaitForSelectActionBarStatus(false); |
| 653 commitText("Sample Text", 1); | 547 mRule.commitText("Sample Text", 1); |
| 654 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 548 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 655 assertWaitForSelectActionBarStatus(true); | 549 mRule.assertWaitForSelectActionBarStatus(true); |
| 656 } | 550 } |
| 657 | 551 |
| 552 @Test |
| 658 @SmallTest | 553 @SmallTest |
| 659 @Feature({"TextInput"}) | 554 @Feature({"TextInput"}) |
| 660 public void testLongPressInputWhileComposingText() throws Exception { | 555 public void testLongPressInputWhileComposingText() throws Exception { |
| 661 assertWaitForSelectActionBarStatus(false); | 556 mRule.assertWaitForSelectActionBarStatus(false); |
| 662 setComposingText("Sample Text", 1); | 557 mRule.setComposingText("Sample Text", 1); |
| 663 waitAndVerifyUpdateSelection(0, 11, 11, 0, 11); | 558 mRule.waitAndVerifyUpdateSelection(0, 11, 11, 0, 11); |
| 664 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 559 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 665 | 560 |
| 666 assertWaitForSelectActionBarStatus(true); | 561 mRule.assertWaitForSelectActionBarStatus(true); |
| 667 | 562 |
| 668 // Long press will first change selection region, and then trigger IME a
pp to show up. | 563 // Long press will first change selection region, and then trigger IME a
pp to show up. |
| 669 // See RenderFrameImpl::didChangeSelection() and RenderWidget::didHandle
GestureEvent(). | 564 // See RenderFrameImpl::didChangeSelection() and RenderWidget::didHandle
GestureEvent(). |
| 670 waitAndVerifyUpdateSelection(1, 7, 11, 0, 11); | 565 mRule.waitAndVerifyUpdateSelection(1, 7, 11, 0, 11); |
| 671 | 566 |
| 672 // Now IME app wants to finish composing text because an external select
ion | 567 // Now IME app wants to finish composing text because an external select
ion |
| 673 // change has been detected. At least Google Latin IME and Samsung IME | 568 // change has been detected. At least Google Latin IME and Samsung IME |
| 674 // behave this way. | 569 // behave this way. |
| 675 finishComposingText(); | 570 mRule.finishComposingText(); |
| 676 waitAndVerifyUpdateSelection(2, 7, 11, -1, -1); | 571 mRule.waitAndVerifyUpdateSelection(2, 7, 11, -1, -1); |
| 677 } | 572 } |
| 678 | 573 |
| 574 @Test |
| 679 @SmallTest | 575 @SmallTest |
| 680 @Feature({"TextInput"}) | 576 @Feature({"TextInput"}) |
| 681 public void testImeShownWhenLongPressOnAlreadySelectedText() throws Exceptio
n { | 577 public void testImeShownWhenLongPressOnAlreadySelectedText() throws Exceptio
n { |
| 682 assertWaitForSelectActionBarStatus(false); | 578 mRule.assertWaitForSelectActionBarStatus(false); |
| 683 commitText("Sample Text", 1); | 579 mRule.commitText("Sample Text", 1); |
| 684 | 580 |
| 685 int showCount = mInputMethodManagerWrapper.getShowSoftInputCounter(); | 581 int showCount = mRule.getInputMethodManagerWrapper().getShowSoftInputCou
nter(); |
| 686 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 582 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 687 assertWaitForSelectActionBarStatus(true); | 583 mRule.assertWaitForSelectActionBarStatus(true); |
| 688 assertEquals(showCount + 1, mInputMethodManagerWrapper.getShowSoftInputC
ounter()); | 584 Assert.assertEquals( |
| 585 showCount + 1, mRule.getInputMethodManagerWrapper().getShowSoftI
nputCounter()); |
| 689 | 586 |
| 690 // Now long press again. Selection region remains the same, but the logi
c | 587 // Now long press again. Selection region remains the same, but the logi
c |
| 691 // should trigger IME to show up. Note that Android does not provide sho
w / | 588 // should trigger IME to show up. Note that Android does not provide sho
w / |
| 692 // hide status of IME, so we will just check whether showIme() has been
triggered. | 589 // hide status of IME, so we will just check whether showIme() has been
triggered. |
| 693 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 590 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 694 final int newCount = showCount + 2; | 591 final int newCount = showCount + 2; |
| 695 CriteriaHelper.pollUiThread(Criteria.equals(newCount, new Callable<Integ
er>() { | 592 CriteriaHelper.pollUiThread(Criteria.equals(newCount, new Callable<Integ
er>() { |
| 696 @Override | 593 @Override |
| 697 public Integer call() { | 594 public Integer call() { |
| 698 return mInputMethodManagerWrapper.getShowSoftInputCounter(); | 595 return mRule.getInputMethodManagerWrapper().getShowSoftInputCoun
ter(); |
| 699 } | 596 } |
| 700 })); | 597 })); |
| 701 } | 598 } |
| 702 | 599 |
| 703 private void attachPhysicalKeyboard() { | 600 private void attachPhysicalKeyboard() { |
| 704 Configuration hardKeyboardConfig = | 601 Configuration hardKeyboardConfig = new Configuration( |
| 705 new Configuration(mContentViewCore.getContext().getResources().g
etConfiguration()); | 602 mRule.getContentViewCore().getContext().getResources().getConfig
uration()); |
| 706 hardKeyboardConfig.keyboard = Configuration.KEYBOARD_QWERTY; | 603 hardKeyboardConfig.keyboard = Configuration.KEYBOARD_QWERTY; |
| 707 hardKeyboardConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; | 604 hardKeyboardConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; |
| 708 hardKeyboardConfig.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN
_NO; | 605 hardKeyboardConfig.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN
_NO; |
| 709 onConfigurationChanged(hardKeyboardConfig); | 606 onConfigurationChanged(hardKeyboardConfig); |
| 710 } | 607 } |
| 711 | 608 |
| 712 private void detachPhysicalKeyboard() { | 609 private void detachPhysicalKeyboard() { |
| 713 Configuration softKeyboardConfig = | 610 Configuration softKeyboardConfig = new Configuration( |
| 714 new Configuration(mContentViewCore.getContext().getResources().g
etConfiguration()); | 611 mRule.getContentViewCore().getContext().getResources().getConfig
uration()); |
| 715 softKeyboardConfig.keyboard = Configuration.KEYBOARD_NOKEYS; | 612 softKeyboardConfig.keyboard = Configuration.KEYBOARD_NOKEYS; |
| 716 softKeyboardConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; | 613 softKeyboardConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; |
| 717 softKeyboardConfig.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN
_YES; | 614 softKeyboardConfig.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN
_YES; |
| 718 onConfigurationChanged(softKeyboardConfig); | 615 onConfigurationChanged(softKeyboardConfig); |
| 719 } | 616 } |
| 720 | 617 |
| 721 private void onConfigurationChanged(final Configuration config) { | 618 private void onConfigurationChanged(final Configuration config) { |
| 722 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 619 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 723 @Override | 620 @Override |
| 724 public void run() { | 621 public void run() { |
| 725 mContentViewCore.onConfigurationChanged(config); | 622 mRule.getContentViewCore().onConfigurationChanged(config); |
| 726 } | 623 } |
| 727 }); | 624 }); |
| 728 } | 625 } |
| 729 | 626 |
| 730 private void reloadPage() throws Throwable { | 627 private void reloadPage() throws Throwable { |
| 731 // Reload the page, then focus will be lost and keyboard should be hidde
n. | 628 // Reload the page, then focus will be lost and keyboard should be hidde
n. |
| 732 fullyLoadUrl(getContentViewCore().getWebContents().getUrl()); | 629 mRule.fullyLoadUrl(mRule.getContentViewCore().getWebContents().getUrl())
; |
| 733 } | 630 } |
| 734 | 631 |
| 632 @Test |
| 735 @SmallTest | 633 @SmallTest |
| 736 @Feature({"TextInput"}) | 634 @Feature({"TextInput"}) |
| 737 public void testPhysicalKeyboard_AttachDetach() throws Throwable { | 635 public void testPhysicalKeyboard_AttachDetach() throws Throwable { |
| 738 attachPhysicalKeyboard(); | 636 attachPhysicalKeyboard(); |
| 739 // We still call showSoftKeyboard, which will be ignored by physical key
board. | 637 // We still call showSoftKeyboard, which will be ignored by physical key
board. |
| 740 waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT}); | 638 mRule.waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT})
; |
| 741 setComposingText("a", 1); | 639 mRule.setComposingText("a", 1); |
| 742 waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT}); | 640 mRule.waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT})
; |
| 743 detachPhysicalKeyboard(); | 641 detachPhysicalKeyboard(); |
| 744 assertWaitForKeyboardStatus(true); | 642 mRule.assertWaitForKeyboardStatus(true); |
| 745 // Now we really show soft keyboard. We also call restartInput when conf
iguration changes. | 643 // Now we really show soft keyboard. We also call mRule.restartInput whe
n configuration |
| 746 waitForKeyboardStates(2, 0, 2, new Integer[] {TextInputType.TEXT, TextIn
putType.TEXT}); | 644 // changes. |
| 645 mRule.waitForKeyboardStates( |
| 646 2, 0, 2, new Integer[] {TextInputType.TEXT, TextInputType.TEXT})
; |
| 747 | 647 |
| 748 reloadPage(); | 648 reloadPage(); |
| 749 | 649 |
| 750 // Depending on the timing, hideSoftInput and restartInput call counts m
ay vary here | 650 // Depending on the timing, hideSoftInput and mRule.restartInput call co
unts may vary here |
| 751 // because render widget gets restarted. But the end result should be th
e same. | 651 // because render widget gets restarted. But the end result should be th
e same. |
| 752 assertWaitForKeyboardStatus(false); | 652 mRule.assertWaitForKeyboardStatus(false); |
| 753 | 653 |
| 754 detachPhysicalKeyboard(); | 654 detachPhysicalKeyboard(); |
| 755 | 655 |
| 756 try { | 656 try { |
| 757 // We should not show soft keyboard here because focus has been lost
. | 657 // We should not show soft keyboard here because focus has been lost
. |
| 758 CriteriaHelper.pollUiThread(new Criteria() { | 658 CriteriaHelper.pollUiThread(new Criteria() { |
| 759 @Override | 659 @Override |
| 760 public boolean isSatisfied() { | 660 public boolean isSatisfied() { |
| 761 return mInputMethodManagerWrapper.isShowWithoutHideOutstandi
ng(); | 661 return mRule.getInputMethodManagerWrapper().isShowWithoutHid
eOutstanding(); |
| 762 } | 662 } |
| 763 }); | 663 }); |
| 764 fail("Keyboard incorrectly showing"); | 664 Assert.fail("Keyboard incorrectly showing"); |
| 765 } catch (AssertionError e) { | 665 } catch (AssertionError e) { |
| 766 // TODO(tedchoc): This is horrible and should never timeout to deter
mine success. | 666 // TODO(tedchoc): This is horrible and should never timeout to deter
mine success. |
| 767 } | 667 } |
| 768 } | 668 } |
| 769 | 669 |
| 670 @Test |
| 770 @SmallTest | 671 @SmallTest |
| 771 @Feature({"TextInput"}) | 672 @Feature({"TextInput"}) |
| 772 public void testSelectActionBarClearedOnTappingInput() throws Exception { | 673 public void testSelectActionBarClearedOnTappingInput() throws Exception { |
| 773 commitText("Sample Text", 1); | 674 mRule.commitText("Sample Text", 1); |
| 774 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 675 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 775 assertWaitForKeyboardStatus(true); | 676 mRule.assertWaitForKeyboardStatus(true); |
| 776 assertWaitForSelectActionBarStatus(true); | 677 mRule.assertWaitForSelectActionBarStatus(true); |
| 777 DOMUtils.clickNode(mContentViewCore, "input_text"); | 678 DOMUtils.clickNode(mRule.getContentViewCore(), "input_text"); |
| 778 assertWaitForSelectActionBarStatus(false); | 679 mRule.assertWaitForSelectActionBarStatus(false); |
| 779 } | 680 } |
| 780 | 681 |
| 682 @Test |
| 781 @SmallTest | 683 @SmallTest |
| 782 @Feature({"TextInput"}) | 684 @Feature({"TextInput"}) |
| 783 public void testSelectActionBarClearedOnTappingOutsideInput() throws Excepti
on { | 685 public void testSelectActionBarClearedOnTappingOutsideInput() throws Excepti
on { |
| 784 commitText("Sample Text", 1); | 686 mRule.commitText("Sample Text", 1); |
| 785 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 687 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 786 assertWaitForKeyboardStatus(true); | 688 mRule.assertWaitForKeyboardStatus(true); |
| 787 assertWaitForSelectActionBarStatus(true); | 689 mRule.assertWaitForSelectActionBarStatus(true); |
| 788 DOMUtils.clickNode(mContentViewCore, "plain_text"); | 690 DOMUtils.clickNode(mRule.getContentViewCore(), "plain_text"); |
| 789 assertWaitForKeyboardStatus(false); | 691 mRule.assertWaitForKeyboardStatus(false); |
| 790 assertWaitForSelectActionBarStatus(false); | 692 mRule.assertWaitForSelectActionBarStatus(false); |
| 791 } | 693 } |
| 792 | 694 |
| 695 @Test |
| 793 @SmallTest | 696 @SmallTest |
| 794 @Feature({"TextInput"}) | 697 @Feature({"TextInput"}) |
| 795 public void testImeNotShownOnLongPressingDifferentEmptyInputs() throws Excep
tion { | 698 public void testImeNotShownOnLongPressingDifferentEmptyInputs() throws Excep
tion { |
| 796 DOMUtils.focusNode(mWebContents, "input_radio"); | 699 DOMUtils.focusNode(mRule.getWebContents(), "input_radio"); |
| 797 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 700 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 798 assertWaitForKeyboardStatus(false); | 701 mRule.assertWaitForKeyboardStatus(false); |
| 799 DOMUtils.longPressNode(mContentViewCore, "textarea"); | 702 DOMUtils.longPressNode(mRule.getContentViewCore(), "textarea"); |
| 800 assertWaitForKeyboardStatus(false); | 703 mRule.assertWaitForKeyboardStatus(false); |
| 801 } | 704 } |
| 802 | 705 |
| 706 @Test |
| 803 @SmallTest | 707 @SmallTest |
| 804 @Feature({"TextInput"}) | 708 @Feature({"TextInput"}) |
| 805 public void testImeStaysOnLongPressingDifferentNonEmptyInputs() throws Excep
tion { | 709 public void testImeStaysOnLongPressingDifferentNonEmptyInputs() throws Excep
tion { |
| 806 DOMUtils.focusNode(mWebContents, "input_text"); | 710 DOMUtils.focusNode(mRule.getWebContents(), "input_text"); |
| 807 assertWaitForKeyboardStatus(true); | 711 mRule.assertWaitForKeyboardStatus(true); |
| 808 | 712 |
| 809 commitText("Sample Text", 1); | 713 mRule.commitText("Sample Text", 1); |
| 810 // We should wait to avoid race condition. | 714 // We should wait to avoid race condition. |
| 811 waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); | 715 mRule.waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); |
| 812 | 716 |
| 813 DOMUtils.focusNode(mWebContents, "textarea"); | 717 DOMUtils.focusNode(mRule.getWebContents(), "textarea"); |
| 814 waitAndVerifyUpdateSelection(1, 0, 0, -1, -1); | 718 mRule.waitAndVerifyUpdateSelection(1, 0, 0, -1, -1); |
| 815 | 719 |
| 816 commitText("Sample Text", 1); | 720 mRule.commitText("Sample Text", 1); |
| 817 waitAndVerifyUpdateSelection(2, 11, 11, -1, -1); | 721 mRule.waitAndVerifyUpdateSelection(2, 11, 11, -1, -1); |
| 818 | 722 |
| 819 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 723 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 820 assertWaitForKeyboardStatus(true); | 724 mRule.assertWaitForKeyboardStatus(true); |
| 821 assertWaitForSelectActionBarStatus(true); | 725 mRule.assertWaitForSelectActionBarStatus(true); |
| 822 | 726 |
| 823 DOMUtils.longPressNode(mContentViewCore, "textarea"); | 727 DOMUtils.longPressNode(mRule.getContentViewCore(), "textarea"); |
| 824 assertWaitForKeyboardStatus(true); | 728 mRule.assertWaitForKeyboardStatus(true); |
| 825 } | 729 } |
| 826 | 730 |
| 731 @Test |
| 827 @SmallTest | 732 @SmallTest |
| 828 @Feature({"TextInput"}) | 733 @Feature({"TextInput"}) |
| 829 public void testImeCut() throws Exception { | 734 public void testImeCut() throws Exception { |
| 830 commitText("snarful", 1); | 735 mRule.commitText("snarful", 1); |
| 831 waitAndVerifyUpdateSelection(0, 7, 7, -1, -1); | 736 mRule.waitAndVerifyUpdateSelection(0, 7, 7, -1, -1); |
| 832 | 737 |
| 833 setSelection(1, 5); | 738 mRule.setSelection(1, 5); |
| 834 waitAndVerifyUpdateSelection(1, 1, 5, -1, -1); | 739 mRule.waitAndVerifyUpdateSelection(1, 1, 5, -1, -1); |
| 835 | 740 |
| 836 cut(); | 741 mRule.cut(); |
| 837 waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); | 742 mRule.waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); |
| 838 assertTextsAroundCursor("s", null, "ul"); | 743 mRule.assertTextsAroundCursor("s", null, "ul"); |
| 839 assertClipboardContents(getActivity(), "narf"); | 744 mRule.assertClipboardContents(mRule.getActivity(), "narf"); |
| 840 } | 745 } |
| 841 | 746 |
| 747 @Test |
| 842 @SmallTest | 748 @SmallTest |
| 843 @Feature({"TextInput"}) | 749 @Feature({"TextInput"}) |
| 844 public void testImePaste() throws Exception { | 750 public void testImePaste() throws Exception { |
| 845 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 751 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 846 @Override | 752 @Override |
| 847 public void run() { | 753 public void run() { |
| 848 ClipboardManager clipboardManager = | 754 ClipboardManager clipboardManager = |
| 849 (ClipboardManager) getActivity().getSystemService( | 755 (ClipboardManager) mRule.getActivity().getSystemService( |
| 850 Context.CLIPBOARD_SERVICE); | 756 Context.CLIPBOARD_SERVICE); |
| 851 clipboardManager.setPrimaryClip(ClipData.newPlainText("blarg", "
blarg")); | 757 clipboardManager.setPrimaryClip(ClipData.newPlainText("blarg", "
blarg")); |
| 852 } | 758 } |
| 853 }); | 759 }); |
| 854 | 760 |
| 855 paste(); | 761 mRule.paste(); |
| 856 // Paste is a two step process when there is a non-zero selection. | 762 // Paste is a two step process when there is a non-zero selection. |
| 857 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 763 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 858 assertTextsAroundCursor("blarg", null, ""); | 764 mRule.assertTextsAroundCursor("blarg", null, ""); |
| 859 | 765 |
| 860 setSelection(3, 5); | 766 mRule.setSelection(3, 5); |
| 861 waitAndVerifyUpdateSelection(1, 3, 5, -1, -1); | 767 mRule.waitAndVerifyUpdateSelection(1, 3, 5, -1, -1); |
| 862 assertTextsAroundCursor("bla", "rg", ""); | 768 mRule.assertTextsAroundCursor("bla", "rg", ""); |
| 863 | 769 |
| 864 paste(); | 770 mRule.paste(); |
| 865 // Paste is a two step process when there is a non-zero selection. | 771 // Paste is a two step process when there is a non-zero selection. |
| 866 waitAndVerifyUpdateSelection(2, 8, 8, -1, -1); | 772 mRule.waitAndVerifyUpdateSelection(2, 8, 8, -1, -1); |
| 867 assertTextsAroundCursor("blablarg", null, ""); | 773 mRule.assertTextsAroundCursor("blablarg", null, ""); |
| 868 | 774 |
| 869 paste(); | 775 mRule.paste(); |
| 870 waitAndVerifyUpdateSelection(3, 13, 13, -1, -1); | 776 mRule.waitAndVerifyUpdateSelection(3, 13, 13, -1, -1); |
| 871 assertTextsAroundCursor("blablargblarg", null, ""); | 777 mRule.assertTextsAroundCursor("blablargblarg", null, ""); |
| 872 } | 778 } |
| 873 | 779 |
| 780 @Test |
| 874 @SmallTest | 781 @SmallTest |
| 875 @Feature({"TextInput"}) | 782 @Feature({"TextInput"}) |
| 876 public void testImeSelectAndCollapseSelection() throws Exception { | 783 public void testImeSelectAndCollapseSelection() throws Exception { |
| 877 commitText("hello", 1); | 784 mRule.commitText("hello", 1); |
| 878 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 785 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 879 | 786 |
| 880 selectAll(); | 787 mRule.selectAll(); |
| 881 waitAndVerifyUpdateSelection(1, 0, 5, -1, -1); | 788 mRule.waitAndVerifyUpdateSelection(1, 0, 5, -1, -1); |
| 882 | 789 |
| 883 collapseSelection(); | 790 mRule.collapseSelection(); |
| 884 waitAndVerifyUpdateSelection(2, 5, 5, -1, -1); | 791 mRule.waitAndVerifyUpdateSelection(2, 5, 5, -1, -1); |
| 885 } | 792 } |
| 886 | 793 |
| 794 @Test |
| 887 @SmallTest | 795 @SmallTest |
| 888 @Feature({"TextInput", "Main"}) | 796 @Feature({"TextInput", "Main"}) |
| 889 public void testShowImeIfNeeded() throws Throwable { | 797 public void testShowImeIfNeeded() throws Throwable { |
| 890 // showImeIfNeeded() is now implicitly called by the updated focus | 798 // showImeIfNeeded() is now implicitly called by the updated focus |
| 891 // heuristic so no need to call explicitly. http://crbug.com/371927 | 799 // heuristic so no need to call explicitly. http://crbug.com/371927 |
| 892 DOMUtils.focusNode(mWebContents, "input_radio"); | 800 DOMUtils.focusNode(mRule.getWebContents(), "input_radio"); |
| 893 assertWaitForKeyboardStatus(false); | 801 mRule.assertWaitForKeyboardStatus(false); |
| 894 | 802 |
| 895 DOMUtils.focusNode(mWebContents, "input_text"); | 803 DOMUtils.focusNode(mRule.getWebContents(), "input_text"); |
| 896 assertWaitForKeyboardStatus(true); | 804 mRule.assertWaitForKeyboardStatus(true); |
| 897 } | 805 } |
| 898 | 806 |
| 807 @Test |
| 899 @SmallTest | 808 @SmallTest |
| 900 @Feature({"TextInput", "Main"}) | 809 @Feature({"TextInput", "Main"}) |
| 901 public void testFinishComposingText() throws Throwable { | 810 public void testFinishComposingText() throws Throwable { |
| 902 focusElementAndWaitForStateUpdate("textarea"); | 811 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 903 | 812 |
| 904 commitText("hllo", 1); | 813 mRule.commitText("hllo", 1); |
| 905 waitAndVerifyUpdateSelection(0, 4, 4, -1, -1); | 814 mRule.waitAndVerifyUpdateSelection(0, 4, 4, -1, -1); |
| 906 | 815 |
| 907 commitText(" ", 1); | 816 mRule.commitText(" ", 1); |
| 908 waitAndVerifyUpdateSelection(1, 5, 5, -1, -1); | 817 mRule.waitAndVerifyUpdateSelection(1, 5, 5, -1, -1); |
| 909 | 818 |
| 910 setSelection(1, 1); | 819 mRule.setSelection(1, 1); |
| 911 waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); | 820 mRule.waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); |
| 912 assertTextsAroundCursor("h", null, "llo "); | 821 mRule.assertTextsAroundCursor("h", null, "llo "); |
| 913 | 822 |
| 914 setComposingRegion(0, 4); | 823 mRule.setComposingRegion(0, 4); |
| 915 waitAndVerifyUpdateSelection(3, 1, 1, 0, 4); | 824 mRule.waitAndVerifyUpdateSelection(3, 1, 1, 0, 4); |
| 916 | 825 |
| 917 finishComposingText(); | 826 mRule.finishComposingText(); |
| 918 waitAndVerifyUpdateSelection(4, 1, 1, -1, -1); | 827 mRule.waitAndVerifyUpdateSelection(4, 1, 1, -1, -1); |
| 919 | 828 |
| 920 commitText("\n", 1); | 829 mRule.commitText("\n", 1); |
| 921 waitAndVerifyUpdateSelection(5, 2, 2, -1, -1); | 830 mRule.waitAndVerifyUpdateSelection(5, 2, 2, -1, -1); |
| 922 assertTextsAroundCursor("h\n", null, "llo "); | 831 mRule.assertTextsAroundCursor("h\n", null, "llo "); |
| 923 } | 832 } |
| 924 | 833 |
| 925 // http://crbug.com/445499 | 834 // http://crbug.com/445499 |
| 835 @Test |
| 926 @SmallTest | 836 @SmallTest |
| 927 @Feature({"TextInput", "Main"}) | 837 @Feature({"TextInput", "Main"}) |
| 928 public void testDeleteText() throws Throwable { | 838 public void testDeleteText() throws Throwable { |
| 929 focusElement("textarea"); | 839 mRule.focusElement("textarea"); |
| 930 | 840 |
| 931 // The calls below are a reflection of what the stock Google Keyboard (A
ndr | 841 // The calls below are a reflection of what the stock Google Keyboard (A
ndr |
| 932 // when the noted key is touched on screen. | 842 // when the noted key is touched on screen. |
| 933 // H | 843 // H |
| 934 setComposingText("h", 1); | 844 mRule.setComposingText("h", 1); |
| 935 assertEquals("h", getTextBeforeCursor(9, 0)); | 845 Assert.assertEquals("h", mRule.getTextBeforeCursor(9, 0)); |
| 936 | 846 |
| 937 // O | 847 // O |
| 938 setComposingText("ho", 1); | 848 mRule.setComposingText("ho", 1); |
| 939 assertEquals("ho", getTextBeforeCursor(9, 0)); | 849 Assert.assertEquals("ho", mRule.getTextBeforeCursor(9, 0)); |
| 940 | 850 |
| 941 setComposingText("h", 1); | 851 mRule.setComposingText("h", 1); |
| 942 setComposingRegion(0, 1); | 852 mRule.setComposingRegion(0, 1); |
| 943 setComposingText("h", 1); | 853 mRule.setComposingText("h", 1); |
| 944 assertEquals("h", getTextBeforeCursor(9, 0)); | 854 Assert.assertEquals("h", mRule.getTextBeforeCursor(9, 0)); |
| 945 | 855 |
| 946 // I | 856 // I |
| 947 setComposingText("hi", 1); | 857 mRule.setComposingText("hi", 1); |
| 948 assertEquals("hi", getTextBeforeCursor(9, 0)); | 858 Assert.assertEquals("hi", mRule.getTextBeforeCursor(9, 0)); |
| 949 | 859 |
| 950 // SPACE | 860 // SPACE |
| 951 commitText("hi", 1); | 861 mRule.commitText("hi", 1); |
| 952 commitText(" ", 1); | 862 mRule.commitText(" ", 1); |
| 953 assertEquals("hi ", getTextBeforeCursor(9, 0)); | 863 Assert.assertEquals("hi ", mRule.getTextBeforeCursor(9, 0)); |
| 954 | 864 |
| 955 // DEL | 865 // DEL |
| 956 deleteSurroundingText(1, 0); | 866 mRule.deleteSurroundingText(1, 0); |
| 957 setComposingRegion(0, 2); | 867 mRule.setComposingRegion(0, 2); |
| 958 assertEquals("hi", getTextBeforeCursor(9, 0)); | 868 Assert.assertEquals("hi", mRule.getTextBeforeCursor(9, 0)); |
| 959 | 869 |
| 960 setComposingText("h", 1); | 870 mRule.setComposingText("h", 1); |
| 961 assertEquals("h", getTextBeforeCursor(9, 0)); | 871 Assert.assertEquals("h", mRule.getTextBeforeCursor(9, 0)); |
| 962 | 872 |
| 963 commitText("", 1); | 873 mRule.commitText("", 1); |
| 964 assertEquals("", getTextBeforeCursor(9, 0)); | 874 Assert.assertEquals("", mRule.getTextBeforeCursor(9, 0)); |
| 965 | 875 |
| 966 // DEL (on empty input) | 876 // DEL (on empty input) |
| 967 deleteSurroundingText(1, 0); // DEL on empty still sends 1,0 | 877 mRule.deleteSurroundingText(1, 0); // DEL on empty still sends 1,0 |
| 968 assertEquals("", getTextBeforeCursor(9, 0)); | 878 Assert.assertEquals("", mRule.getTextBeforeCursor(9, 0)); |
| 969 } | 879 } |
| 970 | 880 |
| 971 | 881 @Test |
| 972 @SmallTest | 882 @SmallTest |
| 973 @Feature({"TextInput", "Main"}) | 883 @Feature({"TextInput", "Main"}) |
| 974 public void testSwipingText() throws Throwable { | 884 public void testSwipingText() throws Throwable { |
| 975 focusElement("textarea"); | 885 mRule.focusElement("textarea"); |
| 976 | 886 |
| 977 // The calls below are a reflection of what the stock Google Keyboard (A
ndroid 4.4) sends | 887 // The calls below are a reflection of what the stock Google Keyboard (A
ndroid 4.4) sends |
| 978 // when the word is swiped on the soft keyboard. Exercise care when alt
ering to make sure | 888 // when the word is swiped on the soft keyboard. Exercise care when alt
ering to make sure |
| 979 // that the test reflects reality. If this test breaks, it's possible t
hat code has | 889 // that the test reflects reality. If this test breaks, it's possible t
hat code has |
| 980 // changed and different calls need to be made instead. | 890 // changed and different calls need to be made instead. |
| 981 // "three" | 891 // "three" |
| 982 setComposingText("three", 1); | 892 mRule.setComposingText("three", 1); |
| 983 assertEquals("three", getTextBeforeCursor(99, 0)); | 893 Assert.assertEquals("three", mRule.getTextBeforeCursor(99, 0)); |
| 984 | 894 |
| 985 // "word" | 895 // "word" |
| 986 commitText("three", 1); | 896 mRule.commitText("three", 1); |
| 987 commitText(" ", 1); | 897 mRule.commitText(" ", 1); |
| 988 setComposingText("word", 1); | 898 mRule.setComposingText("word", 1); |
| 989 assertEquals("three word", getTextBeforeCursor(99, 0)); | 899 Assert.assertEquals("three word", mRule.getTextBeforeCursor(99, 0)); |
| 990 | 900 |
| 991 // "test" | 901 // "test" |
| 992 commitText("word", 1); | 902 mRule.commitText("word", 1); |
| 993 commitText(" ", 1); | 903 mRule.commitText(" ", 1); |
| 994 setComposingText("test", 1); | 904 mRule.setComposingText("test", 1); |
| 995 assertEquals("three word test", getTextBeforeCursor(99, 0)); | 905 Assert.assertEquals("three word test", mRule.getTextBeforeCursor(99, 0))
; |
| 996 } | 906 } |
| 997 | 907 |
| 908 @Test |
| 998 @SmallTest | 909 @SmallTest |
| 999 @Feature({"TextInput", "Main"}) | 910 @Feature({"TextInput", "Main"}) |
| 1000 public void testDeleteMultiCharacterCodepoint() throws Throwable { | 911 public void testDeleteMultiCharacterCodepoint() throws Throwable { |
| 1001 // This smiley is a multi character codepoint. | 912 // This smiley is a multi character codepoint. |
| 1002 final String smiley = "\uD83D\uDE0A"; | 913 final String smiley = "\uD83D\uDE0A"; |
| 1003 | 914 |
| 1004 commitText(smiley, 1); | 915 mRule.commitText(smiley, 1); |
| 1005 waitAndVerifyUpdateSelection(0, 2, 2, -1, -1); | 916 mRule.waitAndVerifyUpdateSelection(0, 2, 2, -1, -1); |
| 1006 assertTextsAroundCursor(smiley, null, ""); | 917 mRule.assertTextsAroundCursor(smiley, null, ""); |
| 1007 | 918 |
| 1008 // DEL, sent via dispatchKeyEvent like it is in Android WebView or a phy
sical keyboard. | 919 // DEL, sent via mRule.dispatchKeyEvent like it is in Android WebView or
a physical |
| 1009 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL
)); | 920 // keyboard. |
| 1010 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL))
; | 921 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DEL)); |
| 1011 | 922 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_DEL)); |
| 1012 waitAndVerifyUpdateSelection(1, 0, 0, -1, -1); | 923 |
| 924 mRule.waitAndVerifyUpdateSelection(1, 0, 0, -1, -1); |
| 1013 | 925 |
| 1014 // Make sure that we accept further typing after deleting the smiley. | 926 // Make sure that we accept further typing after deleting the smiley. |
| 1015 setComposingText("s", 1); | 927 mRule.setComposingText("s", 1); |
| 1016 setComposingText("sm", 1); | 928 mRule.setComposingText("sm", 1); |
| 1017 waitAndVerifyUpdateSelection(2, 1, 1, 0, 1); | 929 mRule.waitAndVerifyUpdateSelection(2, 1, 1, 0, 1); |
| 1018 waitAndVerifyUpdateSelection(3, 2, 2, 0, 2); | 930 mRule.waitAndVerifyUpdateSelection(3, 2, 2, 0, 2); |
| 1019 } | 931 } |
| 1020 | 932 |
| 933 @Test |
| 1021 @SmallTest | 934 @SmallTest |
| 1022 @Feature({"TextInput", "Main"}) | 935 @Feature({"TextInput", "Main"}) |
| 1023 public void testBackspaceKeycode() throws Throwable { | 936 public void testBackspaceKeycode() throws Throwable { |
| 1024 focusElement("textarea"); | 937 mRule.focusElement("textarea"); |
| 1025 | 938 |
| 1026 // H | 939 // H |
| 1027 commitText("h", 1); | 940 mRule.commitText("h", 1); |
| 1028 assertEquals("h", getTextBeforeCursor(9, 0)); | 941 Assert.assertEquals("h", mRule.getTextBeforeCursor(9, 0)); |
| 1029 | 942 |
| 1030 // O | 943 // O |
| 1031 commitText("o", 1); | 944 mRule.commitText("o", 1); |
| 1032 assertEquals("ho", getTextBeforeCursor(9, 0)); | 945 Assert.assertEquals("ho", mRule.getTextBeforeCursor(9, 0)); |
| 1033 | 946 |
| 1034 // DEL, sent via dispatchKeyEvent like it is in Android WebView or a phy
sical keyboard. | 947 // DEL, sent via mRule.dispatchKeyEvent like it is in Android WebView or
a physical |
| 1035 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL
)); | 948 // keyboard. |
| 1036 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL))
; | 949 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DEL)); |
| 950 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_DEL)); |
| 1037 | 951 |
| 1038 // DEL | 952 // DEL |
| 1039 assertEquals("h", getTextBeforeCursor(9, 0)); | 953 Assert.assertEquals("h", mRule.getTextBeforeCursor(9, 0)); |
| 1040 } | 954 } |
| 1041 | 955 |
| 956 @Test |
| 1042 @SmallTest | 957 @SmallTest |
| 1043 @Feature({"TextInput", "Main"}) | 958 @Feature({"TextInput", "Main"}) |
| 1044 public void testRepeatBackspaceKeycode() throws Throwable { | 959 public void testRepeatBackspaceKeycode() throws Throwable { |
| 1045 focusElement("textarea"); | 960 mRule.focusElement("textarea"); |
| 1046 | 961 |
| 1047 // H | 962 // H |
| 1048 commitText("h", 1); | 963 mRule.commitText("h", 1); |
| 1049 assertEquals("h", getTextBeforeCursor(9, 0)); | 964 Assert.assertEquals("h", mRule.getTextBeforeCursor(9, 0)); |
| 1050 | 965 |
| 1051 // O | 966 // O |
| 1052 commitText("o", 1); | 967 mRule.commitText("o", 1); |
| 1053 assertEquals("ho", getTextBeforeCursor(9, 0)); | 968 Assert.assertEquals("ho", mRule.getTextBeforeCursor(9, 0)); |
| 1054 | 969 |
| 1055 // Multiple keydowns should each delete one character (this is for physi
cal keyboard | 970 // Multiple keydowns should each delete one character (this is for physi
cal keyboard |
| 1056 // key-repeat). | 971 // key-repeat). |
| 1057 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL
)); | 972 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DEL)); |
| 1058 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL
)); | 973 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DEL)); |
| 1059 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL))
; | 974 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_DEL)); |
| 1060 | 975 |
| 1061 // DEL | 976 // DEL |
| 1062 assertEquals("", getTextBeforeCursor(9, 0)); | 977 Assert.assertEquals("", mRule.getTextBeforeCursor(9, 0)); |
| 1063 } | 978 } |
| 1064 | 979 |
| 980 @Test |
| 1065 @SmallTest | 981 @SmallTest |
| 1066 @Feature({"TextInput", "Main"}) | 982 @Feature({"TextInput", "Main"}) |
| 1067 public void testPhysicalKeyboard() throws Throwable { | 983 public void testPhysicalKeyboard() throws Throwable { |
| 1068 focusElementAndWaitForStateUpdate("textarea"); | 984 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 1069 | 985 |
| 1070 // Type 'a' using a physical keyboard. | 986 // Type 'a' using a physical keyboard. |
| 1071 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A))
; | 987 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_A)); |
| 1072 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A)); | 988 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_A)); |
| 1073 waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); | 989 mRule.waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); |
| 1074 | 990 |
| 1075 // Type 'enter' key. | 991 // Type 'enter' key. |
| 1076 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENT
ER)); | 992 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_ENTER)); |
| 1077 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER
)); | 993 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_ENTER)); |
| 1078 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 994 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 1079 assertTextsAroundCursor("a\n", null, "\n"); | 995 mRule.assertTextsAroundCursor("a\n", null, "\n"); |
| 1080 | 996 |
| 1081 // Type 'b'. | 997 // Type 'b'. |
| 1082 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_B))
; | 998 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_B)); |
| 1083 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_B)); | 999 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_B)); |
| 1084 waitAndVerifyUpdateSelection(2, 3, 3, -1, -1); | 1000 mRule.waitAndVerifyUpdateSelection(2, 3, 3, -1, -1); |
| 1085 assertTextsAroundCursor("a\nb", null, ""); | 1001 mRule.assertTextsAroundCursor("a\nb", null, ""); |
| 1086 } | 1002 } |
| 1087 | 1003 |
| 1004 @Test |
| 1088 @SmallTest | 1005 @SmallTest |
| 1089 @Feature({"TextInput", "Main"}) | 1006 @Feature({"TextInput", "Main"}) |
| 1090 public void testPhysicalKeyboard_AccentKeyCodes() throws Throwable { | 1007 public void testPhysicalKeyboard_AccentKeyCodes() throws Throwable { |
| 1091 focusElementAndWaitForStateUpdate("textarea"); | 1008 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 1092 | 1009 |
| 1093 // h | 1010 // h |
| 1094 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_H))
; | 1011 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_H)); |
| 1095 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_H)); | 1012 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_H)); |
| 1096 assertEquals("h", getTextBeforeCursor(9, 0)); | 1013 Assert.assertEquals("h", mRule.getTextBeforeCursor(9, 0)); |
| 1097 waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); | 1014 mRule.waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); |
| 1098 | 1015 |
| 1099 // ALT-i (circumflex accent key on virtual keyboard) | 1016 // ALT-i (circumflex accent key on virtual keyboard) |
| 1100 dispatchKeyEvent(new KeyEvent( | 1017 mRule.dispatchKeyEvent(new KeyEvent( |
| 1101 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); | 1018 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); |
| 1102 assertEquals("hˆ", getTextBeforeCursor(9, 0)); | 1019 Assert.assertEquals("hˆ", mRule.getTextBeforeCursor(9, 0)); |
| 1103 dispatchKeyEvent(new KeyEvent( | 1020 mRule.dispatchKeyEvent(new KeyEvent( |
| 1104 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); | 1021 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); |
| 1105 assertEquals("hˆ", getTextBeforeCursor(9, 0)); | 1022 Assert.assertEquals("hˆ", mRule.getTextBeforeCursor(9, 0)); |
| 1106 waitAndVerifyUpdateSelection(1, 2, 2, 1, 2); | 1023 mRule.waitAndVerifyUpdateSelection(1, 2, 2, 1, 2); |
| 1107 | 1024 |
| 1108 // o | 1025 // o |
| 1109 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_O))
; | 1026 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_O)); |
| 1110 assertEquals("hô", getTextBeforeCursor(9, 0)); | 1027 Assert.assertEquals("hô", mRule.getTextBeforeCursor(9, 0)); |
| 1111 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_O)); | 1028 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_O)); |
| 1112 assertEquals("hô", getTextBeforeCursor(9, 0)); | 1029 Assert.assertEquals("hô", mRule.getTextBeforeCursor(9, 0)); |
| 1113 waitAndVerifyUpdateSelection(2, 2, 2, -1, -1); | 1030 mRule.waitAndVerifyUpdateSelection(2, 2, 2, -1, -1); |
| 1114 | 1031 |
| 1115 // ALT-i | 1032 // ALT-i |
| 1116 dispatchKeyEvent(new KeyEvent( | 1033 mRule.dispatchKeyEvent(new KeyEvent( |
| 1117 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); | 1034 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); |
| 1118 dispatchKeyEvent(new KeyEvent( | 1035 mRule.dispatchKeyEvent(new KeyEvent( |
| 1119 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); | 1036 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); |
| 1120 assertEquals("hôˆ", getTextBeforeCursor(9, 0)); | 1037 Assert.assertEquals("hôˆ", mRule.getTextBeforeCursor(9, 0)); |
| 1121 waitAndVerifyUpdateSelection(3, 3, 3, 2, 3); | 1038 mRule.waitAndVerifyUpdateSelection(3, 3, 3, 2, 3); |
| 1122 | 1039 |
| 1123 // ALT-i again should have no effect | 1040 // ALT-i again should have no effect |
| 1124 dispatchKeyEvent(new KeyEvent( | 1041 mRule.dispatchKeyEvent(new KeyEvent( |
| 1125 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); | 1042 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); |
| 1126 dispatchKeyEvent(new KeyEvent( | 1043 mRule.dispatchKeyEvent(new KeyEvent( |
| 1127 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); | 1044 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); |
| 1128 assertEquals("hôˆ", getTextBeforeCursor(9, 0)); | 1045 Assert.assertEquals("hôˆ", mRule.getTextBeforeCursor(9, 0)); |
| 1129 | 1046 |
| 1130 // b (cannot be accented, should just appear after) | 1047 // b (cannot be accented, should just appear after) |
| 1131 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_B))
; | 1048 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_B)); |
| 1132 assertEquals("hôˆb", getTextBeforeCursor(9, 0)); | 1049 Assert.assertEquals("hôˆb", mRule.getTextBeforeCursor(9, 0)); |
| 1133 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_B)); | 1050 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_B)); |
| 1134 assertEquals("hôˆb", getTextBeforeCursor(9, 0)); | 1051 Assert.assertEquals("hôˆb", mRule.getTextBeforeCursor(9, 0)); |
| 1135 int index = 4; | 1052 int index = 4; |
| 1136 waitAndVerifyUpdateSelection(index++, 4, 4, -1, -1); | 1053 mRule.waitAndVerifyUpdateSelection(index++, 4, 4, -1, -1); |
| 1137 | 1054 |
| 1138 // ALT-i | 1055 // ALT-i |
| 1139 dispatchKeyEvent(new KeyEvent( | 1056 mRule.dispatchKeyEvent(new KeyEvent( |
| 1140 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); | 1057 0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META
_ALT_ON)); |
| 1141 dispatchKeyEvent(new KeyEvent( | 1058 mRule.dispatchKeyEvent(new KeyEvent( |
| 1142 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); | 1059 0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_A
LT_ON)); |
| 1143 assertEquals("hôˆbˆ", getTextBeforeCursor(9, 0)); | 1060 Assert.assertEquals("hôˆbˆ", mRule.getTextBeforeCursor(9, 0)); |
| 1144 waitAndVerifyUpdateSelection(index++, 5, 5, 4, 5); | 1061 mRule.waitAndVerifyUpdateSelection(index++, 5, 5, 4, 5); |
| 1145 | 1062 |
| 1146 // Backspace | 1063 // Backspace |
| 1147 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL
)); | 1064 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DEL)); |
| 1148 assertEquals("hôˆb", getTextBeforeCursor(9, 0)); | 1065 Assert.assertEquals("hôˆb", mRule.getTextBeforeCursor(9, 0)); |
| 1149 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL))
; | 1066 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_DEL)); |
| 1150 assertEquals("hôˆb", getTextBeforeCursor(9, 0)); | 1067 Assert.assertEquals("hôˆb", mRule.getTextBeforeCursor(9, 0)); |
| 1151 waitAndVerifyUpdateSelection(index++, 4, 4, -1, -1); | 1068 mRule.waitAndVerifyUpdateSelection(index++, 4, 4, -1, -1); |
| 1152 } | 1069 } |
| 1153 | 1070 |
| 1071 @Test |
| 1154 @SmallTest | 1072 @SmallTest |
| 1155 @Feature({"TextInput", "Main"}) | 1073 @Feature({"TextInput", "Main"}) |
| 1156 public void testSetComposingRegionOutOfBounds() throws Throwable { | 1074 public void testSetComposingRegionOutOfBounds() throws Throwable { |
| 1157 focusElementAndWaitForStateUpdate("textarea"); | 1075 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 1158 setComposingText("hello", 1); | 1076 mRule.setComposingText("hello", 1); |
| 1159 waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); | 1077 mRule.waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); |
| 1160 | 1078 |
| 1161 setComposingRegion(0, 0); | 1079 mRule.setComposingRegion(0, 0); |
| 1162 waitAndVerifyUpdateSelection(1, 5, 5, -1, -1); | 1080 mRule.waitAndVerifyUpdateSelection(1, 5, 5, -1, -1); |
| 1163 setComposingRegion(0, 9); | 1081 mRule.setComposingRegion(0, 9); |
| 1164 waitAndVerifyUpdateSelection(2, 5, 5, 0, 5); | 1082 mRule.waitAndVerifyUpdateSelection(2, 5, 5, 0, 5); |
| 1165 setComposingRegion(9, 1); | 1083 mRule.setComposingRegion(9, 1); |
| 1166 waitAndVerifyUpdateSelection(3, 5, 5, 1, 5); | 1084 mRule.waitAndVerifyUpdateSelection(3, 5, 5, 1, 5); |
| 1167 } | 1085 } |
| 1168 | 1086 |
| 1087 @Test |
| 1169 @SmallTest | 1088 @SmallTest |
| 1170 @Feature({"TextInput", "Main"}) | 1089 @Feature({"TextInput", "Main"}) |
| 1171 public void testEnterKey_AfterCommitText() throws Throwable { | 1090 public void testEnterKey_AfterCommitText() throws Throwable { |
| 1172 focusElementAndWaitForStateUpdate("textarea"); | 1091 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 1173 | 1092 |
| 1174 commitText("hello", 1); | 1093 mRule.commitText("hello", 1); |
| 1175 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 1094 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 1176 | 1095 |
| 1177 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENT
ER)); | 1096 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_ENTER)); |
| 1178 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER
)); | 1097 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_ENTER)); |
| 1179 waitAndVerifyUpdateSelection(1, 6, 6, -1, -1); | 1098 mRule.waitAndVerifyUpdateSelection(1, 6, 6, -1, -1); |
| 1180 assertTextsAroundCursor("hello\n", null, "\n"); | 1099 mRule.assertTextsAroundCursor("hello\n", null, "\n"); |
| 1181 | 1100 |
| 1182 commitText("world", 1); | 1101 mRule.commitText("world", 1); |
| 1183 waitAndVerifyUpdateSelection(2, 11, 11, -1, -1); | 1102 mRule.waitAndVerifyUpdateSelection(2, 11, 11, -1, -1); |
| 1184 assertTextsAroundCursor("hello\nworld", null, ""); | 1103 mRule.assertTextsAroundCursor("hello\nworld", null, ""); |
| 1185 } | 1104 } |
| 1186 | 1105 |
| 1106 @Test |
| 1187 @SmallTest | 1107 @SmallTest |
| 1188 @Feature({"TextInput", "Main"}) | 1108 @Feature({"TextInput", "Main"}) |
| 1189 public void testEnterKey_WhileComposingText() throws Throwable { | 1109 public void testEnterKey_WhileComposingText() throws Throwable { |
| 1190 focusElementAndWaitForStateUpdate("textarea"); | 1110 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 1191 | 1111 |
| 1192 setComposingText("hello", 1); | 1112 mRule.setComposingText("hello", 1); |
| 1193 waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); | 1113 mRule.waitAndVerifyUpdateSelection(0, 5, 5, 0, 5); |
| 1194 | 1114 |
| 1195 // IME app should call this, otherwise enter key should clear the curren
t composition. | 1115 // IME app should call this, otherwise enter key should clear the curren
t composition. |
| 1196 finishComposingText(); | 1116 mRule.finishComposingText(); |
| 1197 waitAndVerifyUpdateSelection(1, 5, 5, -1, -1); | 1117 mRule.waitAndVerifyUpdateSelection(1, 5, 5, -1, -1); |
| 1198 | 1118 |
| 1199 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENT
ER)); | 1119 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_ENTER)); |
| 1200 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER
)); | 1120 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_ENTER)); |
| 1201 | 1121 |
| 1202 // The second new line is not a user visible/editable one, it is a side-
effect of Blink | 1122 // The second new line is not a user visible/editable one, it is a side-
effect of Blink |
| 1203 // using <br> internally. This only happens when \n is at the end. | 1123 // using <br> internally. This only happens when \n is at the end. |
| 1204 waitAndVerifyUpdateSelection(2, 6, 6, -1, -1); | 1124 mRule.waitAndVerifyUpdateSelection(2, 6, 6, -1, -1); |
| 1205 | 1125 |
| 1206 commitText("world", 1); | 1126 mRule.commitText("world", 1); |
| 1207 waitAndVerifyUpdateSelection(3, 11, 11, -1, -1); | 1127 mRule.waitAndVerifyUpdateSelection(3, 11, 11, -1, -1); |
| 1208 assertTextsAroundCursor("hello\nworld", null, ""); | 1128 mRule.assertTextsAroundCursor("hello\nworld", null, ""); |
| 1209 } | 1129 } |
| 1210 | 1130 |
| 1131 @Test |
| 1211 @SmallTest | 1132 @SmallTest |
| 1212 @Feature({"TextInput", "Main"}) | 1133 @Feature({"TextInput", "Main"}) |
| 1213 public void testDpadKeyCodesWhileSwipingText() throws Throwable { | 1134 public void testDpadKeyCodesWhileSwipingText() throws Throwable { |
| 1214 focusElement("textarea"); | 1135 mRule.focusElement("textarea"); |
| 1215 | 1136 |
| 1216 // DPAD_CENTER should cause keyboard to appear | 1137 // DPAD_CENTER should cause keyboard to appear |
| 1217 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPA
D_CENTER)); | 1138 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DPAD_CENTER)); |
| 1218 | 1139 |
| 1219 // TODO(changwan): should really check this. | 1140 // TODO(changwan): should really check this. |
| 1220 } | 1141 } |
| 1221 | 1142 |
| 1143 @Test |
| 1222 @SmallTest | 1144 @SmallTest |
| 1223 @Feature({"TextInput", "Main"}) | 1145 @Feature({"TextInput", "Main"}) |
| 1224 public void testNavigateTextWithDpadKeyCodes() throws Throwable { | 1146 public void testNavigateTextWithDpadKeyCodes() throws Throwable { |
| 1225 focusElementAndWaitForStateUpdate("textarea"); | 1147 mRule.focusElementAndWaitForStateUpdate("textarea"); |
| 1226 | 1148 |
| 1227 commitText("hello", 1); | 1149 mRule.commitText("hello", 1); |
| 1228 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 1150 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 1229 | 1151 |
| 1230 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPA
D_LEFT)); | 1152 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DPAD_LEFT)); |
| 1231 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_
LEFT)); | 1153 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE
_DPAD_LEFT)); |
| 1232 | 1154 |
| 1233 assertTextsAroundCursor("hell", null, "o"); | 1155 mRule.assertTextsAroundCursor("hell", null, "o"); |
| 1234 } | 1156 } |
| 1235 | 1157 |
| 1158 @Test |
| 1236 @SmallTest | 1159 @SmallTest |
| 1237 @Feature({"TextInput"}) | 1160 @Feature({"TextInput"}) |
| 1238 public void testPastePopupShowAndHide() throws Throwable { | 1161 public void testPastePopupShowAndHide() throws Throwable { |
| 1239 commitText("hello", 1); | 1162 mRule.commitText("hello", 1); |
| 1240 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 1163 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 1241 | 1164 |
| 1242 selectAll(); | 1165 mRule.selectAll(); |
| 1243 waitAndVerifyUpdateSelection(1, 0, 5, -1, -1); | 1166 mRule.waitAndVerifyUpdateSelection(1, 0, 5, -1, -1); |
| 1244 assertTextsAroundCursor("", "hello", ""); | 1167 mRule.assertTextsAroundCursor("", "hello", ""); |
| 1245 | 1168 |
| 1246 cut(); | 1169 mRule.cut(); |
| 1247 waitAndVerifyUpdateSelection(2, 0, 0, -1, -1); | 1170 mRule.waitAndVerifyUpdateSelection(2, 0, 0, -1, -1); |
| 1248 assertTextsAroundCursor("", null, ""); | 1171 mRule.assertTextsAroundCursor("", null, ""); |
| 1249 | 1172 |
| 1250 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 1173 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 1251 CriteriaHelper.pollUiThread(new Criteria() { | 1174 CriteriaHelper.pollUiThread(new Criteria() { |
| 1252 @Override | 1175 @Override |
| 1253 public boolean isSatisfied() { | 1176 public boolean isSatisfied() { |
| 1254 return mSelectionPopupController.isPastePopupShowing() | 1177 return mRule.getSelectionPopupController().isPastePopupShowing() |
| 1255 && mSelectionPopupController.isInsertion(); | 1178 && mRule.getSelectionPopupController().isInsertion(); |
| 1256 } | 1179 } |
| 1257 }); | 1180 }); |
| 1258 | 1181 |
| 1259 setComposingText("h", 1); | 1182 mRule.setComposingText("h", 1); |
| 1260 CriteriaHelper.pollUiThread(new Criteria() { | 1183 CriteriaHelper.pollUiThread(new Criteria() { |
| 1261 @Override | 1184 @Override |
| 1262 public boolean isSatisfied() { | 1185 public boolean isSatisfied() { |
| 1263 return !mSelectionPopupController.isPastePopupShowing(); | 1186 return !mRule.getSelectionPopupController().isPastePopupShowing(
); |
| 1264 } | 1187 } |
| 1265 }); | 1188 }); |
| 1266 assertFalse(mSelectionPopupController.isInsertion()); | 1189 Assert.assertFalse(mRule.getSelectionPopupController().isInsertion()); |
| 1267 } | 1190 } |
| 1268 | 1191 |
| 1192 @Test |
| 1269 @SmallTest | 1193 @SmallTest |
| 1270 @Feature({"TextInput"}) | 1194 @Feature({"TextInput"}) |
| 1271 public void testSelectionClearedOnKeyEvent() throws Throwable { | 1195 public void testSelectionClearedOnKeyEvent() throws Throwable { |
| 1272 commitText("Sample Text", 1); | 1196 mRule.commitText("Sample Text", 1); |
| 1273 waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); | 1197 mRule.waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); |
| 1274 | 1198 |
| 1275 DOMUtils.longPressNode(mContentViewCore, "input_text"); | 1199 DOMUtils.longPressNode(mRule.getContentViewCore(), "input_text"); |
| 1276 assertWaitForSelectActionBarStatus(true); | 1200 mRule.assertWaitForSelectActionBarStatus(true); |
| 1277 | 1201 |
| 1278 setComposingText("h", 1); | 1202 mRule.setComposingText("h", 1); |
| 1279 assertWaitForSelectActionBarStatus(false); | 1203 mRule.assertWaitForSelectActionBarStatus(false); |
| 1280 assertFalse(mSelectionPopupController.hasSelection()); | 1204 Assert.assertFalse(mRule.getSelectionPopupController().hasSelection()); |
| 1281 } | 1205 } |
| 1282 | 1206 |
| 1207 @Test |
| 1283 @SmallTest | 1208 @SmallTest |
| 1284 @Feature({"TextInput"}) | 1209 @Feature({"TextInput"}) |
| 1285 public void testTextHandlesPreservedWithDpadNavigation() throws Throwable { | 1210 public void testTextHandlesPreservedWithDpadNavigation() throws Throwable { |
| 1286 DOMUtils.longPressNode(mContentViewCore, "plain_text"); | 1211 DOMUtils.longPressNode(mRule.getContentViewCore(), "plain_text"); |
| 1287 assertWaitForSelectActionBarStatus(true); | 1212 mRule.assertWaitForSelectActionBarStatus(true); |
| 1288 assertTrue(mSelectionPopupController.hasSelection()); | 1213 Assert.assertTrue(mRule.getSelectionPopupController().hasSelection()); |
| 1289 | 1214 |
| 1290 dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPA
D_DOWN)); | 1215 mRule.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCO
DE_DPAD_DOWN)); |
| 1291 assertWaitForSelectActionBarStatus(true); | 1216 mRule.assertWaitForSelectActionBarStatus(true); |
| 1292 assertTrue(mSelectionPopupController.hasSelection()); | 1217 Assert.assertTrue(mRule.getSelectionPopupController().hasSelection()); |
| 1293 } | 1218 } |
| 1294 | 1219 |
| 1220 @Test |
| 1295 @MediumTest | 1221 @MediumTest |
| 1296 @Feature({"TextInput"}) | 1222 @Feature({"TextInput"}) |
| 1297 public void testRestartInputWhileComposingText() throws Throwable { | 1223 public void testRestartInputWhileComposingText() throws Throwable { |
| 1298 setComposingText("abc", 1); | 1224 mRule.setComposingText("abc", 1); |
| 1299 waitAndVerifyUpdateSelection(0, 3, 3, 0, 3); | 1225 mRule.waitAndVerifyUpdateSelection(0, 3, 3, 0, 3); |
| 1300 restartInput(); | 1226 mRule.restartInput(); |
| 1301 // We don't do anything when input gets restarted. But we depend on Andr
oid's | 1227 // We don't do anything when input gets restarted. But we depend on Andr
oid's |
| 1302 // InputMethodManager and/or input methods to call finishComposingText()
in setting | 1228 // InputMethodManager and/or input methods to call mRule.finishComposing
Text() in setting |
| 1303 // current input connection as active or finishing the current input con
nection. | 1229 // current input connection as active or finishing the current input con
nection. |
| 1304 Thread.sleep(1000); | 1230 Thread.sleep(1000); |
| 1305 assertEquals(1, mInputMethodManagerWrapper.getUpdateSelectionList().size
()); | 1231 Assert.assertEquals( |
| 1306 } | 1232 1, mRule.getInputMethodManagerWrapper().getUpdateSelectionList()
.size()); |
| 1307 | 1233 } |
| 1234 |
| 1235 @Test |
| 1308 @MediumTest | 1236 @MediumTest |
| 1309 @Feature({"TextInput"}) | 1237 @Feature({"TextInput"}) |
| 1310 public void testRestartInputKeepsTextAndCursor() throws Exception { | 1238 public void testRestartInputKeepsTextAndCursor() throws Exception { |
| 1311 commitText("ab", 2); | 1239 mRule.commitText("ab", 2); |
| 1312 restartInput(); | 1240 mRule.restartInput(); |
| 1313 assertEquals("ab", getTextBeforeCursor(10, 0)); | 1241 Assert.assertEquals("ab", mRule.getTextBeforeCursor(10, 0)); |
| 1314 } | 1242 } |
| 1315 | 1243 |
| 1244 @Test |
| 1316 @MediumTest | 1245 @MediumTest |
| 1317 @Feature({"TextInput"}) | 1246 @Feature({"TextInput"}) |
| 1318 public void testContentEditableEvents_ComposingText() throws Throwable { | 1247 public void testContentEditableEvents_ComposingText() throws Throwable { |
| 1319 focusElementAndWaitForStateUpdate("contenteditable_event"); | 1248 mRule.focusElementAndWaitForStateUpdate("contenteditable_event"); |
| 1320 waitForEventLogs("selectionchange"); | 1249 mRule.waitForEventLogs("selectionchange"); |
| 1321 clearEventLogs(); | 1250 mRule.clearEventLogs(); |
| 1322 | 1251 |
| 1323 setComposingText("a", 1); | 1252 mRule.setComposingText("a", 1); |
| 1324 waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); | 1253 mRule.waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); |
| 1325 // TODO(changwan): reduce the number of selection changes. | 1254 // TODO(changwan): reduce the number of selection changes. |
| 1326 waitForEventLogs("keydown(229),compositionstart(),compositionupdate(a),i
nput,keyup(229)," | 1255 mRule.waitForEventLogs( |
| 1256 "keydown(229),compositionstart(),compositionupdate(a),input,keyu
p(229)," |
| 1327 + "selectionchange,selectionchange"); | 1257 + "selectionchange,selectionchange"); |
| 1328 clearEventLogs(); | 1258 mRule.clearEventLogs(); |
| 1329 | 1259 |
| 1330 finishComposingText(); | 1260 mRule.finishComposingText(); |
| 1331 waitAndVerifyUpdateSelection(1, 1, 1, -1, -1); | 1261 mRule.waitAndVerifyUpdateSelection(1, 1, 1, -1, -1); |
| 1332 waitForEventLogs( | 1262 mRule.waitForEventLogs("compositionend(a)"); |
| 1333 "compositionend(a)"); | 1263 } |
| 1334 } | 1264 |
| 1335 | 1265 @Test |
| 1336 @MediumTest | 1266 @MediumTest |
| 1337 @Feature({"TextInput"}) | 1267 @Feature({"TextInput"}) |
| 1338 public void testInputTextEvents_ComposingText() throws Throwable { | 1268 public void testInputTextEvents_ComposingText() throws Throwable { |
| 1339 setComposingText("a", 1); | 1269 mRule.setComposingText("a", 1); |
| 1340 waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); | 1270 mRule.waitAndVerifyUpdateSelection(0, 1, 1, 0, 1); |
| 1341 // TODO(changwan): reduce the number of selection changes. | 1271 // TODO(changwan): reduce the number of selection changes. |
| 1342 waitForEventLogs("keydown(229),compositionstart(),compositionupdate(a)," | 1272 mRule.waitForEventLogs("keydown(229),compositionstart(),compositionupdat
e(a)," |
| 1343 + "input,keyup(229),selectionchange,selectionchange"); | 1273 + "input,keyup(229),selectionchange,selectionchange"); |
| 1344 clearEventLogs(); | 1274 mRule.clearEventLogs(); |
| 1345 | 1275 |
| 1346 finishComposingText(); | 1276 mRule.finishComposingText(); |
| 1347 waitAndVerifyUpdateSelection(1, 1, 1, -1, -1); | 1277 mRule.waitAndVerifyUpdateSelection(1, 1, 1, -1, -1); |
| 1348 waitForEventLogs("compositionend(a)"); | 1278 mRule.waitForEventLogs("compositionend(a)"); |
| 1349 } | 1279 } |
| 1350 | 1280 |
| 1281 @Test |
| 1351 @MediumTest | 1282 @MediumTest |
| 1352 @Feature({"TextInput"}) | 1283 @Feature({"TextInput"}) |
| 1353 public void testContentEditableEvents_CommitText() throws Throwable { | 1284 public void testContentEditableEvents_CommitText() throws Throwable { |
| 1354 focusElementAndWaitForStateUpdate("contenteditable_event"); | 1285 mRule.focusElementAndWaitForStateUpdate("contenteditable_event"); |
| 1355 waitForEventLogs("selectionchange"); | 1286 mRule.waitForEventLogs("selectionchange"); |
| 1356 clearEventLogs(); | 1287 mRule.clearEventLogs(); |
| 1357 | 1288 |
| 1358 commitText("a", 1); | 1289 mRule.commitText("a", 1); |
| 1359 waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); | 1290 mRule.waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); |
| 1360 | 1291 |
| 1361 waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); | 1292 mRule.waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); |
| 1362 } | 1293 } |
| 1363 | 1294 |
| 1295 @Test |
| 1364 @MediumTest | 1296 @MediumTest |
| 1365 @Feature({"TextInput"}) | 1297 @Feature({"TextInput"}) |
| 1366 public void testInputTextEvents_CommitText() throws Throwable { | 1298 public void testInputTextEvents_CommitText() throws Throwable { |
| 1367 commitText("a", 1); | 1299 mRule.commitText("a", 1); |
| 1368 waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); | 1300 mRule.waitAndVerifyUpdateSelection(0, 1, 1, -1, -1); |
| 1369 | 1301 |
| 1370 waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); | 1302 mRule.waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); |
| 1371 } | 1303 } |
| 1372 | 1304 |
| 1305 @Test |
| 1373 @MediumTest | 1306 @MediumTest |
| 1374 @Feature({"TextInput"}) | 1307 @Feature({"TextInput"}) |
| 1375 public void testContentEditableEvents_DeleteSurroundingText() throws Throwab
le { | 1308 public void testContentEditableEvents_DeleteSurroundingText() throws Throwab
le { |
| 1376 focusElementAndWaitForStateUpdate("contenteditable_event"); | 1309 mRule.focusElementAndWaitForStateUpdate("contenteditable_event"); |
| 1377 waitForEventLogs("selectionchange"); | 1310 mRule.waitForEventLogs("selectionchange"); |
| 1378 clearEventLogs(); | 1311 mRule.clearEventLogs(); |
| 1379 | 1312 |
| 1380 commitText("hello", 1); | 1313 mRule.commitText("hello", 1); |
| 1381 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 1314 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 1382 waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); | 1315 mRule.waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); |
| 1383 clearEventLogs(); | 1316 mRule.clearEventLogs(); |
| 1384 | 1317 |
| 1385 setSelection(2, 2); | 1318 mRule.setSelection(2, 2); |
| 1386 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 1319 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 1387 waitForEventLogs("selectionchange"); | 1320 mRule.waitForEventLogs("selectionchange"); |
| 1388 clearEventLogs(); | 1321 mRule.clearEventLogs(); |
| 1389 | 1322 |
| 1390 deleteSurroundingText(1, 1); | 1323 mRule.deleteSurroundingText(1, 1); |
| 1391 waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); | 1324 mRule.waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); |
| 1325 |
| 1392 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. | 1326 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. |
| 1393 waitForEventLogs("keydown(229),input,input,keyup(229),selectionchange,se
lectionchange"); | 1327 mRule.waitForEventLogs( |
| 1394 } | 1328 "keydown(229),input,input,keyup(229),selectionchange,selectionch
ange"); |
| 1395 | 1329 } |
| 1330 |
| 1331 @Test |
| 1396 @MediumTest | 1332 @MediumTest |
| 1397 @Feature({"TextInput"}) | 1333 @Feature({"TextInput"}) |
| 1398 public void testInputTextEvents_DeleteSurroundingText() throws Throwable { | 1334 public void testInputTextEvents_DeleteSurroundingText() throws Throwable { |
| 1399 commitText("hello", 1); | 1335 mRule.commitText("hello", 1); |
| 1400 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 1336 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 1401 waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); | 1337 mRule.waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); |
| 1402 clearEventLogs(); | 1338 mRule.clearEventLogs(); |
| 1403 | 1339 |
| 1404 setSelection(2, 2); | 1340 mRule.setSelection(2, 2); |
| 1405 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 1341 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 1406 waitForEventLogs("selectionchange"); | 1342 mRule.waitForEventLogs("selectionchange"); |
| 1407 clearEventLogs(); | 1343 mRule.clearEventLogs(); |
| 1408 | 1344 |
| 1409 deleteSurroundingText(1, 1); | 1345 mRule.deleteSurroundingText(1, 1); |
| 1410 waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); | 1346 mRule.waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); |
| 1411 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. | 1347 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. |
| 1412 waitForEventLogs("keydown(229),input,input,keyup(229),selectionchange,se
lectionchange"); | 1348 mRule.waitForEventLogs( |
| 1413 } | 1349 "keydown(229),input,input,keyup(229),selectionchange,selectionch
ange"); |
| 1414 | 1350 } |
| 1351 |
| 1352 @Test |
| 1415 @MediumTest | 1353 @MediumTest |
| 1416 @Feature({"TextInput"}) | 1354 @Feature({"TextInput"}) |
| 1417 public void testContentEditableEvents_DeleteSurroundingTextInCodePoints() th
rows Throwable { | 1355 public void testContentEditableEvents_DeleteSurroundingTextInCodePoints() th
rows Throwable { |
| 1418 focusElementAndWaitForStateUpdate("contenteditable_event"); | 1356 mRule.focusElementAndWaitForStateUpdate("contenteditable_event"); |
| 1419 waitForEventLogs("selectionchange"); | 1357 mRule.waitForEventLogs("selectionchange"); |
| 1420 clearEventLogs(); | 1358 mRule.clearEventLogs(); |
| 1421 | 1359 |
| 1422 commitText("hello", 1); | 1360 mRule.commitText("hello", 1); |
| 1423 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 1361 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 1424 waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); | 1362 mRule.waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); |
| 1425 clearEventLogs(); | 1363 mRule.clearEventLogs(); |
| 1426 | 1364 |
| 1427 setSelection(2, 2); | 1365 mRule.setSelection(2, 2); |
| 1428 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 1366 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 1429 waitForEventLogs("selectionchange"); | 1367 mRule.waitForEventLogs("selectionchange"); |
| 1430 clearEventLogs(); | 1368 mRule.clearEventLogs(); |
| 1431 | 1369 |
| 1432 deleteSurroundingTextInCodePoints(1, 1); | 1370 mRule.deleteSurroundingTextInCodePoints(1, 1); |
| 1433 waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); | 1371 mRule.waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); |
| 1434 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. | 1372 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. |
| 1435 waitForEventLogs("keydown(229),input,input,keyup(229),selectionchange,se
lectionchange"); | 1373 mRule.waitForEventLogs( |
| 1436 } | 1374 "keydown(229),input,input,keyup(229),selectionchange,selectionch
ange"); |
| 1437 | 1375 } |
| 1376 |
| 1377 @Test |
| 1438 @MediumTest | 1378 @MediumTest |
| 1439 @Feature({"TextInput"}) | 1379 @Feature({"TextInput"}) |
| 1440 public void testInputTextEvents_DeleteSurroundingTextInCodePoints() throws T
hrowable { | 1380 public void testInputTextEvents_DeleteSurroundingTextInCodePoints() throws T
hrowable { |
| 1441 commitText("hello", 1); | 1381 mRule.commitText("hello", 1); |
| 1442 waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); | 1382 mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); |
| 1443 waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); | 1383 mRule.waitForEventLogs("keydown(229),input,keyup(229),selectionchange"); |
| 1444 clearEventLogs(); | 1384 mRule.clearEventLogs(); |
| 1445 | 1385 |
| 1446 setSelection(2, 2); | 1386 mRule.setSelection(2, 2); |
| 1447 waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); | 1387 mRule.waitAndVerifyUpdateSelection(1, 2, 2, -1, -1); |
| 1448 waitForEventLogs("selectionchange"); | 1388 mRule.waitForEventLogs("selectionchange"); |
| 1449 clearEventLogs(); | 1389 mRule.clearEventLogs(); |
| 1450 | 1390 |
| 1451 deleteSurroundingTextInCodePoints(1, 1); | 1391 mRule.deleteSurroundingTextInCodePoints(1, 1); |
| 1452 waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); | 1392 mRule.waitAndVerifyUpdateSelection(2, 1, 1, -1, -1); |
| 1453 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. | 1393 // TODO(yabinh): It should only fire 1 input and 1 selectionchange event
s. |
| 1454 waitForEventLogs("keydown(229),input,input,keyup(229),selectionchange,se
lectionchange"); | 1394 mRule.waitForEventLogs( |
| 1455 } | 1395 "keydown(229),input,input,keyup(229),selectionchange,selectionch
ange"); |
| 1456 | 1396 } |
| 1397 |
| 1398 @Test |
| 1457 @MediumTest | 1399 @MediumTest |
| 1458 @Feature({"TextInput"}) | 1400 @Feature({"TextInput"}) |
| 1459 public void testGetCursorCapsMode() throws Throwable { | 1401 public void testGetCursorCapsMode() throws Throwable { |
| 1460 focusElementAndWaitForStateUpdate("contenteditable_event"); | 1402 mRule.focusElementAndWaitForStateUpdate("contenteditable_event"); |
| 1461 commitText("Hello World", 1); | 1403 mRule.commitText("Hello World", 1); |
| 1462 waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); | 1404 mRule.waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); |
| 1463 assertEquals(0, | 1405 Assert.assertEquals(0, mRule.getCursorCapsMode(InputType.TYPE_TEXT_FLAG_
CAP_WORDS)); |
| 1464 getCursorCapsMode(InputType.TYPE_TEXT_FLAG_CAP_WORDS)); | 1406 mRule.setSelection(6, 6); |
| 1465 setSelection(6, 6); | 1407 mRule.waitAndVerifyUpdateSelection(1, 6, 6, -1, -1); |
| 1466 waitAndVerifyUpdateSelection(1, 6, 6, -1, -1); | 1408 Assert.assertEquals(InputType.TYPE_TEXT_FLAG_CAP_WORDS, |
| 1467 assertEquals(InputType.TYPE_TEXT_FLAG_CAP_WORDS, | 1409 mRule.getCursorCapsMode(InputType.TYPE_TEXT_FLAG_CAP_WORDS)); |
| 1468 getCursorCapsMode(InputType.TYPE_TEXT_FLAG_CAP_WORDS)); | 1410 mRule.commitText("\n", 1); |
| 1469 commitText("\n", 1); | 1411 Assert.assertEquals(InputType.TYPE_TEXT_FLAG_CAP_WORDS, |
| 1470 assertEquals(InputType.TYPE_TEXT_FLAG_CAP_WORDS, | 1412 mRule.getCursorCapsMode(InputType.TYPE_TEXT_FLAG_CAP_WORDS)); |
| 1471 getCursorCapsMode(InputType.TYPE_TEXT_FLAG_CAP_WORDS)); | |
| 1472 } | |
| 1473 | |
| 1474 private void clearEventLogs() throws Exception { | |
| 1475 final String code = "clearEventLogs()"; | |
| 1476 JavaScriptUtils.executeJavaScriptAndWaitForResult( | |
| 1477 getContentViewCore().getWebContents(), code); | |
| 1478 } | |
| 1479 | |
| 1480 private void waitForEventLogs(String expectedLogs) throws Exception { | |
| 1481 final String code = "getEventLogs()"; | |
| 1482 final String sanitizedExpectedLogs = "\"" + expectedLogs + "\""; | |
| 1483 assertEquals(sanitizedExpectedLogs, JavaScriptUtils.executeJavaScriptAnd
WaitForResult( | |
| 1484 getContentViewCore().getWebC
ontents(), code)); | |
| 1485 } | 1413 } |
| 1486 | 1414 |
| 1487 // https://crbug.com/604675 | 1415 // https://crbug.com/604675 |
| 1416 @Test |
| 1488 @MediumTest | 1417 @MediumTest |
| 1489 @Feature({"TextInput"}) | 1418 @Feature({"TextInput"}) |
| 1490 public void testAlertInKeyUpListenerDoesNotCrash() throws Exception { | 1419 public void testAlertInKeyUpListenerDoesNotCrash() throws Exception { |
| 1491 // Call 'alert()' when 'keyup' event occurs. Since we are in contentshel
l, | 1420 // Call 'alert()' when 'keyup' event occurs. Since we are in contentshel
l, |
| 1492 // this does not actually pops up the alert window. | 1421 // this does not actually pops up the alert window. |
| 1493 String code = "(function() { " | 1422 String code = "(function() { " |
| 1494 + "var editor = document.getElementById('input_text');" | 1423 + "var editor = document.getElementById('input_text');" |
| 1495 + "editor.addEventListener('keyup', function(e) { alert('keyup')
});" | 1424 + "editor.addEventListener('keyup', function(e) { alert('keyup')
});" |
| 1496 + "})();"; | 1425 + "})();"; |
| 1497 JavaScriptUtils.executeJavaScriptAndWaitForResult( | 1426 JavaScriptUtils.executeJavaScriptAndWaitForResult( |
| 1498 getContentViewCore().getWebContents(), code); | 1427 mRule.getContentViewCore().getWebContents(), code); |
| 1499 setComposingText("ab", 1); | 1428 mRule.setComposingText("ab", 1); |
| 1500 finishComposingText(); | 1429 mRule.finishComposingText(); |
| 1501 assertEquals("ab", getTextBeforeCursor(10, 0)); | 1430 Assert.assertEquals("ab", mRule.getTextBeforeCursor(10, 0)); |
| 1502 } | 1431 } |
| 1503 | 1432 |
| 1504 // https://crbug.com/616334 | 1433 // https://crbug.com/616334 |
| 1434 @Test |
| 1505 @SmallTest | 1435 @SmallTest |
| 1506 @Feature({"TextInput"}) | 1436 @Feature({"TextInput"}) |
| 1507 public void testCastToBaseInputConnection() throws Exception { | 1437 public void testCastToBaseInputConnection() throws Exception { |
| 1508 commitText("a", 1); | 1438 mRule.commitText("a", 1); |
| 1509 final BaseInputConnection baseInputConnection = (BaseInputConnection) mC
onnection; | 1439 final BaseInputConnection baseInputConnection = (BaseInputConnection) mR
ule.getConnection(); |
| 1510 assertEquals("a", runBlockingOnImeThread(new Callable<CharSequence>() { | 1440 Assert.assertEquals("a", mRule.runBlockingOnImeThread(new Callable<CharS
equence>() { |
| 1511 @Override | 1441 @Override |
| 1512 public CharSequence call() { | 1442 public CharSequence call() { |
| 1513 return baseInputConnection.getTextBeforeCursor(10, 0); | 1443 return baseInputConnection.getTextBeforeCursor(10, 0); |
| 1514 } | 1444 } |
| 1515 })); | 1445 })); |
| 1516 } | 1446 } |
| 1517 | 1447 |
| 1518 // Tests that the method call order is kept. | 1448 // Tests that the method call order is kept. |
| 1519 // See crbug.com/601707 for details. | 1449 // See crbug.com/601707 for details. |
| 1450 @Test |
| 1520 @MediumTest | 1451 @MediumTest |
| 1521 @Feature({"TextInput"}) | 1452 @Feature({"TextInput"}) |
| 1522 public void testSetSelectionCommitTextOrder() throws Exception { | 1453 public void testSetSelectionCommitTextOrder() throws Exception { |
| 1523 final ChromiumBaseInputConnection connection = mConnection; | 1454 final ChromiumBaseInputConnection connection = mRule.getConnection(); |
| 1524 runBlockingOnImeThread(new Callable<Void>() { | 1455 mRule.runBlockingOnImeThread(new Callable<Void>() { |
| 1525 @Override | 1456 @Override |
| 1526 public Void call() { | 1457 public Void call() { |
| 1527 connection.beginBatchEdit(); | 1458 connection.beginBatchEdit(); |
| 1528 connection.commitText("hello world", 1); | 1459 connection.commitText("hello world", 1); |
| 1529 connection.setSelection(6, 6); | 1460 connection.setSelection(6, 6); |
| 1530 connection.deleteSurroundingText(0, 5); | 1461 connection.deleteSurroundingText(0, 5); |
| 1531 connection.commitText("'", 1); | 1462 connection.commitText("'", 1); |
| 1532 connection.commitText("world", 1); | 1463 connection.commitText("world", 1); |
| 1533 connection.setSelection(7, 7); | 1464 connection.setSelection(7, 7); |
| 1534 connection.setComposingText("", 1); | 1465 connection.setComposingText("", 1); |
| 1535 connection.endBatchEdit(); | 1466 connection.endBatchEdit(); |
| 1536 return null; | 1467 return null; |
| 1537 } | 1468 } |
| 1538 }); | 1469 }); |
| 1539 waitAndVerifyUpdateSelection(0, 7, 7, -1, -1); | 1470 mRule.waitAndVerifyUpdateSelection(0, 7, 7, -1, -1); |
| 1540 } | 1471 } |
| 1541 | 1472 |
| 1542 // crbug.com/643477 | 1473 // crbug.com/643477 |
| 1474 @Test |
| 1543 @MediumTest | 1475 @MediumTest |
| 1544 @Feature({"TextInput"}) | 1476 @Feature({"TextInput"}) |
| 1545 public void testUiThreadAccess() throws Exception { | 1477 public void testUiThreadAccess() throws Exception { |
| 1546 final ChromiumBaseInputConnection connection = mConnection; | 1478 final ChromiumBaseInputConnection connection = mRule.getConnection(); |
| 1547 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 1479 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 1548 @Override | 1480 @Override |
| 1549 public void run() { | 1481 public void run() { |
| 1550 // We allow UI thread access for most functions, except for | 1482 // We allow UI thread access for most functions, except for |
| 1551 // beginBatchEdit(), endBatchEdit(), and get* methods(). | 1483 // beginBatchEdit(), endBatchEdit(), and get* methods(). |
| 1552 assertTrue(connection.commitText("a", 1)); | 1484 Assert.assertTrue(connection.commitText("a", 1)); |
| 1553 assertTrue(connection.setComposingText("b", 1)); | 1485 Assert.assertTrue(connection.setComposingText("b", 1)); |
| 1554 assertTrue(connection.setComposingText("bc", 1)); | 1486 Assert.assertTrue(connection.setComposingText("bc", 1)); |
| 1555 assertTrue(connection.finishComposingText()); | 1487 Assert.assertTrue(connection.finishComposingText()); |
| 1556 } | 1488 } |
| 1557 }); | 1489 }); |
| 1558 assertEquals("abc", runBlockingOnImeThread(new Callable<CharSequence>()
{ | 1490 Assert.assertEquals("abc", mRule.runBlockingOnImeThread(new Callable<Cha
rSequence>() { |
| 1559 @Override | 1491 @Override |
| 1560 public CharSequence call() throws Exception { | 1492 public CharSequence call() throws Exception { |
| 1561 return connection.getTextBeforeCursor(5, 0); | 1493 return connection.getTextBeforeCursor(5, 0); |
| 1562 } | 1494 } |
| 1563 })); | 1495 })); |
| 1564 } | 1496 } |
| 1565 | 1497 |
| 1566 private void performGo(TestCallbackHelperContainer testCallbackHelperContain
er) | |
| 1567 throws Throwable { | |
| 1568 final InputConnection inputConnection = mConnection; | |
| 1569 final Callable<Void> callable = new Callable<Void>() { | |
| 1570 @Override | |
| 1571 public Void call() throws Exception { | |
| 1572 inputConnection.performEditorAction(EditorInfo.IME_ACTION_GO); | |
| 1573 return null; | |
| 1574 } | |
| 1575 }; | |
| 1576 | |
| 1577 handleBlockingCallbackAction( | |
| 1578 testCallbackHelperContainer.getOnPageFinishedHelper(), | |
| 1579 new Runnable() { | |
| 1580 @Override | |
| 1581 public void run() { | |
| 1582 try { | |
| 1583 runBlockingOnImeThread(callable); | |
| 1584 } catch (Exception e) { | |
| 1585 e.printStackTrace(); | |
| 1586 fail(); | |
| 1587 } | |
| 1588 } | |
| 1589 }); | |
| 1590 } | |
| 1591 | |
| 1592 private void assertWaitForKeyboardStatus(final boolean show) { | |
| 1593 CriteriaHelper.pollUiThread(new Criteria() { | |
| 1594 @Override | |
| 1595 public boolean isSatisfied() { | |
| 1596 // We do not check the other way around: in some cases we need t
o keep | |
| 1597 // input connection even when the last known status is 'hidden'. | |
| 1598 if (show && getInputConnection() == null) { | |
| 1599 updateFailureReason("input connection should not be null."); | |
| 1600 return false; | |
| 1601 } | |
| 1602 updateFailureReason("expected show: " + show); | |
| 1603 return show == mInputMethodManagerWrapper.isShowWithoutHideOutst
anding(); | |
| 1604 } | |
| 1605 }); | |
| 1606 } | |
| 1607 | |
| 1608 private void assertWaitForSelectActionBarStatus(final boolean show) { | |
| 1609 CriteriaHelper.pollUiThread(Criteria.equals(show, new Callable<Boolean>(
) { | |
| 1610 @Override | |
| 1611 public Boolean call() { | |
| 1612 return mContentViewCore.isSelectActionBarShowing(); | |
| 1613 } | |
| 1614 })); | |
| 1615 } | |
| 1616 | |
| 1617 private void waitAndVerifyUpdateSelection(final int index, final int selecti
onStart, | |
| 1618 final int selectionEnd, final int compositionStart, final int compos
itionEnd) { | |
| 1619 final List<Pair<Range, Range>> states = mInputMethodManagerWrapper.getUp
dateSelectionList(); | |
| 1620 CriteriaHelper.pollUiThread(new Criteria() { | |
| 1621 @Override | |
| 1622 public boolean isSatisfied() { | |
| 1623 return states.size() > index; | |
| 1624 } | |
| 1625 }); | |
| 1626 Pair<Range, Range> selection = states.get(index); | |
| 1627 assertEquals(selectionStart, selection.first.start()); | |
| 1628 assertEquals(selectionEnd, selection.first.end()); | |
| 1629 assertEquals(compositionStart, selection.second.start()); | |
| 1630 assertEquals(compositionEnd, selection.second.end()); | |
| 1631 } | |
| 1632 | |
| 1633 private void resetUpdateSelectionList() { | |
| 1634 mInputMethodManagerWrapper.getUpdateSelectionList().clear(); | |
| 1635 } | |
| 1636 | |
| 1637 private void assertClipboardContents(final Activity activity, final String e
xpectedContents) { | |
| 1638 CriteriaHelper.pollUiThread(new Criteria() { | |
| 1639 @Override | |
| 1640 public boolean isSatisfied() { | |
| 1641 ClipboardManager clipboardManager = | |
| 1642 (ClipboardManager) activity.getSystemService(Context.CLI
PBOARD_SERVICE); | |
| 1643 ClipData clip = clipboardManager.getPrimaryClip(); | |
| 1644 return clip != null && clip.getItemCount() == 1 | |
| 1645 && TextUtils.equals(clip.getItemAt(0).getText(), expecte
dContents); | |
| 1646 } | |
| 1647 }); | |
| 1648 } | |
| 1649 | |
| 1650 private ImeAdapter getImeAdapter() { | |
| 1651 return mContentViewCore.getImeAdapterForTest(); | |
| 1652 } | |
| 1653 | |
| 1654 private ChromiumBaseInputConnection getInputConnection() { | |
| 1655 try { | |
| 1656 return ThreadUtils.runOnUiThreadBlocking(new Callable<ChromiumBaseIn
putConnection>() { | |
| 1657 @Override | |
| 1658 public ChromiumBaseInputConnection call() { | |
| 1659 return mContentViewCore.getImeAdapterForTest().getInputConne
ctionForTest(); | |
| 1660 } | |
| 1661 }); | |
| 1662 } catch (ExecutionException e) { | |
| 1663 e.printStackTrace(); | |
| 1664 fail(); | |
| 1665 return null; | |
| 1666 } | |
| 1667 } | |
| 1668 | |
| 1669 private void restartInput() { | |
| 1670 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1671 @Override | |
| 1672 public void run() { | |
| 1673 mImeAdapter.restartInput(); | |
| 1674 } | |
| 1675 }); | |
| 1676 } | |
| 1677 | |
| 1678 // After calling this method, we should call assertClipboardContents() to wa
it for the clipboard | |
| 1679 // to get updated. See cubug.com/621046 | |
| 1680 private void copy() { | |
| 1681 final WebContents webContents = mWebContents; | |
| 1682 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1683 @Override | |
| 1684 public void run() { | |
| 1685 webContents.copy(); | |
| 1686 } | |
| 1687 }); | |
| 1688 } | |
| 1689 | |
| 1690 private void cut() { | |
| 1691 final WebContents webContents = mWebContents; | |
| 1692 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1693 @Override | |
| 1694 public void run() { | |
| 1695 webContents.cut(); | |
| 1696 } | |
| 1697 }); | |
| 1698 } | |
| 1699 | |
| 1700 private void setClip(final CharSequence text) { | |
| 1701 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1702 @Override | |
| 1703 public void run() { | |
| 1704 final ClipboardManager clipboardManager = | |
| 1705 (ClipboardManager) getActivity().getSystemService( | |
| 1706 Context.CLIPBOARD_SERVICE); | |
| 1707 clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text
)); | |
| 1708 } | |
| 1709 }); | |
| 1710 } | |
| 1711 | |
| 1712 private void paste() { | |
| 1713 final WebContents webContents = mWebContents; | |
| 1714 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1715 @Override | |
| 1716 public void run() { | |
| 1717 webContents.paste(); | |
| 1718 } | |
| 1719 }); | |
| 1720 } | |
| 1721 | |
| 1722 private void selectAll() { | |
| 1723 final WebContents webContents = mWebContents; | |
| 1724 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1725 @Override | |
| 1726 public void run() { | |
| 1727 webContents.selectAll(); | |
| 1728 } | |
| 1729 }); | |
| 1730 } | |
| 1731 | |
| 1732 private void collapseSelection() { | |
| 1733 final WebContents webContents = mWebContents; | |
| 1734 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1735 @Override | |
| 1736 public void run() { | |
| 1737 webContents.collapseSelection(); | |
| 1738 } | |
| 1739 }); | |
| 1740 } | |
| 1741 | |
| 1742 /** | |
| 1743 * Run the {@Callable} on IME thread (or UI thread if not applicable). | |
| 1744 * @param c The callable | |
| 1745 * @return The result from running the callable. | |
| 1746 */ | |
| 1747 protected <T> T runBlockingOnImeThread(Callable<T> c) throws Exception { | |
| 1748 return ImeTestUtils.runBlockingOnHandler(mConnectionFactory.getHandler()
, c); | |
| 1749 } | |
| 1750 | |
| 1751 private boolean beginBatchEdit() throws Exception { | |
| 1752 final ChromiumBaseInputConnection connection = mConnection; | |
| 1753 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1754 @Override | |
| 1755 public Boolean call() { | |
| 1756 return connection.beginBatchEdit(); | |
| 1757 } | |
| 1758 }); | |
| 1759 } | |
| 1760 | |
| 1761 private boolean endBatchEdit() throws Exception { | |
| 1762 final ChromiumBaseInputConnection connection = mConnection; | |
| 1763 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1764 @Override | |
| 1765 public Boolean call() { | |
| 1766 return connection.endBatchEdit(); | |
| 1767 } | |
| 1768 }); | |
| 1769 } | |
| 1770 | |
| 1771 private boolean commitText(final CharSequence text, final int newCursorPosit
ion) | |
| 1772 throws Exception { | |
| 1773 final ChromiumBaseInputConnection connection = mConnection; | |
| 1774 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1775 @Override | |
| 1776 public Boolean call() { | |
| 1777 return connection.commitText(text, newCursorPosition); | |
| 1778 } | |
| 1779 }); | |
| 1780 } | |
| 1781 | |
| 1782 private boolean setSelection(final int start, final int end) throws Exceptio
n { | |
| 1783 final ChromiumBaseInputConnection connection = mConnection; | |
| 1784 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1785 @Override | |
| 1786 public Boolean call() { | |
| 1787 return connection.setSelection(start, end); | |
| 1788 } | |
| 1789 }); | |
| 1790 } | |
| 1791 | |
| 1792 private boolean setComposingRegion(final int start, final int end) throws Ex
ception { | |
| 1793 final ChromiumBaseInputConnection connection = mConnection; | |
| 1794 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1795 @Override | |
| 1796 public Boolean call() { | |
| 1797 return connection.setComposingRegion(start, end); | |
| 1798 } | |
| 1799 }); | |
| 1800 } | |
| 1801 | |
| 1802 protected boolean setComposingText(final CharSequence text, final int newCur
sorPosition) | |
| 1803 throws Exception { | |
| 1804 final ChromiumBaseInputConnection connection = mConnection; | |
| 1805 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1806 @Override | |
| 1807 public Boolean call() { | |
| 1808 return connection.setComposingText(text, newCursorPosition); | |
| 1809 } | |
| 1810 }); | |
| 1811 } | |
| 1812 | |
| 1813 private boolean finishComposingText() throws Exception { | |
| 1814 final ChromiumBaseInputConnection connection = mConnection; | |
| 1815 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1816 @Override | |
| 1817 public Boolean call() { | |
| 1818 return connection.finishComposingText(); | |
| 1819 } | |
| 1820 }); | |
| 1821 } | |
| 1822 | |
| 1823 private boolean deleteSurroundingText(final int before, final int after) thr
ows Exception { | |
| 1824 final ChromiumBaseInputConnection connection = mConnection; | |
| 1825 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1826 @Override | |
| 1827 public Boolean call() { | |
| 1828 return connection.deleteSurroundingText(before, after); | |
| 1829 } | |
| 1830 }); | |
| 1831 } | |
| 1832 | |
| 1833 // Note that deleteSurroundingTextInCodePoints() was introduced in Android N
(Api level 24), but | |
| 1834 // the Android repository used in Chrome is behind that (level 23). So this
function can't be | |
| 1835 // called by keyboard apps currently. | |
| 1836 @TargetApi(24) | |
| 1837 private boolean deleteSurroundingTextInCodePoints(final int before, final in
t after) | |
| 1838 throws Exception { | |
| 1839 final ThreadedInputConnection connection = (ThreadedInputConnection) mCo
nnection; | |
| 1840 return runBlockingOnImeThread(new Callable<Boolean>() { | |
| 1841 @Override | |
| 1842 public Boolean call() { | |
| 1843 return connection.deleteSurroundingTextInCodePoints(before, afte
r); | |
| 1844 } | |
| 1845 }); | |
| 1846 } | |
| 1847 | |
| 1848 private CharSequence getTextBeforeCursor(final int length, final int flags)
throws Exception { | |
| 1849 final ChromiumBaseInputConnection connection = mConnection; | |
| 1850 return runBlockingOnImeThread(new Callable<CharSequence>() { | |
| 1851 @Override | |
| 1852 public CharSequence call() { | |
| 1853 return connection.getTextBeforeCursor(length, flags); | |
| 1854 } | |
| 1855 }); | |
| 1856 } | |
| 1857 | |
| 1858 private CharSequence getSelectedText(final int flags) throws Exception { | |
| 1859 final ChromiumBaseInputConnection connection = mConnection; | |
| 1860 return runBlockingOnImeThread(new Callable<CharSequence>() { | |
| 1861 @Override | |
| 1862 public CharSequence call() { | |
| 1863 return connection.getSelectedText(flags); | |
| 1864 } | |
| 1865 }); | |
| 1866 } | |
| 1867 | |
| 1868 private CharSequence getTextAfterCursor(final int length, final int flags) t
hrows Exception { | |
| 1869 final ChromiumBaseInputConnection connection = mConnection; | |
| 1870 return runBlockingOnImeThread(new Callable<CharSequence>() { | |
| 1871 @Override | |
| 1872 public CharSequence call() { | |
| 1873 return connection.getTextAfterCursor(length, flags); | |
| 1874 } | |
| 1875 }); | |
| 1876 } | |
| 1877 | |
| 1878 private int getCursorCapsMode(final int reqModes) throws Throwable { | |
| 1879 final ChromiumBaseInputConnection connection = mConnection; | |
| 1880 return runBlockingOnImeThread(new Callable<Integer>() { | |
| 1881 @Override | |
| 1882 public Integer call() { | |
| 1883 return connection.getCursorCapsMode(reqModes); | |
| 1884 } | |
| 1885 }); | |
| 1886 } | |
| 1887 | |
| 1888 private void dispatchKeyEvent(final KeyEvent event) { | |
| 1889 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 1890 @Override | |
| 1891 public void run() { | |
| 1892 mImeAdapter.dispatchKeyEvent(event); | |
| 1893 } | |
| 1894 }); | |
| 1895 } | |
| 1896 | |
| 1897 /** | |
| 1898 * Focus element, wait for a single state update, reset state update list. | |
| 1899 * @param id ID of the element to focus. | |
| 1900 */ | |
| 1901 private void focusElementAndWaitForStateUpdate(String id) | |
| 1902 throws InterruptedException, TimeoutException { | |
| 1903 resetUpdateSelectionList(); | |
| 1904 focusElement(id); | |
| 1905 waitAndVerifyUpdateSelection(0, 0, 0, -1, -1); | |
| 1906 resetUpdateSelectionList(); | |
| 1907 } | |
| 1908 | |
| 1909 private void focusElement(final String id) throws InterruptedException, Time
outException { | |
| 1910 focusElement(id, true); | |
| 1911 } | |
| 1912 | |
| 1913 private void focusElement(final String id, boolean shouldShowKeyboard) | |
| 1914 throws InterruptedException, TimeoutException { | |
| 1915 DOMUtils.focusNode(mWebContents, id); | |
| 1916 assertWaitForKeyboardStatus(shouldShowKeyboard); | |
| 1917 CriteriaHelper.pollInstrumentationThread(Criteria.equals(id, new Callabl
e<String>() { | |
| 1918 @Override | |
| 1919 public String call() throws Exception { | |
| 1920 return DOMUtils.getFocusedNode(mWebContents); | |
| 1921 } | |
| 1922 })); | |
| 1923 // When we focus another element, the connection may be recreated. | |
| 1924 mConnection = getInputConnection(); | |
| 1925 } | |
| 1926 | |
| 1927 private static class TestInputConnectionFactory implements ChromiumBaseInput
Connection.Factory { | |
| 1928 private final ChromiumBaseInputConnection.Factory mFactory; | |
| 1929 | |
| 1930 private final List<Integer> mTextInputTypeList = new ArrayList<>(); | |
| 1931 private EditorInfo mOutAttrs; | |
| 1932 | |
| 1933 public TestInputConnectionFactory(ChromiumBaseInputConnection.Factory fa
ctory) { | |
| 1934 mFactory = factory; | |
| 1935 } | |
| 1936 | |
| 1937 @Override | |
| 1938 public ChromiumBaseInputConnection initializeAndGet(View view, ImeAdapte
r imeAdapter, | |
| 1939 int inputType, int inputFlags, int inputMode, int selectionStart
, int selectionEnd, | |
| 1940 EditorInfo outAttrs) { | |
| 1941 mTextInputTypeList.add(inputType); | |
| 1942 mOutAttrs = outAttrs; | |
| 1943 return mFactory.initializeAndGet(view, imeAdapter, inputType, inputM
ode, inputFlags, | |
| 1944 selectionStart, selectionEnd, outAttrs); | |
| 1945 } | |
| 1946 | |
| 1947 @Override | |
| 1948 public Handler getHandler() { | |
| 1949 return mFactory.getHandler(); | |
| 1950 } | |
| 1951 | |
| 1952 public Integer[] getTextInputTypeHistory() { | |
| 1953 Integer[] result = new Integer[mTextInputTypeList.size()]; | |
| 1954 mTextInputTypeList.toArray(result); | |
| 1955 return result; | |
| 1956 } | |
| 1957 | |
| 1958 public void clearTextInputTypeHistory() { | |
| 1959 mTextInputTypeList.clear(); | |
| 1960 } | |
| 1961 | |
| 1962 public EditorInfo getOutAttrs() { | |
| 1963 return mOutAttrs; | |
| 1964 } | |
| 1965 | |
| 1966 @Override | |
| 1967 public void onWindowFocusChanged(boolean gainFocus) { | |
| 1968 mFactory.onWindowFocusChanged(gainFocus); | |
| 1969 } | |
| 1970 | |
| 1971 @Override | |
| 1972 public void onViewFocusChanged(boolean gainFocus) { | |
| 1973 mFactory.onViewFocusChanged(gainFocus); | |
| 1974 } | |
| 1975 | |
| 1976 @Override | |
| 1977 public void onViewAttachedToWindow() { | |
| 1978 mFactory.onViewAttachedToWindow(); | |
| 1979 } | |
| 1980 | |
| 1981 @Override | |
| 1982 public void onViewDetachedFromWindow() { | |
| 1983 mFactory.onViewDetachedFromWindow(); | |
| 1984 } | |
| 1985 } | |
| 1986 } | 1498 } |
| OLD | NEW |