blob: add04b2cbe4fe4904069dead43a0fd49d911a5d9 [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 android.platform.test.helpers;
import android.app.Instrumentation;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.SystemClock;
import android.platform.test.helpers.exceptions.UnknownUiException;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.Until;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.util.Log;
import android.widget.EditText;
public class PlayStoreHelperImpl extends AbstractPlayStoreHelper {
private static final String LOG_TAG = PlayStoreHelperImpl.class.getSimpleName();
private static final String UI_PACKAGE = "com.android.vending";
private static final long LONG_TOS_DIALOG_WAIT = 20000;
private static final long LOAD_RESULT_TRANSITION = 10000;
private static final long INSTALL_DELAY = 5000;
public PlayStoreHelperImpl(Instrumentation instr) {
super(instr);
}
/**
* {@inheritDoc}
*/
@Override
public String getPackage() {
return "com.android.vending";
}
/**
* {@inheritDoc}
*/
@Override
public String getLauncherName() {
return "Play Store";
}
/**
* {@inheritDoc}
*/
@Override
public void dismissInitialDialogs() {
if (!isAppInForeground()) {
throw new IllegalStateException("The Play Store app is not in the foreground.");
}
// Dismiss the ToS dialog by pressing accept
if (mDevice.wait(Until.hasObject(
By.textContains("Google Play Terms of Service")), LONG_TOS_DIALOG_WAIT)) {
mDevice.findObject(getPositiveButtonSelector()).click();
boolean home = mDevice.wait(Until.hasObject(getSearchBoxSelector()), 10000);
if (!home) {
throw new UnknownUiException("Failed to reach the home screen.");
}
} else {
throw new UnknownUiException("Unable to find ToS");
}
}
/**
* {@inheritDoc}
*/
@Override
public void doSearch(String query) {
if (!isAppInForeground()) {
throw new IllegalStateException("The Play Store app is not in the foreground.");
}
// Scroll up or press back until searching is available, or fail
UiObject2 search = null;
for (int retries = 5; retries > 0; retries--) {
// Search for the search box
search = mDevice.findObject(getSearchBoxSelector());
if (search != null) {
break;
}
// Search for the search button
search = mDevice.findObject(getSearchButtonSelector());
if (search != null) {
break;
}
// Scroll up or back out
if (!scrollPage(Direction.UP, 100.0f)) {
mDevice.pressBack();
}
}
if (search == null) {
throw new UnknownUiException("Failed to find a search method.");
}
search.click();
// After pressing, the search element becomes the edit text box
UiObject2 edit = mDevice.wait(
Until.findObject(By.clazz(EditText.class)), 5000);
if (edit == null) {
throw new UnknownUiException("Failed to find an edit text.");
}
edit.setText(query);
mDevice.pressEnter();
// Validate the end criteria that the search list is visible
if (!mDevice.wait(Until.hasObject(getSearchResultSelector()), 5000)) {
throw new UnknownUiException("Failed to find the search results.");
}
}
/**
* {@inheritDoc}
*/
@Override
public void selectFirstResult() {
if (!mDevice.hasObject(getSearchResultSelector())) {
throw new IllegalStateException("No available search result list.");
}
UiObject2 result = mDevice.findObject(By.res(UI_PACKAGE, "play_card"));
if (result == null) {
throw new UnknownUiException("Failed to find a search result card.");
}
result.click();
if (!mDevice.wait(Until.hasObject(getAppTitleSelector()), LOAD_RESULT_TRANSITION)) {
throw new UnknownUiException("Failed to find the app page open.");
}
}
/**
* {@inheritDoc}
*/
@Override
public void installApp() {
// #isAppInstalled also verifies that this is an app page
if (isAppInstalled()) {
throw new IllegalStateException("This app is already installed.");
}
UiObject2 install = mDevice.findObject(getInstallButtonSelector());
if (install == null) {
throw new UnknownUiException("Could not find an install button.");
}
install.click();
// Search for the Android 6.0 permission dialog
if (mDevice.wait(Until.hasObject(getAndroid6DialogSelector()), 2500)) {
mDevice.findObject(getPositiveButtonSelector()).click();
mDevice.waitForIdle();
} else {
// If the install button is present, then downloading failed
if (mDevice.wait(Until.findObject(
getInstallButtonSelector()), INSTALL_DELAY) != null) {
throw new UnknownUiException("Did not detect that the installation started.");
}
}
}
private boolean scrollPage(Direction dir, float value) {
UiObject2 scroller = mDevice.findObject(By.res(UI_PACKAGE, "recycler_view"));
if (scroller == null) {
scroller = mDevice.findObject(By.res(UI_PACKAGE, "viewpager"));
}
if (scroller != null) {
return scroller.scroll(dir, value);
} else {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAppInstalled() {
if (!isAppPage()) {
throw new IllegalStateException("Play Store was not on the app's install page.");
}
return (mDevice.findObject(getInstallButtonSelector()) == null);
}
private boolean isAppPage () {
// Warning: this can fail if the page is scrolled down
return mDevice.hasObject(getAppTitleSelector());
}
private BySelector getPositiveButtonSelector() {
return By.res(UI_PACKAGE, "positive_button");
}
private BySelector getSearchBoxSelector() {
return By.res(UI_PACKAGE, "search_box_idle_text");
}
private BySelector getSearchButtonSelector() {
return By.res(UI_PACKAGE, "search_button");
}
private BySelector getSearchResultSelector() {
return By.res(UI_PACKAGE, "search_results_list");
}
private BySelector getAppTitleSelector() {
return By.res(UI_PACKAGE, "title_background");
}
private BySelector getInstallButtonSelector() {
return By.res(UI_PACKAGE, "buy_button");
}
private BySelector getAndroid6DialogSelector() {
return By.res(UI_PACKAGE, "optional_permissions_help_screen");
}
}