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 androidx.test.espresso.Espresso.onView; 20 import static androidx.test.espresso.action.ViewActions.typeText; 21 import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; 22 import static androidx.test.espresso.matcher.ViewMatchers.isClickable; 23 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; 24 import static androidx.test.espresso.matcher.ViewMatchers.withId; 25 26 import static junit.framework.Assert.assertEquals; 27 import static junit.framework.Assert.assertFalse; 28 import static junit.framework.Assert.assertTrue; 29 30 import static org.hamcrest.CoreMatchers.allOf; 31 import static org.hamcrest.CoreMatchers.anyOf; 32 33 import android.content.Context; 34 import android.support.test.uiautomator.UiDevice; 35 import android.support.test.uiautomator.UiObject; 36 import android.support.test.uiautomator.UiObjectNotFoundException; 37 import android.view.View; 38 39 import androidx.recyclerview.R; 40 41 import org.hamcrest.Matcher; 42 43 /** 44 * A test helper class that provides support for controlling the search UI 45 * programmatically, and making assertions against the state of the UI. 46 * <p> 47 * Support for working directly with Roots and Directory view can be found in the respective bots. 48 */ 49 public class SearchBot extends Bots.BaseBot { 50 51 // Dumb search layout changes substantially between Ryu and Angler. 52 @SuppressWarnings("unchecked") 53 private static final Matcher<View> SEARCH_WIDGET = allOf( 54 withId(R.id.option_menu_search), 55 anyOf(isClickable(), hasDescendant(isClickable()))); 56 57 // Note that input is visible when the clicky button is not 58 // present. So to clearly qualify the two...we explicitly 59 // require this input be not clickable. 60 @SuppressWarnings("unchecked") 61 private static final Matcher<View> SEARCH_INPUT = allOf( 62 withId(R.id.search_src_text), 63 isDisplayed()); 64 SearchBot(UiDevice device, Context context, int timeout)65 public SearchBot(UiDevice device, Context context, int timeout) { 66 super(device, context, timeout); 67 } 68 clickIcon()69 public void clickIcon() throws UiObjectNotFoundException { 70 UiObject searchView = findSearchView(); 71 searchView.click(); 72 73 UiObject fragmentSearchView = findFragmentSearchView(); 74 assertTrue(fragmentSearchView.exists()); 75 } 76 clickSearchViewClearButton()77 public void clickSearchViewClearButton() throws UiObjectNotFoundException { 78 UiObject clear = findSearchViewClearButton(); 79 clear.click(); 80 } 81 clickFragmentSearchViewClearButton()82 public void clickFragmentSearchViewClearButton() throws UiObjectNotFoundException { 83 UiObject clear = findFragmentSearchClearButton(); 84 clear.click(); 85 } 86 setInputText(String query)87 public void setInputText(String query) throws UiObjectNotFoundException { 88 onView(SEARCH_INPUT).perform(typeText(query)); 89 } 90 assertIconVisible(boolean visible)91 public void assertIconVisible(boolean visible) { 92 if (visible) { 93 assertTrue( 94 "Search icon should be visible.", 95 Matchers.present(SEARCH_WIDGET)); 96 } else { 97 assertFalse( 98 "Search icon should not be visible.", 99 Matchers.present(SEARCH_WIDGET)); 100 } 101 } 102 assertInputEquals(String query)103 public void assertInputEquals(String query) 104 throws UiObjectNotFoundException { 105 UiObject textField = findSearchViewTextField(); 106 107 assertTrue(textField.exists()); 108 assertEquals(query, textField.getText()); 109 } 110 assertInputFocused(boolean focused)111 public void assertInputFocused(boolean focused) 112 throws UiObjectNotFoundException { 113 UiObject textField = findSearchViewTextField(); 114 115 assertTrue(textField.exists()); 116 assertEquals(focused, textField.isFocused()); 117 } 118 assertInputExists(boolean exists)119 public void assertInputExists(boolean exists) 120 throws UiObjectNotFoundException { 121 assertEquals(exists, findSearchViewTextField().exists()); 122 } 123 assertFragmentInputFocused(boolean focused)124 public void assertFragmentInputFocused(boolean focused) 125 throws UiObjectNotFoundException { 126 UiObject textField = findFragmentSearchViewTextField(); 127 128 assertTrue(textField.exists()); 129 assertEquals(focused, textField.isFocused()); 130 } 131 assertFragmentInputExists(boolean exists)132 public void assertFragmentInputExists(boolean exists) 133 throws UiObjectNotFoundException { 134 assertEquals(exists, findFragmentSearchViewTextField().exists()); 135 } 136 findSearchView()137 private UiObject findSearchView() { 138 return findObject(mTargetPackage + ":id/option_menu_search"); 139 } 140 findSearchViewTextField()141 private UiObject findSearchViewTextField() { 142 return findObject(mTargetPackage + ":id/option_menu_search", 143 mTargetPackage + ":id/search_src_text"); 144 } 145 findSearchViewClearButton()146 private UiObject findSearchViewClearButton() { 147 return findObject(mTargetPackage + ":id/option_menu_search", 148 mTargetPackage + ":id/search_close_btn"); 149 } 150 findFragmentSearchView()151 private UiObject findFragmentSearchView() { 152 return findObject(mTargetPackage + ":id/search_view"); 153 } 154 findFragmentSearchViewTextField()155 private UiObject findFragmentSearchViewTextField() { 156 return findObject(mTargetPackage + ":id/search_view", 157 mTargetPackage + ":id/search_src_text"); 158 } 159 findFragmentSearchClearButton()160 private UiObject findFragmentSearchClearButton() { 161 return findObject(mTargetPackage + ":id/search_view", 162 mTargetPackage + ":id/search_close_btn"); 163 } 164 findSearchViewIcon()165 private UiObject findSearchViewIcon() { 166 return mContext.getResources().getBoolean(R.bool.full_bar_search_view) 167 ? findObject(mTargetPackage + ":id/option_menu_search") 168 : findObject(mTargetPackage + ":id/option_menu_search", 169 "android:id/search_button"); 170 } 171 } 172