Home | History | Annotate | Download | only in shell
      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 
     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      */
     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 
     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      */
     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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    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      */
    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 
    169     public void pressBack() {
    170         mDevice.pressBack();
    171     }
    172 
    173     public void turnScreenOn() throws Exception {
    174         mDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
    175         mDevice.executeShellCommand("wm dismiss-keyguard");
    176     }
    177 
    178 }
    179