UiBot.java revision e53e85f6051d20cbd477bc25d446a41996411fab
1e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/* 2e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Copyright (C) 2015 The Android Open Source Project 3e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * 4e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License"); 5e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * you may not use this file except in compliance with the License. 6e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * You may obtain a copy of the License at 7e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * 8e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * http://www.apache.org/licenses/LICENSE-2.0 9e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * 10e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Unless required by applicable law or agreed to in writing, software 11e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS, 12e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * See the License for the specific language governing permissions and 14e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * limitations under the License. 15e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */ 16e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 17e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemepackage com.android.shell; 18e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 19e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.By; 20e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiDevice; 21e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiObject; 22e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiObjectNotFoundException; 23e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.UiSelector; 24e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.support.test.uiautomator.Until; 25e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport android.util.Log; 26e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemeimport static junit.framework.Assert.assertTrue; 27e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 28e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme/** 29e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * A helper class for UI-related testing tasks. 30e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */ 31e53e85f6051d20cbd477bc25d446a41996411fabFelipe Lemefinal class UiBot { 32e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 33e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme private static final String TAG = "UiBot"; 34e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme private static final String SYSTEMUI_PACKAGED = "com.android.systemui"; 35e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 36e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme private final UiDevice mDevice; 37e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme private final int mTimeout; 38e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 39e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme public UiBot(UiDevice device, int timeout) { 40e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme mDevice = device; 41e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme mTimeout = timeout; 42e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } 43e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 44e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme /** 45e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Opens the system notification and clicks a given notification. 46e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * 47e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * @param text Notificaton's text as displayed by the UI. 48e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */ 49e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme public void clickOnNotification(String text) { 50e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme boolean opened = mDevice.openNotification(); 51e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme Log.v(TAG, "openNotification(): " + opened); 52e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGED)), mTimeout); 53e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme assertTrue("could not get system ui (" + SYSTEMUI_PACKAGED + ")", gotIt); 54e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 55e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout); 56e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme assertTrue("object with text '(" + text + "') not visible yet", gotIt); 57e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 58e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme UiObject notification = getVisibleObject(text); 59e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 60e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme click(notification, "bug report notification"); 61e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } 62e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 63e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme /** 64e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Gets an object which is guaranteed to be present in the current UI.\ 65e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * 66e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * @param text Object's text as displayed by the UI. 67e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */ 68e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme public UiObject getVisibleObject(String text) { 69e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme UiObject uiObject = mDevice.findObject(new UiSelector().text(text)); 70e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme assertTrue("could not find object with text '(" + text + "')", uiObject.exists()); 71e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme return uiObject; 72e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } 73e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 74e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme /** 75e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Clicks on a UI element. 76e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * 77e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * @param uiObject UI element to be clicked. 78e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * @param description Elements's description used on logging statements. 79e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */ 80e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme public void click(UiObject uiObject, String description) { 81e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme try { 82e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme boolean clicked = uiObject.click(); 83e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // TODO: assertion below fails sometimes, even though the click succeeded, 84e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // (specially when clicking the "Just Once" button), so it's currently just logged. 85e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // assertTrue("could not click on object '" + description + "'", clicked); 86e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 87e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme Log.v(TAG, "onClick for " + description + ": " + clicked); 88e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } catch (UiObjectNotFoundException e) { 89e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme throw new IllegalStateException("exception when clicking on object '" + description 90e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme + "'", e); 91e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } 92e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } 93e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 94e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme /** 95e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * Chooses a given activity to handle an Intent, using the "Just Once" button. 96e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * 97e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * @param name name of the activity as displayed in the UI (typically the value set by 98e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme * {@code android:label} in the manifest). 99e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme */ 100e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // TODO: UI Automator should provide such logic. 101e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme public void chooseActivity(String name) { 102e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // First select activity if it's not the default option. 103e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme boolean gotIt = mDevice.wait(Until.hasObject(By.text(name)), mTimeout); 104e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // TODO: if the activity is indeed the default option, call above will timeout, which will 105e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // make the tests run slower. It might be better to change the logic to assume the default 106e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // first. 107e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme if (gotIt) { 108e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme Log.v(TAG, "Found activity " + name + ", it's not default action"); 109e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme UiObject activityChooser = getVisibleObject(name); 110e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme click(activityChooser, "activity chooser"); 111e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } else { 112e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme String text = String.format("Share with %s", name); 113e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme Log.v(TAG, "Didn't find activity " + name 114e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme + ", assuming it's the default action and search for '" + text + "'"); 115e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout); 116e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme assertTrue("did not find text '" + text + "'", gotIt); 117e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } 118e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 119e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme // Then clicks the "Just Once" button. 120e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme gotIt = mDevice 121e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme .wait(Until.hasObject(By.res("android", "button_once")), mTimeout); 122e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme assertTrue("'Just Once' button not visible yet", gotIt); 123e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 124e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme UiObject justOnce = mDevice 125e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme .findObject(new UiSelector().resourceId("android:id/button_once")); 126e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme assertTrue("'Just Once' button not found", justOnce.exists()); 127e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme 128e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme click(justOnce, "Just Once"); 129e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme } 130e53e85f6051d20cbd477bc25d446a41996411fabFelipe Leme} 131