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 |