blob: dad85f2c1badc0d00d9fc30d34ef6dd6045dded4 [file] [log] [blame]
/*
* 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.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()));
}
}
}