aboutsummaryrefslogtreecommitdiff
path: root/libs/UiAutomatorLib/src/com/android/afwtest/uiautomator/utils/TextField.java
diff options
context:
space:
mode:
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.java158
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()));
+ }
+ }
+}