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
17package com.android.documentsui.bots;
18
19import static android.support.test.espresso.Espresso.onView;
20import static android.support.test.espresso.action.ViewActions.typeText;
21import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
22import static android.support.test.espresso.matcher.ViewMatchers.isClickable;
23import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
24import static android.support.test.espresso.matcher.ViewMatchers.withId;
25import static junit.framework.Assert.assertEquals;
26import static junit.framework.Assert.assertFalse;
27import static junit.framework.Assert.assertTrue;
28import static org.hamcrest.CoreMatchers.allOf;
29import static org.hamcrest.CoreMatchers.anyOf;
30
31import android.content.Context;
32import android.support.test.uiautomator.UiDevice;
33import android.support.test.uiautomator.UiObject;
34import android.support.test.uiautomator.UiObjectNotFoundException;
35import android.support.v7.recyclerview.R;
36import android.view.View;
37
38import 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 */
46public 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
64    public SearchBot(UiDevice device, Context context, int timeout) {
65        super(device, context, timeout);
66    }
67
68    public void clickIcon() throws UiObjectNotFoundException {
69        UiObject searchView = findSearchView();
70        searchView.click();
71        assertTrue(searchView.exists());
72    }
73
74    public void setInputText(String query) throws UiObjectNotFoundException {
75        onView(SEARCH_INPUT).perform(typeText(query));
76    }
77
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
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
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
106    public void assertInputExists(boolean exists)
107            throws UiObjectNotFoundException {
108        assertEquals(exists, findSearchViewTextField().exists());
109    }
110
111    private UiObject findSearchView() {
112        return findObject("com.android.documentsui:id/menu_search");
113    }
114
115    private UiObject findSearchViewTextField() {
116        return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
117    }
118
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