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.typeText;
21 import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
22 import static android.support.test.espresso.matcher.ViewMatchers.isClickable;
23 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
24 import static android.support.test.espresso.matcher.ViewMatchers.withId;
25 import static junit.framework.Assert.assertEquals;
26 import static junit.framework.Assert.assertFalse;
27 import static junit.framework.Assert.assertTrue;
28 import static org.hamcrest.CoreMatchers.allOf;
29 import static org.hamcrest.CoreMatchers.anyOf;
30 
31 import android.content.Context;
32 import android.support.test.uiautomator.UiDevice;
33 import android.support.test.uiautomator.UiObject;
34 import android.support.test.uiautomator.UiObjectNotFoundException;
35 import android.support.v7.recyclerview.R;
36 import android.view.View;
37 
38 import org.hamcrest.Matcher;
39 
40 /**
41  * A test helper class that provides support for controlling the search UI
42  * programmatically, and making assertions against the state of the UI.
43  * <p>
44  * Support for working directly with Roots and Directory view can be found in the respective bots.
45  */
46 public class SearchBot extends Bots.BaseBot {
47 
48     public static final String TARGET_PKG = "com.android.documentsui";
49 
50     // Dumb search layout changes substantially between Ryu and Angler.
51     @SuppressWarnings("unchecked")
52     private static final Matcher<View> SEARCH_WIDGET = allOf(
53             withId(R.id.menu_search),
54             anyOf(isClickable(), hasDescendant(isClickable())));
55 
56     // Note that input is visible when the clicky button is not
57     // present. So to clearly qualify the two...we explicitly
58     // require this input be not clickable.
59     @SuppressWarnings("unchecked")
60     private static final Matcher<View> SEARCH_INPUT = allOf(
61             withId(R.id.menu_search),
62             isDisplayed());
63 
SearchBot(UiDevice device, Context context, int timeout)64     public SearchBot(UiDevice device, Context context, int timeout) {
65         super(device, context, timeout);
66     }
67 
clickIcon()68     public void clickIcon() throws UiObjectNotFoundException {
69         UiObject searchView = findSearchView();
70         searchView.click();
71         assertTrue(searchView.exists());
72     }
73 
setInputText(String query)74     public void setInputText(String query) throws UiObjectNotFoundException {
75         onView(SEARCH_INPUT).perform(typeText(query));
76     }
77 
assertIconVisible(boolean visible)78     public void assertIconVisible(boolean visible) {
79         if (visible) {
80             assertTrue(
81                     "Search icon should be visible.",
82                     Matchers.present(SEARCH_WIDGET));
83         } else {
84             assertFalse(
85                     "Search icon should not be visible.",
86                     Matchers.present(SEARCH_WIDGET));
87         }
88     }
89 
assertInputEquals(String query)90     public void assertInputEquals(String query)
91             throws UiObjectNotFoundException {
92         UiObject textField = findSearchViewTextField();
93 
94         assertTrue(textField.exists());
95         assertEquals(query, textField.getText());
96     }
97 
assertInputFocused(boolean focused)98     public void assertInputFocused(boolean focused)
99             throws UiObjectNotFoundException {
100         UiObject textField = findSearchViewTextField();
101 
102         assertTrue(textField.exists());
103         assertEquals(focused, textField.isFocused());
104     }
105 
assertInputExists(boolean exists)106     public void assertInputExists(boolean exists)
107             throws UiObjectNotFoundException {
108         assertEquals(exists, findSearchViewTextField().exists());
109     }
110 
findSearchView()111     private UiObject findSearchView() {
112         return findObject("com.android.documentsui:id/menu_search");
113     }
114 
findSearchViewTextField()115     private UiObject findSearchViewTextField() {
116         return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
117     }
118 
findSearchViewIcon()119     private UiObject findSearchViewIcon() {
120         return mContext.getResources().getBoolean(R.bool.full_bar_search_view)
121                 ? findObject("com.android.documentsui:id/menu_search")
122                 : findObject("com.android.documentsui:id/menu_search", "android:id/search_button");
123     }
124 }
125