Home | History | Annotate | Download | only in bots
      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.documentsui.bots;
     18 
     19 import static junit.framework.Assert.assertEquals;
     20 import static junit.framework.Assert.assertFalse;
     21 import static junit.framework.Assert.assertNotNull;
     22 import static junit.framework.Assert.assertTrue;
     23 
     24 import android.content.Context;
     25 import android.support.test.uiautomator.By;
     26 import android.support.test.uiautomator.UiDevice;
     27 import android.support.test.uiautomator.UiObject;
     28 import android.support.test.uiautomator.UiObject2;
     29 import android.support.test.uiautomator.UiObjectNotFoundException;
     30 import android.support.test.uiautomator.UiSelector;
     31 import android.support.test.uiautomator.Until;
     32 
     33 import com.android.documentsui.R;
     34 
     35 import java.util.Iterator;
     36 import java.util.List;
     37 
     38 /**
     39  * A test helper class that provides support for controlling DocumentsUI activities
     40  * programmatically, and making assertions against the state of the UI.
     41  *
     42  * <p>Support for working directly with Roots and Directory view can be found
     43  * in the respective bots.
     44  */
     45 public class UiBot extends BaseBot {
     46     public static final String TARGET_PKG = "com.android.documentsui";
     47     private static final String LAUNCHER_PKG = "com.android.launcher";
     48 
     49     public UiBot(UiDevice device, Context context, int timeout) {
     50         super(device, context, timeout);
     51     }
     52 
     53     public void assertWindowTitle(String expected) {
     54         // Turns out the title field on a window does not have
     55         // an id associated with it at runtime (which confuses the hell out of me)
     56         // In code we address this via "android.R.id.title".
     57         UiObject2 o = find(By.text(expected));
     58         // It's a bit of a conceit that we then *assert* that the title
     59         // is the value that we used to identify the UiObject2.
     60         // If the preceeding lookup fails, this'll choke with an NPE.
     61         // But given the issue described in the comment above, we're
     62         // going to do it anyway. Because we shouldn't be looking up
     63         // the uiobject by it's expected content :|
     64         assertEquals(expected, o.getText());
     65     }
     66 
     67     public void assertMenuEnabled(int id, boolean enabled) {
     68         UiObject2 menu= findMenuWithName(mContext.getString(id));
     69         assertNotNull(menu);
     70         assertEquals(enabled, menu.isEnabled());
     71     }
     72 
     73     public void assertSearchTextField(boolean isFocused, String query)
     74             throws UiObjectNotFoundException {
     75         UiObject textField = findSearchViewTextField();
     76         UiObject searchIcon = findSearchViewIcon();
     77 
     78         assertFalse(searchIcon.exists());
     79         assertTrue(textField.exists());
     80         assertEquals(isFocused, textField.isFocused());
     81         if(query != null) {
     82             assertEquals(query, textField.getText());
     83         }
     84     }
     85 
     86     public void assertSearchTextFiledAndIcon(boolean searchTextFieldExists, boolean searchIconExists) {
     87         assertEquals(searchTextFieldExists, findSearchViewTextField().exists());
     88         assertEquals(searchIconExists, findSearchViewIcon().exists());
     89     }
     90 
     91     public void assertInActionMode(boolean inActionMode) {
     92         UiObject actionModeBar = findActionModeBar();
     93         assertEquals(inActionMode, actionModeBar.exists());
     94     }
     95 
     96     public void openSearchView() throws UiObjectNotFoundException {
     97         UiObject searchView = findSearchView();
     98         searchView.click();
     99         assertTrue(searchView.exists());
    100     }
    101 
    102     public void setSearchQuery(String query) throws UiObjectNotFoundException {
    103         UiObject searchView = findSearchView();
    104         assertTrue(searchView.exists());
    105         UiObject searchTextField = findSearchViewTextField();
    106         searchTextField.setText(query);
    107         assertSearchTextField(true, query);
    108     }
    109 
    110     public UiObject openOverflowMenu() throws UiObjectNotFoundException {
    111         UiObject obj = findMenuMoreOptions();
    112         obj.click();
    113         mDevice.waitForIdle(mTimeout);
    114         return obj;
    115     }
    116 
    117     public void setDialogText(String text) throws UiObjectNotFoundException {
    118         findDialogEditText().setText(text);
    119     }
    120 
    121     void switchViewMode() {
    122         UiObject2 mode = menuGridMode();
    123         if (mode != null) {
    124             mode.click();
    125         } else {
    126             menuListMode().click();
    127         }
    128     }
    129 
    130     UiObject2 menuGridMode() {
    131         // Note that we're using By.desc rather than By.res, because of b/25285770
    132         return find(By.desc("Grid view"));
    133     }
    134 
    135         UiObject2 menuListMode() {
    136         // Note that we're using By.desc rather than By.res, because of b/25285770
    137         return find(By.desc("List view"));
    138     }
    139 
    140     public UiObject2 menuDelete() {
    141         return find(By.res("com.android.documentsui:id/menu_delete"));
    142     }
    143 
    144     public UiObject2 menuShare() {
    145         return find(By.res("com.android.documentsui:id/menu_share"));
    146     }
    147 
    148     public UiObject2 menuRename() {
    149         return findMenuWithName(mContext.getString(R.string.menu_rename));
    150     }
    151 
    152     public UiObject2 menuNewFolder() {
    153         return findMenuWithName(mContext.getString(R.string.menu_create_dir));
    154     }
    155 
    156     UiObject findSearchView() {
    157         return findObject("com.android.documentsui:id/menu_search");
    158     }
    159 
    160     UiObject findSearchViewTextField() {
    161         return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
    162     }
    163 
    164     UiObject findSearchViewIcon() {
    165         return mContext.getResources().getBoolean(R.bool.full_bar_search_view)
    166                 ? findObject("com.android.documentsui:id/menu_search")
    167                 : findObject("com.android.documentsui:id/menu_search", "android:id/search_button");
    168     }
    169 
    170     UiObject findActionModeBar() {
    171         return findObject("android:id/action_mode_bar");
    172     }
    173 
    174     public UiObject findDialogEditText() {
    175         return findObject("android:id/content", "android:id/text1");
    176     }
    177 
    178     public UiObject findDownloadRetryDialog() {
    179         UiSelector selector = new UiSelector().text("Couldn't download");
    180         UiObject title = mDevice.findObject(selector);
    181         title.waitForExists(mTimeout);
    182         return title;
    183     }
    184 
    185     public UiObject findDialogOkButton() {
    186         UiObject object = findObject("android:id/content", "android:id/button1");
    187         object.waitForExists(mTimeout);
    188         return object;
    189     }
    190 
    191     public UiObject findDialogCancelButton() {
    192         UiObject object = findObject("android:id/content", "android:id/button2");
    193         object.waitForExists(mTimeout);
    194         return object;
    195     }
    196 
    197     UiObject findMenuLabelWithName(String label) {
    198         UiSelector selector = new UiSelector().text(label);
    199         return mDevice.findObject(selector);
    200     }
    201 
    202     UiObject2 findMenuWithName(String label) {
    203         List<UiObject2> menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout"));
    204         Iterator<UiObject2> it = menuItems.iterator();
    205 
    206         UiObject2 menuItem = null;
    207         while(it.hasNext()) {
    208             menuItem = it.next();
    209             UiObject2 text = menuItem.findObject(By.text(label));
    210             if(text != null) {
    211                 break;
    212             }
    213         }
    214         return menuItem;
    215     }
    216 
    217     UiObject findMenuMoreOptions() {
    218         UiSelector selector = new UiSelector().className("android.widget.ImageButton")
    219                 .descriptionContains("More options");
    220         //TODO: use the system string ? android.R.string.action_menu_overflow_description
    221         return mDevice.findObject(selector);
    222     }
    223 
    224     public void pressKey(int keyCode) {
    225         mDevice.pressKeyCode(keyCode);
    226     }
    227 }
    228