Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Unified Diff: content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java

Issue 1388283002: Fix OSK flickering issue (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
index bf4c10a3fb8dbd73e129020d4e867d539b0e9fea..fa0dd818f6784f23dcdb54caea584b1bc8870458 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -29,25 +29,30 @@ import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper;
import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper.Range;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_shell_apk.ContentShellTestBase;
+import org.chromium.ui.base.ime.TextInputType;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
/**
* Integration tests for text input using cases based on fixed regressions.
*/
public class ImeTest extends ContentShellTestBase {
-
private static final String DATA_URL = UrlUtils.encodeHtmlDataUri(
"<html><head><meta name=\"viewport\""
+ "content=\"width=device-width, initial-scale=2.0, maximum-scale=2.0\" /></head>"
+ "<body><form action=\"about:blank\">"
- + "<input id=\"input_text\" type=\"text\" /><br/>"
+ + "<input id=\"input_text\" type=\"text\" /><br/></form><form>"
+ "<input id=\"input_radio\" type=\"radio\" style=\"width:50px;height:50px\" />"
+ "<br/><textarea id=\"textarea\" rows=\"4\" cols=\"20\"></textarea>"
+ "<br/><textarea id=\"textarea2\" rows=\"4\" cols=\"20\" autocomplete=\"off\">"
+ "</textarea>"
+ + "<br/><input id=\"input_number1\" type=\"number\" /><br/>"
+ + "<br/><input id=\"input_number2\" type=\"number\" /><br/>"
+ "<br/><p><span id=\"plain_text\">This is Plain Text One</span></p>"
+ "</form></body></html>");
@@ -86,23 +91,21 @@ public class ImeTest extends ContentShellTestBase {
mConnection = (TestAdapterInputConnection) getAdapterInputConnection();
mImeAdapter = getImeAdapter();
- // Two state updates from focus change and GestureTap.
- waitAndVerifyStatesAndCalls(0, "", 0, 0, -1, -1);
- waitAndVerifyStatesAndCalls(1, "", 0, 0, -1, -1);
-
- assertEquals(1, mInputMethodManagerWrapper.getShowSoftInputCounter());
+ waitAndVerifyStatesAndCalls("", 0, 0, -1, -1);
+ waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT});
assertEquals(0, mInputMethodManagerWrapper.getEditorInfo().initialSelStart);
assertEquals(0, mInputMethodManagerWrapper.getEditorInfo().initialSelEnd);
- resetUpdateStateList();
+ resetAllStates();
}
- private void assertNoFurtherStateUpdate(final int index) throws InterruptedException {
+ private void assertNoFurtherStateUpdate() throws InterruptedException {
final List<TestImeState> states = mConnectionFactory.getImeStateList();
- assertFalse(CriteriaHelper.pollForCriteria(new Criteria() {
+ final int oldSize = states.size();
+ assertFalse(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
@Override
public boolean isSatisfied() {
- return states.size() > index;
+ return states.size() > oldSize;
}
}));
}
@@ -110,51 +113,47 @@ public class ImeTest extends ContentShellTestBase {
@MediumTest
@Feature({"TextInput", "Main"})
public void testSetUpGeneratesNoFurtherStateUpdate() throws Throwable {
- assertNoFurtherStateUpdate(0);
+ assertNoFurtherStateUpdate();
+ waitForKeyboardStates(0, 0, 0, new Integer[] {});
}
@MediumTest
@Feature({"TextInput", "Main"})
public void testKeyboardDismissedAfterClickingGo() throws Throwable {
setComposingText("hello", 1);
- waitAndVerifyStatesAndCalls(0, "hello", 5, 5, 0, 5);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, 0, 5);
performGo(mCallbackContainer);
- waitAndVerifyStatesAndCalls(1, "", 0, 0, -1, -1);
+ // May not have a selection update if initial selection was already 0,0.
+ waitAndVerifyStates("", 0, 0, -1, -1);
assertWaitForKeyboardStatus(false);
}
@SmallTest
@Feature({"TextInput", "Main"})
- @RerunWithUpdatedContainerView
- public void testGetTextUpdatesAfterEnteringText() throws Throwable {
+ public void testCommitWhileComposingText() throws Throwable {
setComposingText("h", 1);
- waitAndVerifyStates(0, "h", 1, 1, 0, 1);
- assertEquals(1, mInputMethodManagerWrapper.getShowSoftInputCounter());
+ waitAndVerifyStates("h", 1, 1, 0, 1);
setComposingText("he", 1);
- waitAndVerifyStates(1, "he", 2, 2, 0, 2);
- assertEquals(1, mInputMethodManagerWrapper.getShowSoftInputCounter());
+ waitAndVerifyStates("he", 2, 2, 0, 2);
setComposingText("hel", 1);
- waitAndVerifyStates(2, "hel", 3, 3, 0, 3);
- assertEquals(1, mInputMethodManagerWrapper.getShowSoftInputCounter());
+ waitAndVerifyStates("hel", 3, 3, 0, 3);
commitText("hel", 1);
- waitAndVerifyStates(3, "hel", 3, 3, -1, -1);
- assertEquals(1, mInputMethodManagerWrapper.getShowSoftInputCounter());
+ waitAndVerifyStates("hel", 3, 3, -1, -1);
}
@SmallTest
@Feature({"TextInput"})
- @RerunWithUpdatedContainerView
public void testImeCopy() throws Exception {
commitText("hello", 1);
- waitAndVerifyStates(0, "hello", 5, 5, -1, -1);
+ waitAndVerifyStates("hello", 5, 5, -1, -1);
setSelection(2, 5);
- waitAndVerifyStates(1, "hello", 2, 5, -1, -1);
+ waitAndVerifyStates("hello", 2, 5, -1, -1);
copy();
assertClipboardContents(getActivity(), "llo");
@@ -164,22 +163,90 @@ public class ImeTest extends ContentShellTestBase {
@Feature({"TextInput"})
public void testEnterTextAndRefocus() throws Exception {
commitText("hello", 1);
- waitAndVerifyStatesAndCalls(0, "hello", 5, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, -1, -1);
DOMUtils.clickNode(this, mContentViewCore, "input_radio");
assertWaitForKeyboardStatus(false);
DOMUtils.clickNode(this, mContentViewCore, "input_text");
assertWaitForKeyboardStatus(true);
- assertEquals(5, mInputMethodManagerWrapper.getEditorInfo().initialSelStart);
- assertEquals(5, mInputMethodManagerWrapper.getEditorInfo().initialSelEnd);
+
+ // Current logic does not set initial selection range correctly. If the
+ // timing is correct (updateState immediately before restartInput happens).
+ // assertEquals(5, mInputMethodManagerWrapper.getEditorInfo().initialSelStart);
+ // assertEquals(5, mInputMethodManagerWrapper.getEditorInfo().initialSelEnd);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, -1, -1);
+ }
+
+ @SmallTest
+ @Feature({"TextInput"})
+ public void testShowAndHideSoftInput() throws Exception {
+ focusElement("input_radio", false);
+ waitAndVerifyStatesAndCalls("", 0, 0, -1, -1);
+
+ // hideSoftKeyboard().
+ waitForKeyboardStates(0, 1, 0, new Integer[] {});
+
+ // showSoftInput(), restartInput()
+ focusElement("input_number1");
+ waitForKeyboardStates(1, 1, 1, new Integer[] {TextInputType.NUMBER});
+
+ focusElement("input_number2");
+ // Hide should never be called here. Otherwise we will see a flicker. Restarted to
+ // reset internal states to handle the new input form.
+ waitForKeyboardStates(2, 1, 2, new Integer[] {TextInputType.NUMBER, TextInputType.NUMBER});
+
+ focusElement("input_text");
+ // showSoftInput() on input_text. restartInput() on input_number1 due to focus change,
+ // and restartInput() on input_text later.
+ // TODO(changwan): reduce unnecessary restart input.
+ waitForKeyboardStates(3, 1, 4, new Integer[] {
+ TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.NUMBER,
+ TextInputType.TEXT});
+
+ focusElement("input_radio", false);
+ // hideSoftInput().
+ waitForKeyboardStates(3, 2, 4, new Integer[] {
+ TextInputType.NUMBER, TextInputType.NUMBER, TextInputType.NUMBER,
+ TextInputType.TEXT});
+ }
+
+ private void waitForKeyboardStates(int show, int hide, int restart, Integer[] history)
+ throws InterruptedException {
+ final String expected = stringifyKeyboardStates(show, hide, restart, history);
+ assertTrue("Expected: {" + expected + "}, Actual: {" + getKeyboardStates() + "}",
+ CriteriaHelper.pollForCriteria(new Criteria() {
+ @Override
+ public boolean isSatisfied() {
+ return expected.equals(getKeyboardStates());
+ }
+ }));
+ }
+
+ private void resetAllStates() {
+ mInputMethodManagerWrapper.resetCounters();
+ mConnectionFactory.clearTextInputTypeHistory();
+ resetUpdateStateList();
+ }
+
+ private String getKeyboardStates() {
+ int showCount = mInputMethodManagerWrapper.getShowSoftInputCounter();
+ int hideCount = mInputMethodManagerWrapper.getHideSoftInputCounter();
+ int restartCount = mInputMethodManagerWrapper.getRestartInputCounter();
+ Integer[] history = mConnectionFactory.getTextInputTypeHistory();
+ return stringifyKeyboardStates(showCount, hideCount, restartCount, history);
+ }
+
+ private String stringifyKeyboardStates(int show, int hide, int restart, Integer[] history) {
+ return "show count: " + show + ", hide count: " + hide + ", restart count: " + restart
+ + ", input type history: " + Arrays.deepToString(history);
}
@SmallTest
@Feature({"TextInput"})
public void testKeyboardNotDismissedAfterCopySelection() throws Exception {
commitText("Sample Text", 1);
- waitAndVerifyStatesAndCalls(0, "Sample Text", 11, 11, -1, -1);
+ waitAndVerifyStatesAndCalls("Sample Text", 11, 11, -1, -1);
DOMUtils.clickNode(this, mContentViewCore, "input_text");
assertWaitForKeyboardStatus(true);
DOMUtils.longPressNode(this, mContentViewCore, "input_text");
@@ -193,7 +260,7 @@ public class ImeTest extends ContentShellTestBase {
@Feature({"TextInput"})
public void testImeNotDismissedAfterCutSelection() throws Exception {
commitText("Sample Text", 1);
- waitAndVerifyStatesAndCalls(0, "Sample Text", 11, 11, -1, -1);
+ waitAndVerifyStatesAndCalls("Sample Text", 11, 11, -1, -1);
DOMUtils.longPressNode(this, mContentViewCore, "input_text");
assertWaitForSelectActionBarStatus(true);
assertWaitForKeyboardStatus(true);
@@ -228,21 +295,21 @@ public class ImeTest extends ContentShellTestBase {
public void testLongPressInputWhileComposingText() throws Exception {
assertWaitForSelectActionBarStatus(false);
setComposingText("Sample Text", 1);
- waitAndVerifyStatesAndCalls(0, "Sample Text", 11, 11, 0, 11);
+ waitAndVerifyStatesAndCalls("Sample Text", 11, 11, 0, 11);
DOMUtils.longPressNode(this, mContentViewCore, "input_text");
assertWaitForSelectActionBarStatus(true);
// Long press will first change selection region, and then trigger IME app to show up.
// See RenderFrameImpl::didChangeSelection() and RenderWidget::didHandleGestureEvent().
- waitAndVerifyStatesAndCalls(1, "Sample Text", 7, 11, 0, 11);
- waitAndVerifyStatesAndCalls(2, "Sample Text", 7, 11, 0, 11);
+ waitAndVerifyStatesAndCalls("Sample Text", 7, 11, 0, 11);
+ waitAndVerifyStatesAndCalls("Sample Text", 7, 11, 0, 11);
// Now IME app wants to finish composing text because an external selection
// change has been detected. At least Google Latin IME and Samsung IME
// behave this way.
finishComposingText();
- waitAndVerifyStatesAndCalls(3, "Sample Text", 7, 11, -1, -1);
+ waitAndVerifyStatesAndCalls("Sample Text", 7, 11, -1, -1);
}
@SmallTest
@@ -320,13 +387,13 @@ public class ImeTest extends ContentShellTestBase {
@Feature({"TextInput"})
public void testImeCut() throws Exception {
commitText("snarful", 1);
- waitAndVerifyStatesAndCalls(0, "snarful", 7, 7, -1, -1);
+ waitAndVerifyStatesAndCalls("snarful", 7, 7, -1, -1);
setSelection(1, 5);
- waitAndVerifyStatesAndCalls(1, "snarful", 1, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("snarful", 1, 5, -1, -1);
cut();
- waitAndVerifyStatesAndCalls(2, "sul", 1, 1, -1, -1);
+ waitAndVerifyStatesAndCalls("sul", 1, 1, -1, -1);
assertClipboardContents(getActivity(), "narf");
}
@@ -345,31 +412,29 @@ public class ImeTest extends ContentShellTestBase {
});
paste();
- waitAndVerifyStatesAndCalls(0, "blarg", 5, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("blarg", 5, 5, -1, -1);
setSelection(3, 5);
- waitAndVerifyStatesAndCalls(1, "blarg", 3, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("blarg", 3, 5, -1, -1);
paste();
- // Paste is a two step process when there is a non-zero selection.
- waitAndVerifyStates(2, "bla", 3, 3, -1, -1);
- waitAndVerifyStatesAndCalls(3, "blablarg", 8, 8, -1, -1);
+ waitAndVerifyStatesAndCalls("blablarg", 8, 8, -1, -1);
paste();
- waitAndVerifyStatesAndCalls(4, "blablargblarg", 13, 13, -1, -1);
+ waitAndVerifyStatesAndCalls("blablargblarg", 13, 13, -1, -1);
}
@SmallTest
@Feature({"TextInput"})
public void testImeSelectAndUnSelectAll() throws Exception {
commitText("hello", 1);
- waitAndVerifyStatesAndCalls(0, "hello", 5, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, -1, -1);
selectAll();
- waitAndVerifyStatesAndCalls(1, "hello", 0, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hello", 0, 5, -1, -1);
unselect();
- waitAndVerifyStatesAndCalls(2, "", 0, 0, -1, -1);
+ waitAndVerifyStatesAndCalls("", 0, 0, -1, -1);
assertWaitForKeyboardStatus(false);
}
@@ -392,29 +457,29 @@ public class ImeTest extends ContentShellTestBase {
focusElementAndWaitForStateUpdate("textarea");
commitText("hllo", 1);
- waitAndVerifyStatesAndCalls(0, "hllo", 4, 4, -1, -1);
+ waitAndVerifyStatesAndCalls("hllo", 4, 4, -1, -1);
commitText(" ", 1);
- waitAndVerifyStatesAndCalls(1, "hllo ", 5, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hllo ", 5, 5, -1, -1);
setSelection(1, 1);
- waitAndVerifyStatesAndCalls(2, "hllo ", 1, 1, -1, -1);
+ waitAndVerifyStatesAndCalls("hllo ", 1, 1, -1, -1);
setComposingRegion(0, 4);
- waitAndVerifyStatesAndCalls(3, "hllo ", 1, 1, 0, 4);
+ waitAndVerifyStatesAndCalls("hllo ", 1, 1, 0, 4);
finishComposingText();
- waitAndVerifyStatesAndCalls(4, "hllo ", 1, 1, -1, -1);
+ waitAndVerifyStatesAndCalls("hllo ", 1, 1, -1, -1);
commitText("\n", 1);
- waitAndVerifyStatesAndCalls(5, "h\nllo ", 2, 2, -1, -1);
+ waitAndVerifyStatesAndCalls("h\nllo ", 2, 2, -1, -1);
}
/*
- @SmallTest
- @Feature({"TextInput", "Main"})
http://crbug.com/445499
*/
+ @SmallTest
+ @Feature({"TextInput", "Main"})
public void testDeleteText() throws Throwable {
focusElement("textarea");
@@ -423,52 +488,47 @@ public class ImeTest extends ContentShellTestBase {
// H
resetUpdateStateList();
setComposingText("h", 1);
- assertUpdateStateCall(1000);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("h", getTextBeforeCursor(9, 0));
// O
resetUpdateStateList();
setComposingText("ho", 1);
- assertUpdateStateCall(1000);
- assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("ho", getTextBeforeCursor(9, 0));
resetUpdateStateList();
setComposingText("h", 1);
- assertUpdateStateCall(1000);
setComposingRegion(0, 1);
setComposingText("h", 1);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("h", getTextBeforeCursor(9, 0));
// I
setComposingText("hi", 1);
- assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hi", getTextBeforeCursor(9, 0));
// SPACE
commitText("hi", 1);
commitText(" ", 1);
- assertEquals("hi ", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hi ", getTextBeforeCursor(9, 0));
// DEL
deleteSurroundingText(1, 0);
setComposingRegion(0, 2);
- assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hi", getTextBeforeCursor(9, 0));
setComposingText("h", 1);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("h", getTextBeforeCursor(9, 0));
commitText("", 1);
- assertEquals("", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("", getTextBeforeCursor(9, 0));
// DEL (on empty input)
deleteSurroundingText(1, 0); // DEL on empty still sends 1,0
- assertEquals("", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("", getTextBeforeCursor(9, 0));
}
- /*
@SmallTest
@Feature({"TextInput", "Main"})
- */
public void testSwipingText() throws Throwable {
focusElement("textarea");
@@ -477,26 +537,20 @@ public class ImeTest extends ContentShellTestBase {
// that the test reflects reality. If this test breaks, it's possible that code has
// changed and different calls need to be made instead.
// "three"
- resetUpdateStateList();
setComposingText("three", 1);
- assertUpdateStateCall(1000);
- assertEquals("three", mConnection.getTextBeforeCursor(99, 0));
+ assertEquals("three", getTextBeforeCursor(99, 0));
// "word"
commitText("three", 1);
commitText(" ", 1);
setComposingText("word", 1);
- resetUpdateStateList();
- assertUpdateStateCall(1000);
- assertEquals("three word", mConnection.getTextBeforeCursor(99, 0));
+ assertEquals("three word", getTextBeforeCursor(99, 0));
// "test"
commitText("word", 1);
commitText(" ", 1);
- resetUpdateStateList();
setComposingText("test", 1);
- assertUpdateStateCall(1000);
- assertEquals("three word test", mConnection.getTextBeforeCursor(99, 0));
+ assertEquals("three word test", getTextBeforeCursor(99, 0));
}
@SmallTest
@@ -506,19 +560,19 @@ public class ImeTest extends ContentShellTestBase {
final String smiley = "\uD83D\uDE0A";
commitText(smiley, 1);
- waitAndVerifyStatesAndCalls(0, smiley, 2, 2, -1, -1);
+ waitAndVerifyStatesAndCalls(smiley, 2, 2, -1, -1);
// DEL, sent via dispatchKeyEvent like it is in Android WebView or a physical keyboard.
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
- waitAndVerifyStatesAndCalls(1, "", 0, 0, -1, -1);
+ waitAndVerifyStatesAndCalls("", 0, 0, -1, -1);
// Make sure that we accept further typing after deleting the smiley.
setComposingText("s", 1);
- waitAndVerifyStatesAndCalls(2, "s", 1, 1, 0, 1);
+ waitAndVerifyStatesAndCalls("s", 1, 1, 0, 1);
setComposingText("sm", 1);
- waitAndVerifyStatesAndCalls(3, "sm", 2, 2, 0, 2);
+ waitAndVerifyStatesAndCalls("sm", 2, 2, 0, 2);
}
@SmallTest
@@ -527,28 +581,19 @@ public class ImeTest extends ContentShellTestBase {
focusElement("textarea");
// H
- resetUpdateStateList();
commitText("h", 1);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
- assertUpdateStateCall(1000);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("h", getTextBeforeCursor(9, 0));
// O
- resetUpdateStateList();
commitText("o", 1);
- assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
- assertUpdateStateCall(1000);
- assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("ho", getTextBeforeCursor(9, 0));
// DEL, sent via dispatchKeyEvent like it is in Android WebView or a physical keyboard.
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
// DEL
- resetUpdateStateList();
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
- assertUpdateStateCall(1000);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("h", getTextBeforeCursor(9, 0));
}
@SmallTest
@@ -557,18 +602,12 @@ public class ImeTest extends ContentShellTestBase {
focusElement("textarea");
// H
- resetUpdateStateList();
commitText("h", 1);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
- assertUpdateStateCall(1000);
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("h", getTextBeforeCursor(9, 0));
// O
- resetUpdateStateList();
commitText("o", 1);
- assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
- assertUpdateStateCall(1000);
- assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("ho", getTextBeforeCursor(9, 0));
// Multiple keydowns should each delete one character (this is for physical keyboard
// key-repeat).
@@ -577,10 +616,7 @@ public class ImeTest extends ContentShellTestBase {
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
// DEL
- resetUpdateStateList();
- assertEquals("", mConnection.getTextBeforeCursor(9, 0));
- assertUpdateStateCall(1000);
- assertEquals("", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("", getTextBeforeCursor(9, 0));
}
@SmallTest
@@ -591,17 +627,17 @@ public class ImeTest extends ContentShellTestBase {
// Type 'a' using a physical keyboard.
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A));
- waitAndVerifyStatesAndCalls(0, "a", 1, 1, -1, -1);
+ waitAndVerifyStatesAndCalls("a", 1, 1, -1, -1);
// Type 'enter' key.
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER));
- waitAndVerifyStatesAndCalls(1, "a\n\n", 2, 2, -1, -1);
+ waitAndVerifyStatesAndCalls("a\n\n", 2, 2, -1, -1);
// Type 'b'.
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_B));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_B));
- waitAndVerifyStatesAndCalls(2, "a\nb", 3, 3, -1, -1);
+ waitAndVerifyStatesAndCalls("a\nb", 3, 3, -1, -1);
}
@SmallTest
@@ -612,72 +648,61 @@ public class ImeTest extends ContentShellTestBase {
// h
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_H));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_H));
- assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
- waitAndVerifyStatesAndCalls(0, "h", 1, 1, -1, -1);
+ assertEquals("h", getTextBeforeCursor(9, 0));
+ waitAndVerifyStatesAndCalls("h", 1, 1, -1, -1);
// ALT-i (circumflex accent key on virtual keyboard)
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertUpdateStateCall(1000);
- assertEquals("hˆ", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hˆ", getTextBeforeCursor(9, 0));
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertEquals("hˆ", mConnection.getTextBeforeCursor(9, 0));
- waitAndVerifyStatesAndCalls(1, "hˆ", 2, 2, 1, 2);
+ assertEquals("hˆ", getTextBeforeCursor(9, 0));
+ waitAndVerifyStatesAndCalls("hˆ", 2, 2, 1, 2);
// o
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_O));
- assertUpdateStateCall(1000);
- assertEquals("hô", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hô", getTextBeforeCursor(9, 0));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_O));
- assertEquals("hô", mConnection.getTextBeforeCursor(9, 0));
- waitAndVerifyStatesAndCalls(2, "hô", 2, 2, -1, -1);
+ assertEquals("hô", getTextBeforeCursor(9, 0));
+ waitAndVerifyStatesAndCalls("hô", 2, 2, -1, -1);
// ALT-i
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertUpdateStateCall(1000);
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertEquals("hôˆ", mConnection.getTextBeforeCursor(9, 0));
- waitAndVerifyStatesAndCalls(3, "hôˆ", 3, 3, 2, 3);
+ assertEquals("hôˆ", getTextBeforeCursor(9, 0));
+ waitAndVerifyStatesAndCalls("hôˆ", 3, 3, 2, 3);
// ALT-i again should have no effect
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertUpdateStateCall(1000);
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertEquals("hôˆ", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hôˆ", getTextBeforeCursor(9, 0));
// b (cannot be accented, should just appear after)
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_B));
- assertUpdateStateCall(1000);
- assertEquals("hôˆb", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hôˆb", getTextBeforeCursor(9, 0));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_B));
- assertEquals("hôˆb", mConnection.getTextBeforeCursor(9, 0));
- // A transitional state due to finishComposingText.
- waitAndVerifyStates(4, "hôˆ", 3, 3, -1, -1);
- waitAndVerifyStatesAndCalls(5, "hôˆb", 4, 4, -1, -1);
+ assertEquals("hôˆb", getTextBeforeCursor(9, 0));
+ waitAndVerifyStatesAndCalls("hôˆb", 4, 4, -1, -1);
// ALT-i
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertUpdateStateCall(1000);
dispatchKeyEvent(new KeyEvent(
0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_I, 0, KeyEvent.META_ALT_ON));
- assertEquals("hôˆbˆ", mConnection.getTextBeforeCursor(9, 0));
- waitAndVerifyStatesAndCalls(6, "hôˆbˆ", 5, 5, 4, 5);
+ assertEquals("hôˆbˆ", getTextBeforeCursor(9, 0));
+ waitAndVerifyStatesAndCalls("hôˆbˆ", 5, 5, 4, 5);
// Backspace
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
- assertUpdateStateCall(1000);
- assertEquals("hôˆb", mConnection.getTextBeforeCursor(9, 0));
+ assertEquals("hôˆb", getTextBeforeCursor(9, 0));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
- assertEquals("hôˆb", mConnection.getTextBeforeCursor(9, 0));
- // A transitional state due to finishComposingText in deleteSurroundingTextImpl.
- waitAndVerifyStates(7, "hôˆbˆ", 5, 5, -1, -1);
- waitAndVerifyStatesAndCalls(8, "hôˆb", 4, 4, -1, -1);
+ assertEquals("hôˆb", getTextBeforeCursor(9, 0));
+ waitAndVerifyStatesAndCalls("hôˆb", 4, 4, -1, -1);
}
@SmallTest
@@ -697,17 +722,17 @@ public class ImeTest extends ContentShellTestBase {
focusElementAndWaitForStateUpdate("textarea");
commitText("hello", 1);
- waitAndVerifyStatesAndCalls(0, "hello", 5, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, -1, -1);
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER));
// TODO(aurimas): remove this workaround when crbug.com/278584 is fixed.
// The second new line is not a user visible/editable one, it is a side-effect of Blink
// using <br> internally. This only happens when \n is at the end.
- waitAndVerifyStatesAndCalls(1, "hello\n\n", 6, 6, -1, -1);
+ waitAndVerifyStatesAndCalls("hello\n\n", 6, 6, -1, -1);
commitText("world", 1);
- waitAndVerifyStatesAndCalls(2, "hello\nworld", 11, 11, -1, -1);
+ waitAndVerifyStatesAndCalls("hello\nworld", 11, 11, -1, -1);
}
@SmallTest
@@ -716,20 +741,18 @@ public class ImeTest extends ContentShellTestBase {
focusElementAndWaitForStateUpdate("textarea");
setComposingText("hello", 1);
- waitAndVerifyStatesAndCalls(0, "hello", 5, 5, 0, 5);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, 0, 5);
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER));
// TODO(aurimas): remove this workaround when crbug.com/278584 is fixed.
- // A transitional state due to finishComposingText.
- waitAndVerifyStates(1, "hello", 5, 5, -1, -1);
// The second new line is not a user visible/editable one, it is a side-effect of Blink
// using <br> internally. This only happens when \n is at the end.
- waitAndVerifyStatesAndCalls(2, "hello\n\n", 6, 6, -1, -1);
+ waitAndVerifyStatesAndCalls("hello\n\n", 6, 6, -1, -1);
commitText("world", 1);
- waitAndVerifyStatesAndCalls(3, "hello\nworld", 11, 11, -1, -1);
+ waitAndVerifyStatesAndCalls("hello\nworld", 11, 11, -1, -1);
}
@SmallTest
@@ -738,22 +761,21 @@ public class ImeTest extends ContentShellTestBase {
focusElement("textarea");
// DPAD_CENTER should cause keyboard to appear
- resetUpdateStateList();
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
- assertUpdateStateCall(1000);
+ assertWaitForKeyboardStatus(true);
}
@SmallTest
@Feature({"TextInput"})
public void testPastePopupShowAndHide() throws Throwable {
commitText("hello", 1);
- waitAndVerifyStatesAndCalls(0, "hello", 5, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, -1, -1);
selectAll();
- waitAndVerifyStatesAndCalls(1, "hello", 0, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hello", 0, 5, -1, -1);
cut();
- waitAndVerifyStatesAndCalls(2, "", 0, 0, -1, -1);
+ waitAndVerifyStatesAndCalls("", 0, 0, -1, -1);
DOMUtils.longPressNode(this, mContentViewCore, "input_text");
assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
@@ -780,7 +802,7 @@ public class ImeTest extends ContentShellTestBase {
@Feature({"TextInput"})
public void testSelectionClearedOnKeyEvent() throws Throwable {
commitText("hello", 1);
- waitAndVerifyStatesAndCalls(0, "hello", 5, 5, -1, -1);
+ waitAndVerifyStatesAndCalls("hello", 5, 5, -1, -1);
DOMUtils.clickNode(this, mContentViewCore, "input_text");
assertWaitForKeyboardStatus(true);
@@ -809,7 +831,7 @@ public class ImeTest extends ContentShellTestBase {
@Feature({"TextInput"})
public void testRestartInputWhileComposingText() throws Throwable {
setComposingText("abc", 1);
- waitAndVerifyStatesAndCalls(0, "abc", 3, 3, 0, 3);
+ waitAndVerifyStatesAndCalls("abc", 3, 3, 0, 3);
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
@@ -819,7 +841,7 @@ public class ImeTest extends ContentShellTestBase {
// We don't do anything when input gets restarted. But we depend on Android's
// InputMethodManager and/or input methods to call finishComposingText() in setting
// current input connection as active or finishing the current input connection.
- assertNoFurtherStateUpdate(1);
+ assertNoFurtherStateUpdate();
}
private void performGo(TestCallbackHelperContainer testCallbackHelperContainer)
@@ -839,7 +861,7 @@ public class ImeTest extends ContentShellTestBase {
assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
@Override
public boolean isSatisfied() {
- return show == getImeAdapter().mIsShowWithoutHideOutstanding
+ return show == mInputMethodManagerWrapper.isShowWithoutHideOutstanding()
&& (!show || getAdapterInputConnection() != null);
}
}));
@@ -855,25 +877,32 @@ public class ImeTest extends ContentShellTestBase {
}));
}
- private void waitAndVerifyStates(final int index, String text, final int selectionStart,
- final int selectionEnd, final int compositionStart, final int compositionEnd)
- throws InterruptedException {
- final List<TestImeState> states = mConnectionFactory.getImeStateList();
- assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
- @Override
- public boolean isSatisfied() {
- return states.size() > index;
- }
- }));
- states.get(index).assertEqualState(
+ private void waitAndVerifyStates(String text, final int selectionStart, final int selectionEnd,
+ final int compositionStart, final int compositionEnd) throws InterruptedException {
+ final TestImeState expectedState = new TestImeState(
text, selectionStart, selectionEnd, compositionStart, compositionEnd);
+ assertTrue("Expected state: " + expectedState + ", actual state: " + getLastImeState(),
+ CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
+ @Override
+ public boolean isSatisfied() {
+ final TestImeState lastState = getLastImeState();
+ if (lastState == null) return false;
+
+ return expectedState.toString().equals(lastState.toString());
+ }
+ }));
}
- private void waitAndVerifyStatesAndCalls(final int index, String text, final int selectionStart,
+ private TestImeState getLastImeState() {
+ final List<TestImeState> states = mConnectionFactory.getImeStateList();
+ if (states.isEmpty()) return null;
+ return states.get(states.size() - 1);
+ }
+
+ private void waitAndVerifyStatesAndCalls(String text, final int selectionStart,
final int selectionEnd, final int compositionStart, final int compositionEnd)
throws InterruptedException {
- waitAndVerifyStates(
- index, text, selectionStart, selectionEnd, compositionStart, compositionEnd);
+ waitAndVerifyStates(text, selectionStart, selectionEnd, compositionStart, compositionEnd);
// Wait and verify calls to InputMethodManager.
final Range selection = new Range(selectionStart, selectionEnd);
@@ -881,7 +910,7 @@ public class ImeTest extends ContentShellTestBase {
assertTrue("Actual selection was: " + mInputMethodManagerWrapper.getSelection()
+ ", and actual composition was: "
+ mInputMethodManagerWrapper.getComposition(),
- CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
+ CriteriaHelper.pollForCriteria(new Criteria() {
@Override
public boolean isSatisfied() {
return mInputMethodManagerWrapper.getSelection().equals(selection)
@@ -894,18 +923,6 @@ public class ImeTest extends ContentShellTestBase {
mConnectionFactory.getImeStateList().clear();
}
- private void assertUpdateStateCall(int maxms) throws Exception {
- while (mConnectionFactory.getImeStateList().size() == 0 && maxms > 0) {
- try {
- Thread.sleep(50);
- } catch (Exception e) {
- // Not really a problem since we're just going to sleep again.
- }
- maxms -= 50;
- }
- assertTrue(mConnectionFactory.getImeStateList().size() > 0);
- }
-
private void assertClipboardContents(final Activity activity, final String expectedContents)
throws InterruptedException {
assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
@@ -1047,6 +1064,17 @@ public class ImeTest extends ContentShellTestBase {
});
}
+ private CharSequence getTextBeforeCursor(final int length, final int flags)
+ throws ExecutionException {
+ final AdapterInputConnection connection = mConnection;
+ return ThreadUtils.runOnUiThreadBlocking(new Callable<CharSequence>() {
+ @Override
+ public CharSequence call() {
+ return connection.getTextBeforeCursor(length, flags);
+ }
+ });
+ }
+
/**
* Focus element, wait for a single state update, reset state update list.
* @param id ID of the element to focus.
@@ -1054,13 +1082,18 @@ public class ImeTest extends ContentShellTestBase {
private void focusElementAndWaitForStateUpdate(String id)
throws InterruptedException, TimeoutException {
focusElement(id);
- waitAndVerifyStatesAndCalls(0, "", 0, 0, -1, -1);
+ waitAndVerifyStatesAndCalls("", 0, 0, -1, -1);
resetUpdateStateList();
}
private void focusElement(final String id) throws InterruptedException, TimeoutException {
+ focusElement(id, true);
+ }
+
+ private void focusElement(final String id, boolean shouldShowKeyboard)
+ throws InterruptedException, TimeoutException {
DOMUtils.focusNode(mWebContents, id);
- assertWaitForKeyboardStatus(true);
+ assertWaitForKeyboardStatus(shouldShowKeyboard);
assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
@Override
public boolean isSatisfied() {
@@ -1078,10 +1111,12 @@ public class ImeTest extends ContentShellTestBase {
private static class TestAdapterInputConnectionFactory extends
ImeAdapter.AdapterInputConnectionFactory {
private final List<TestImeState> mImeStateList = new ArrayList<>();
+ private final List<Integer> mTextInputTypeList = new ArrayList<>();
@Override
public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
Editable editable, EditorInfo outAttrs) {
+ mTextInputTypeList.add(imeAdapter.getTextInputType());
return new TestAdapterInputConnection(
mImeStateList, view, imeAdapter, editable, outAttrs);
}
@@ -1089,6 +1124,16 @@ public class ImeTest extends ContentShellTestBase {
public List<TestImeState> getImeStateList() {
return mImeStateList;
}
+
+ public Integer[] getTextInputTypeHistory() {
+ Integer[] result = new Integer[mTextInputTypeList.size()];
+ mTextInputTypeList.toArray(result);
+ return result;
+ }
+
+ public void clearTextInputTypeHistory() {
+ mTextInputTypeList.clear();
+ }
}
private static class TestAdapterInputConnection extends AdapterInputConnection {
@@ -1126,13 +1171,10 @@ public class ImeTest extends ContentShellTestBase {
mCompositionEnd = compositionEnd;
}
- public void assertEqualState(String text, int selectionStart, int selectionEnd,
- int compositionStart, int compositionEnd) {
- assertEquals("Text did not match", text, mText);
- assertEquals("Selection start did not match", selectionStart, mSelectionStart);
- assertEquals("Selection end did not match", selectionEnd, mSelectionEnd);
- assertEquals("Composition start did not match", compositionStart, mCompositionStart);
- assertEquals("Composition end did not match", compositionEnd, mCompositionEnd);
+ @Override
+ public String toString() {
+ return "text: " + mText + ", selection: [" + mSelectionStart + ", " + mSelectionEnd
+ + "], composition: [" + mCompositionStart + ", " + mCompositionEnd + "]";
}
}
}

Powered by Google App Engine
This is Rietveld 408576698