diff options
Diffstat (limited to 'libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/utils/TextField.java')
-rw-r--r-- | libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/utils/TextField.java | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/utils/TextField.java b/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/utils/TextField.java new file mode 100644 index 0000000..6a8bab6 --- /dev/null +++ b/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/utils/TextField.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.afwtest.uiautomator.utils; + +import android.os.SystemClock; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.BySelector; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.Until; +import android.util.Log; +import android.view.KeyEvent; + +import java.util.concurrent.TimeUnit; + +/** + * Text field related util functions. + */ +public final class TextField { + + private static final String TAG = "afwtest.TextField"; + + /** + * Default UI waiting time, in milliseconds. + */ + private static final long DEFAULT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5); + + /** + * Keyboard pop up waiting time, in milliseconds. + */ + private static final long KEYBOARD_START_TIME_MS = TimeUnit.SECONDS.toMillis(2); + + /** + * Private constructor to prevent instantiation. + */ + private TextField() { + } + + /** + * Inputs text into a text field and activate the navigation button. + * + * <p>Normally {@link UiObject2}.setText() will input text into a text field. + * But on some activities, such as Add Google Account page, the navigation button (e.g. NEXT) + * will not be activated until there is some non-space characters entered into the text + * field. Calling {@link UiObject2}.setText() will set the text but not activate the + * navigate button. + * This util function solves this problem by simulating key pressing event to enter '0' + * into the text filed to activate the navigation button before calling {@link UiObject2}. + * setText() to set the text. + * </p> + * + * @param uiDevice {@link UiDevice} object + * @param textFieldSelector {@link BySelector} for the text field + * @param text text to set + * @param navigationBtnSelector navigation button to activate + */ + public static void enterTextAndActivateNavigationBtn( + UiDevice uiDevice, + BySelector textFieldSelector, + String text, + BySelector navigationBtnSelector) throws Exception { + + // Try 3 times + int maxAttempts = 3; + while (maxAttempts > 0) { + + Log.i(TAG, String.format("Activating navigation button: %s.", + navigationBtnSelector.toString())); + + try { + activateNavigationBtn(uiDevice, textFieldSelector, navigationBtnSelector); + // Navigation button activated, exit loop + break; + } catch (Exception e) { + + --maxAttempts; + + // Don't throw in the retry loop + Log.e(TAG, String.format("Failed to activate navigation button, attempts left: %d.", + maxAttempts), e); + } + } + + // Throw exception if activation button is not activated. + if (maxAttempts <= 0) { + throw new RuntimeException(String.format("Failed to activate navigation button", + navigationBtnSelector.toString())); + } + + // Hide keyboard. + uiDevice.pressBack(); + + // Set the text now. + UiObject2 textField = WidgetUtils.safeWait(uiDevice, + textFieldSelector, + DEFAULT_TIMEOUT_MS, + 3); + if (textField == null) { + throw new RuntimeException( + "Failed to find text field: " + textFieldSelector.toString()); + } + + + textField.setText(text); + } + + /** + * Activates the navigation button by simulating a key pressing event to enter '0'. + * + * @param uiDevice {@link UiDevice} object + * @param textFieldSelector {@link BySelector} for the text field + * @param navigationBtnSelector navigation button to activate + */ + private static void activateNavigationBtn(UiDevice uiDevice, + BySelector textFieldSelector, + BySelector navigationBtnSelector) throws Exception { + WidgetUtils.waitAndClick(uiDevice, textFieldSelector, DEFAULT_TIMEOUT_MS, 3); + + // Clicking the text field will bring up the keyboard and change the view hierachy of + // current screen; textField may become stale. Try to find it again before simulating + // the keyboard events. + SystemClock.sleep(KEYBOARD_START_TIME_MS); + if (WidgetUtils.safeWait(uiDevice, textFieldSelector, DEFAULT_TIMEOUT_MS, 3) == null) { + throw new RuntimeException( + "Failed to find text field: " + textFieldSelector.toString()); + } + + // Simulate an event to enter '0' to the text field, this will activate the navigate button. + if (!uiDevice.pressKeyCode(KeyEvent.KEYCODE_0)) { + throw new RuntimeException(String.format("Failed to enter 0 into the text field %s", + textFieldSelector.toString())); + } + + // Wait for the navigation button to be activated. + BySelector newNavigationBtnSelector = By.copy(navigationBtnSelector).enabled(true); + if (WidgetUtils.safeWait(uiDevice, + newNavigationBtnSelector, + DEFAULT_TIMEOUT_MS, + 3) == null) { + throw new RuntimeException(String.format("Failed to activate navigation button: %s", + navigationBtnSelector.toString())); + } + } +} |