blob: 30f16928ba52e894d915a84e2ad75414fd61a439 [file] [log] [blame]
Felipe Lemee53e85f2015-11-17 17:37:53 -08001/*
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
17package com.android.shell;
18
19import android.support.test.uiautomator.By;
20import android.support.test.uiautomator.UiDevice;
21import android.support.test.uiautomator.UiObject;
22import android.support.test.uiautomator.UiObjectNotFoundException;
Felipe Lemea4131432015-12-03 11:09:53 -080023import android.support.test.uiautomator.UiScrollable;
Felipe Lemee53e85f2015-11-17 17:37:53 -080024import android.support.test.uiautomator.UiSelector;
25import android.support.test.uiautomator.Until;
26import android.util.Log;
27import static junit.framework.Assert.assertTrue;
28
29/**
30 * A helper class for UI-related testing tasks.
31 */
32final class UiBot {
33
34 private static final String TAG = "UiBot";
Felipe Leme3fc44b92016-03-21 17:34:21 -070035 private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
Felipe Lemee53e85f2015-11-17 17:37:53 -080036
37 private final UiDevice mDevice;
38 private final int mTimeout;
39
40 public UiBot(UiDevice device, int timeout) {
41 mDevice = device;
42 mTimeout = timeout;
43 }
44
45 /**
Felipe Leme69c02922015-11-24 17:48:05 -080046 * Opens the system notification and gets a given notification.
Felipe Lemee53e85f2015-11-17 17:37:53 -080047 *
48 * @param text Notificaton's text as displayed by the UI.
Felipe Leme69c02922015-11-24 17:48:05 -080049 * @return notification object.
Felipe Lemee53e85f2015-11-17 17:37:53 -080050 */
Felipe Leme69c02922015-11-24 17:48:05 -080051 public UiObject getNotification(String text) {
Felipe Lemee53e85f2015-11-17 17:37:53 -080052 boolean opened = mDevice.openNotification();
53 Log.v(TAG, "openNotification(): " + opened);
Felipe Leme3fc44b92016-03-21 17:34:21 -070054 boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGE)), mTimeout);
55 assertTrue("could not get system ui (" + SYSTEMUI_PACKAGE + ")", gotIt);
Felipe Lemee53e85f2015-11-17 17:37:53 -080056
Felipe Leme69c02922015-11-24 17:48:05 -080057 return getObject(text);
58 }
Felipe Lemee53e85f2015-11-17 17:37:53 -080059
Felipe Leme69c02922015-11-24 17:48:05 -080060 /**
61 * Opens the system notification and clicks a given notification.
62 *
63 * @param text Notificaton's text as displayed by the UI.
64 */
65 public void clickOnNotification(String text) {
66 UiObject notification = getNotification(text);
Felipe Lemee53e85f2015-11-17 17:37:53 -080067 click(notification, "bug report notification");
68 }
69
70 /**
Felipe Leme69c02922015-11-24 17:48:05 -080071 * Gets an object that might not yet be available in current UI.
72 *
73 * @param text Object's text as displayed by the UI.
74 */
75 public UiObject getObject(String text) {
76 boolean gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout);
77 assertTrue("object with text '(" + text + "') not visible yet", gotIt);
78 return getVisibleObject(text);
79 }
80
81 /**
Felipe Lemebc73ffc2015-12-11 15:07:14 -080082 * Gets an object that might not yet be available in current UI.
83 *
84 * @param id Object's fully-qualified resource id (like {@code android:id/button1})
85 */
86 public UiObject getObjectById(String id) {
87 boolean gotIt = mDevice.wait(Until.hasObject(By.res(id)), mTimeout);
88 assertTrue("object with id '(" + id + "') not visible yet", gotIt);
89 return getVisibleObjectById(id);
90 }
91
92 /**
Felipe Leme69c02922015-11-24 17:48:05 -080093 * Gets an object which is guaranteed to be present in the current UI.
Felipe Lemee53e85f2015-11-17 17:37:53 -080094 *
95 * @param text Object's text as displayed by the UI.
96 */
97 public UiObject getVisibleObject(String text) {
98 UiObject uiObject = mDevice.findObject(new UiSelector().text(text));
Felipe Leme69c02922015-11-24 17:48:05 -080099 assertTrue("could not find object with text '" + text + "'", uiObject.exists());
Felipe Lemee53e85f2015-11-17 17:37:53 -0800100 return uiObject;
101 }
102
103 /**
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800104 * Gets an object which is guaranteed to be present in the current UI.
105 *
106 * @param text Object's text as displayed by the UI.
107 */
108 public UiObject getVisibleObjectById(String id) {
109 UiObject uiObject = mDevice.findObject(new UiSelector().resourceId(id));
110 assertTrue("could not find object with id '" + id+ "'", uiObject.exists());
111 return uiObject;
112 }
113
114
115 /**
Felipe Lemee53e85f2015-11-17 17:37:53 -0800116 * Clicks on a UI element.
117 *
118 * @param uiObject UI element to be clicked.
119 * @param description Elements's description used on logging statements.
120 */
121 public void click(UiObject uiObject, String description) {
122 try {
123 boolean clicked = uiObject.click();
124 // TODO: assertion below fails sometimes, even though the click succeeded,
125 // (specially when clicking the "Just Once" button), so it's currently just logged.
126 // assertTrue("could not click on object '" + description + "'", clicked);
127
128 Log.v(TAG, "onClick for " + description + ": " + clicked);
129 } catch (UiObjectNotFoundException e) {
130 throw new IllegalStateException("exception when clicking on object '" + description
131 + "'", e);
132 }
133 }
134
135 /**
136 * Chooses a given activity to handle an Intent, using the "Just Once" button.
137 *
138 * @param name name of the activity as displayed in the UI (typically the value set by
139 * {@code android:label} in the manifest).
140 */
141 // TODO: UI Automator should provide such logic.
142 public void chooseActivity(String name) {
Felipe Lemea4131432015-12-03 11:09:53 -0800143 // First check if the activity is the default option.
Felipe Lemeba477932015-12-09 11:04:59 -0800144 String shareText = "Share with " + name;
145 Log.v(TAG, "Waiting for ActivityChooser text: '" + shareText + "'");
Felipe Lemea4131432015-12-03 11:09:53 -0800146 boolean gotIt = mDevice.wait(Until.hasObject(By.text(shareText)), mTimeout);
Felipe Leme3fb3d882016-04-15 11:32:53 -0700147 boolean justOnceHack = false;
Felipe Lemea4131432015-12-03 11:09:53 -0800148
Felipe Lemee53e85f2015-11-17 17:37:53 -0800149 if (gotIt) {
Felipe Lemea4131432015-12-03 11:09:53 -0800150 Log.v(TAG, "Found activity " + name + ", it's the default action");
Felipe Leme3fb3d882016-04-15 11:32:53 -0700151 clickJustOnce();
Felipe Lemee53e85f2015-11-17 17:37:53 -0800152 } else {
Felipe Lemea4131432015-12-03 11:09:53 -0800153 // Since it's not, need to find it in the scrollable list...
154 Log.v(TAG, "Activity " + name + " is not default action");
155 UiScrollable activitiesList = new UiScrollable(new UiSelector().scrollable(true));
Felipe Lemea4131432015-12-03 11:09:53 -0800156 try {
157 activitiesList.scrollForward();
Felipe Lemea4131432015-12-03 11:09:53 -0800158 } catch (UiObjectNotFoundException e) {
Felipe Leme3fb3d882016-04-15 11:32:53 -0700159 // TODO: for some paranormal issue, the first time a test is run the scrollable
160 // activity list is displayed but calling scrollForwad() (or even isScrollable())
161 // throws a "UiObjectNotFoundException: UiSelector[SCROLLABLE=true]" exception
162 justOnceHack = true;
163 Log.d(TAG, "could not scroll forward", e);
Felipe Lemea4131432015-12-03 11:09:53 -0800164 }
Felipe Leme3fb3d882016-04-15 11:32:53 -0700165 UiObject activity = getVisibleObject(name);
Felipe Lemea4131432015-12-03 11:09:53 -0800166 // ... then select it.
167 click(activity, name);
Felipe Leme3fb3d882016-04-15 11:32:53 -0700168 if (justOnceHack) {
169 clickJustOnce();
170 }
Felipe Lemee53e85f2015-11-17 17:37:53 -0800171 }
Felipe Lemee53e85f2015-11-17 17:37:53 -0800172 }
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800173
Felipe Leme3fb3d882016-04-15 11:32:53 -0700174 private void clickJustOnce() {
175 boolean gotIt = mDevice.wait(Until.hasObject(By.res("android", "button_once")), mTimeout);
176 assertTrue("'Just Once' button not visible yet", gotIt);
177
178 UiObject justOnce = mDevice
179 .findObject(new UiSelector().resourceId("android:id/button_once"));
180 assertTrue("'Just Once' button not found", justOnce.exists());
181
182 click(justOnce, "Just Once");
183 }
184
Felipe Lemebc73ffc2015-12-11 15:07:14 -0800185 public void pressBack() {
186 mDevice.pressBack();
187 }
Felipe Lemee53e85f2015-11-17 17:37:53 -0800188}