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 android.widget.espresso; 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.RootMatchers.withDecorView; 23 import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; 24 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 25 import static android.support.test.espresso.matcher.ViewMatchers.isRoot; 26 import static android.support.test.espresso.matcher.ViewMatchers.withTagValue; 27 import static android.support.test.espresso.matcher.ViewMatchers.withId; 28 import static android.support.test.espresso.matcher.ViewMatchers.withText; 29 import static org.hamcrest.Matchers.allOf; 30 import static org.hamcrest.Matchers.is; 31 32 import org.hamcrest.Matcher; 33 34 import android.support.test.espresso.NoMatchingRootException; 35 import android.support.test.espresso.NoMatchingViewException; 36 import android.support.test.espresso.UiController; 37 import android.support.test.espresso.ViewAction; 38 import android.support.test.espresso.ViewInteraction; 39 import android.view.View; 40 41 import com.android.internal.widget.FloatingToolbar; 42 43 /** 44 * Espresso utility methods for the floating toolbar. 45 */ 46 public class FloatingToolbarEspressoUtils { 47 private final static Object TAG = FloatingToolbar.FLOATING_TOOLBAR_TAG; 48 FloatingToolbarEspressoUtils()49 private FloatingToolbarEspressoUtils() {} 50 onFloatingToolBar()51 private static ViewInteraction onFloatingToolBar() { 52 return onView(withTagValue(is(TAG))) 53 .inRoot(withDecorView(hasDescendant(withTagValue(is(TAG))))); 54 } 55 56 /** 57 * Creates a {@link ViewInteraction} for the floating bar menu item with the given matcher. 58 * 59 * @param matcher The matcher for the menu item. 60 */ onFloatingToolBarItem(Matcher<View> matcher)61 public static ViewInteraction onFloatingToolBarItem(Matcher<View> matcher) { 62 return onView(matcher) 63 .inRoot(withDecorView(hasDescendant(withTagValue(is(TAG))))); 64 } 65 66 /** 67 * Asserts that the floating toolbar is displayed on screen. 68 * 69 * @throws AssertionError if the assertion fails 70 */ assertFloatingToolbarIsDisplayed()71 public static void assertFloatingToolbarIsDisplayed() { 72 onFloatingToolBar().check(matches(isDisplayed())); 73 } 74 75 /** 76 * Asserts that the floating toolbar is not displayed on screen. 77 * 78 * @throws AssertionError if the assertion fails 79 */ assertFloatingToolbarIsNotDisplayed()80 public static void assertFloatingToolbarIsNotDisplayed() { 81 try { 82 onFloatingToolBar().check(matches(isDisplayed())); 83 } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) { 84 return; 85 } 86 throw new AssertionError("Floating toolbar is displayed"); 87 } 88 toggleOverflow()89 private static void toggleOverflow() { 90 final int id = com.android.internal.R.id.overflow; 91 onView(allOf(withId(id), isDisplayed())) 92 .inRoot(withDecorView(hasDescendant(withId(id)))) 93 .perform(click()); 94 onView(isRoot()).perform(SLEEP); 95 } 96 sleepForFloatingToolbarPopup()97 public static void sleepForFloatingToolbarPopup() { 98 onView(isRoot()).perform(SLEEP); 99 } 100 101 /** 102 * Asserts that the floating toolbar contains the specified item. 103 * 104 * @param itemLabel label of the item. 105 * @throws AssertionError if the assertion fails 106 */ assertFloatingToolbarContainsItem(String itemLabel)107 public static void assertFloatingToolbarContainsItem(String itemLabel) { 108 try{ 109 onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel)))); 110 } catch (AssertionError e) { 111 try{ 112 toggleOverflow(); 113 } catch (NoMatchingViewException | NoMatchingRootException e2) { 114 // No overflow items. 115 throw e; 116 } 117 try{ 118 onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel)))); 119 } finally { 120 toggleOverflow(); 121 } 122 } 123 } 124 125 /** 126 * Asserts that the floating toolbar doesn't contain the specified item. 127 * 128 * @param itemLabel label of the item. 129 * @throws AssertionError if the assertion fails 130 */ assertFloatingToolbarDoesNotContainItem(String itemLabel)131 public static void assertFloatingToolbarDoesNotContainItem(String itemLabel) { 132 try{ 133 assertFloatingToolbarContainsItem(itemLabel); 134 } catch (AssertionError e) { 135 return; 136 } 137 throw new AssertionError("Floating toolbar contains " + itemLabel); 138 } 139 140 /** 141 * Click specified item on the floating tool bar. 142 * 143 * @param itemLabel label of the item. 144 */ clickFloatingToolbarItem(String itemLabel)145 public static void clickFloatingToolbarItem(String itemLabel) { 146 try{ 147 onFloatingToolBarItem(withText(itemLabel)).check(matches(isDisplayed())); 148 } catch (AssertionError e) { 149 // Try to find the item in the overflow menu. 150 toggleOverflow(); 151 } 152 onFloatingToolBarItem(withText(itemLabel)).perform(click()); 153 } 154 155 /** 156 * ViewAction to sleep to wait floating toolbar's animation. 157 */ 158 private static final ViewAction SLEEP = new ViewAction() { 159 private static final long SLEEP_DURATION = 400; 160 161 @Override 162 public Matcher<View> getConstraints() { 163 return isDisplayed(); 164 } 165 166 @Override 167 public String getDescription() { 168 return "Sleep " + SLEEP_DURATION + " ms."; 169 } 170 171 @Override 172 public void perform(UiController uiController, View view) { 173 uiController.loopMainThreadForAtLeast(SLEEP_DURATION); 174 } 175 }; 176 } 177