1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.shell; 18 19 import android.app.Instrumentation; 20 import android.app.StatusBarManager; 21 import android.support.test.uiautomator.By; 22 import android.support.test.uiautomator.UiDevice; 23 import android.support.test.uiautomator.UiObject; 24 import android.support.test.uiautomator.UiObjectNotFoundException; 25 import android.support.test.uiautomator.UiSelector; 26 import android.support.test.uiautomator.Until; 27 import android.util.Log; 28 29 import static junit.framework.Assert.assertFalse; 30 import static junit.framework.Assert.assertTrue; 31 32 /** 33 * A helper class for UI-related testing tasks. 34 */ 35 final class UiBot { 36 37 private static final String TAG = "UiBot"; 38 private static final String SYSTEMUI_PACKAGE = "com.android.systemui"; 39 40 private final Instrumentation mInstrumentation; 41 private final UiDevice mDevice; 42 private final int mTimeout; 43 UiBot(Instrumentation instrumentation, int timeout)44 public UiBot(Instrumentation instrumentation, int timeout) { 45 mInstrumentation = instrumentation; 46 mDevice = UiDevice.getInstance(instrumentation); 47 mTimeout = timeout; 48 } 49 50 /** 51 * Opens the system notification and gets a given notification. 52 * 53 * @param text Notificaton's text as displayed by the UI. 54 * @return notification object. 55 */ getNotification(String text)56 public UiObject getNotification(String text) { 57 boolean opened = mDevice.openNotification(); 58 Log.v(TAG, "openNotification(): " + opened); 59 boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGE)), mTimeout); 60 assertTrue("could not get system ui (" + SYSTEMUI_PACKAGE + ")", gotIt); 61 62 return getObject(text); 63 } 64 collapseStatusBar()65 public void collapseStatusBar() throws Exception { 66 // TODO: mDevice should provide such method.. 67 StatusBarManager sbm = 68 (StatusBarManager) mInstrumentation.getContext().getSystemService("statusbar"); 69 sbm.collapsePanels(); 70 } 71 72 /** 73 * Opens the system notification and clicks a given notification. 74 * 75 * @param text Notificaton's text as displayed by the UI. 76 */ clickOnNotification(String text)77 public void clickOnNotification(String text) { 78 UiObject notification = getNotification(text); 79 click(notification, "bug report notification"); 80 } 81 82 /** 83 * Gets an object that might not yet be available in current UI. 84 * 85 * @param text Object's text as displayed by the UI. 86 */ getObject(String text)87 public UiObject getObject(String text) { 88 boolean gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout); 89 assertTrue("object with text '(" + text + "') not visible yet", gotIt); 90 return getVisibleObject(text); 91 } 92 93 /** 94 * Gets an object that might not yet be available in current UI. 95 * 96 * @param id Object's fully-qualified resource id (like {@code android:id/button1}) 97 */ getObjectById(String id)98 public UiObject getObjectById(String id) { 99 boolean gotIt = mDevice.wait(Until.hasObject(By.res(id)), mTimeout); 100 assertTrue("object with id '(" + id + "') not visible yet", gotIt); 101 return getVisibleObjectById(id); 102 } 103 104 /** 105 * Gets an object which is guaranteed to be present in the current UI. 106 * 107 * @param text Object's text as displayed by the UI. 108 */ getVisibleObject(String text)109 public UiObject getVisibleObject(String text) { 110 UiObject uiObject = mDevice.findObject(new UiSelector().text(text)); 111 assertTrue("could not find object with text '" + text + "'", uiObject.exists()); 112 return uiObject; 113 } 114 115 /** 116 * Gets an object which is guaranteed to be present in the current UI. 117 * 118 * @param text Object's text as displayed by the UI. 119 */ getVisibleObjectById(String id)120 public UiObject getVisibleObjectById(String id) { 121 UiObject uiObject = mDevice.findObject(new UiSelector().resourceId(id)); 122 assertTrue("could not find object with id '" + id+ "'", uiObject.exists()); 123 return uiObject; 124 } 125 126 /** 127 * Asserts an object is not visible. 128 */ assertNotVisibleById(String id)129 public void assertNotVisibleById(String id) { 130 // TODO: not working when the bugreport dialog is shown, it hangs until the dialog is 131 // dismissed and hence always work. 132 boolean hasIt = mDevice.hasObject(By.res(id)); 133 assertFalse("should not have found object with id '" + id+ "'", hasIt); 134 } 135 136 137 /** 138 * Clicks on a UI element. 139 * 140 * @param uiObject UI element to be clicked. 141 * @param description Elements's description used on logging statements. 142 */ click(UiObject uiObject, String description)143 public void click(UiObject uiObject, String description) { 144 try { 145 boolean clicked = uiObject.click(); 146 // TODO: assertion below fails sometimes, even though the click succeeded, 147 // (specially when clicking the "Just Once" button), so it's currently just logged. 148 // assertTrue("could not click on object '" + description + "'", clicked); 149 150 Log.v(TAG, "onClick for " + description + ": " + clicked); 151 } catch (UiObjectNotFoundException e) { 152 throw new IllegalStateException("exception when clicking on object '" + description 153 + "'", e); 154 } 155 } 156 157 /** 158 * Chooses a given activity to handle an Intent. 159 * 160 * @param name name of the activity as displayed in the UI (typically the value set by 161 * {@code android:label} in the manifest). 162 */ chooseActivity(String name)163 public void chooseActivity(String name) { 164 // It uses an intent chooser now, so just getting the activity by text is enough... 165 UiObject activity = getObject(name); 166 click(activity, name); 167 } 168 pressBack()169 public void pressBack() { 170 mDevice.pressBack(); 171 } 172 turnScreenOn()173 public void turnScreenOn() throws Exception { 174 mDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP"); 175 mDevice.executeShellCommand("wm dismiss-keyguard"); 176 } 177 178 } 179