Home | History | Annotate | Download | only in bots
      1 /*
      2  * Copyright (C) 2016 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 android.support.test.espresso.Espresso.onView;
     20 import static android.support.test.espresso.action.ViewActions.click;
     21 import static android.support.test.espresso.assertion.ViewAssertions.matches;
     22 import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
     23 import static android.support.test.espresso.matcher.ViewMatchers.withId;
     24 import static android.support.test.espresso.matcher.ViewMatchers.withText;
     25 import static org.hamcrest.CoreMatchers.allOf;
     26 import static org.hamcrest.CoreMatchers.anyOf;
     27 import static org.hamcrest.CoreMatchers.is;
     28 
     29 import android.content.Context;
     30 import android.support.test.espresso.ViewInteraction;
     31 import android.support.test.espresso.matcher.BoundedMatcher;
     32 import android.support.test.uiautomator.UiDevice;
     33 import android.support.test.uiautomator.UiObjectNotFoundException;
     34 import android.view.View;
     35 
     36 import com.android.documentsui.DragOverTextView;
     37 import com.android.documentsui.DropdownBreadcrumb;
     38 import com.android.documentsui.R;
     39 import com.android.documentsui.base.DocumentInfo;
     40 
     41 import junit.framework.Assert;
     42 
     43 import org.hamcrest.Description;
     44 import org.hamcrest.Matcher;
     45 
     46 import java.util.ArrayList;
     47 import java.util.Arrays;
     48 import java.util.List;
     49 import java.util.function.Predicate;
     50 
     51 /**
     52  * A test helper class that provides support for controlling the UI Breadcrumb
     53  * programmatically, and making assertions against the state of the UI.
     54  * <p>
     55  * Support for working directly with Roots and Directory view can be found in the respective bots.
     56  */
     57 public class BreadBot extends Bots.BaseBot {
     58 
     59     public static final String TARGET_PKG = "com.android.documentsui";
     60 
     61     private static final Matcher<View> DROPDOWN_BREADCRUMB = withId(
     62             R.id.dropdown_breadcrumb);
     63 
     64     private static final Matcher<View> HORIZONTAL_BREADCRUMB = withId(
     65             R.id.horizontal_breadcrumb);
     66 
     67     // When any 'ol breadcrumb will do. Could be dropdown or horizontal.
     68     @SuppressWarnings("unchecked")
     69     private static final Matcher<View> BREADCRUMB = anyOf(
     70             DROPDOWN_BREADCRUMB, HORIZONTAL_BREADCRUMB);
     71 
     72     private UiBot mMain;
     73 
     74     public BreadBot(
     75             UiDevice device, Context context, int timeout, UiBot main) {
     76         super(device, context, timeout);
     77         mMain = main;
     78     }
     79 
     80     public void assertTitle(String expected) {
     81         // There is no discrete title part on the horizontal breadcrumb...
     82         // so we only test on dropdown.
     83         if (mMain.inDrawerLayout()) {
     84             Matcher<Object> titleMatcher = dropdownTitleMatcher(expected);
     85             onView(BREADCRUMB)
     86                     .check(matches(titleMatcher));
     87         }
     88     }
     89 
     90     /**
     91      * Reveals the bread crumb if it was hidden. This will likely be the case
     92      * when the app is in drawer mode.
     93      */
     94     public void revealAsNeeded() throws Exception {
     95         if (mMain.inDrawerLayout()) {
     96             onView(DROPDOWN_BREADCRUMB).perform(click());
     97         }
     98     }
     99 
    100     public void clickItem(String label) throws UiObjectNotFoundException {
    101         if (mMain.inFixedLayout()) {
    102             findHorizontalEntry(label).perform(click());
    103         } else {
    104             mMain.findMenuWithName(label).click();
    105         }
    106     }
    107 
    108     public void assertItemsPresent(String... items) {
    109         Predicate<String> checker = mMain.inFixedLayout()
    110                     ? this::hasHorizontalEntry
    111                     : mMain::hasMenuWithName;
    112 
    113         assertItemsPresent(items, checker);
    114     }
    115 
    116     public void assertItemsPresent(String[] items, Predicate<String> predicate) {
    117         List<String> absent = new ArrayList<>();
    118         for (String item : items) {
    119             if (!predicate.test(item)) {
    120                 absent.add(item);
    121             }
    122         }
    123         if (!absent.isEmpty()) {
    124             Assert.fail("Expected iteams " + Arrays.asList(items)
    125                     + ", but missing " + absent);
    126         }
    127     }
    128 
    129     public boolean hasHorizontalEntry(String label) {
    130         return Matchers.present(findHorizontalEntry(label), withText(label));
    131     }
    132 
    133     @SuppressWarnings("unchecked")
    134     public ViewInteraction findHorizontalEntry(String label) {
    135         return onView(allOf(isAssignableFrom(DragOverTextView.class), withText(label)));
    136     }
    137 
    138     private static Matcher<Object> dropdownTitleMatcher(String expected) {
    139         final Matcher<String> textMatcher = is(expected);
    140         return new BoundedMatcher<Object, DropdownBreadcrumb>(DropdownBreadcrumb.class) {
    141             @Override
    142             public boolean matchesSafely(DropdownBreadcrumb breadcrumb) {
    143                 DocumentInfo selectedDoc = (DocumentInfo) breadcrumb.getSelectedItem();
    144                 return textMatcher.matches(selectedDoc.displayName);
    145             }
    146 
    147             @Override
    148             public void describeTo(Description description) {
    149                 description.appendText("with breadcrumb title: ");
    150                 textMatcher.describeTo(description);
    151             }
    152         };
    153     }
    154 }
    155