136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley/* 236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Copyright (C) 2017 The Android Open Source Project 336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * 436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Licensed under the Apache License, Version 2.0 (the "License"); 536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * you may not use this file except in compliance with the License. 636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * You may obtain a copy of the License at 736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * 836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * http://www.apache.org/licenses/LICENSE-2.0 936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * 1036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Unless required by applicable law or agreed to in writing, software 1136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * distributed under the License is distributed on an "AS IS" BASIS, 1236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * See the License for the specific language governing permissions and 1436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * limitations under the License. 1536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley */ 1636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 1736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleypackage android.support.wear.widget.drawer; 1836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 1936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.Espresso.onView; 2036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.action.ViewActions.click; 2136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.action.ViewActions.swipeDown; 2236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.assertion.ViewAssertions.matches; 2331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; 2436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; 2536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 2636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.matcher.ViewMatchers.withId; 2731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport static android.support.test.espresso.matcher.ViewMatchers.withParent; 2836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.test.espresso.matcher.ViewMatchers.withText; 2936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static android.support.wear.widget.util.AsyncViewActions.waitForMatchingView; 3036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 3136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static org.hamcrest.Matchers.allOf; 3231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport static org.hamcrest.Matchers.is; 3336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static org.hamcrest.Matchers.not; 3436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static org.junit.Assert.assertNotNull; 3536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static org.junit.Assert.assertTrue; 3636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static org.mockito.Matchers.any; 3736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static org.mockito.Mockito.mock; 3836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport static org.mockito.Mockito.verify; 3936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 4036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.content.Intent; 4131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport android.support.test.espresso.PerformException; 4231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport android.support.test.espresso.UiController; 4331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport android.support.test.espresso.ViewAction; 4431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport android.support.test.espresso.util.HumanReadables; 4531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport android.support.test.espresso.util.TreeIterables; 4636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.test.filters.LargeTest; 4736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.test.rule.ActivityTestRule; 4836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.test.runner.AndroidJUnit4; 4936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.v7.widget.RecyclerView; 5036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.test.R; 5136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.support.wear.widget.drawer.DrawerTestActivity.DrawerStyle; 5231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport android.view.Menu; 5336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.MenuItem; 5436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.MenuItem.OnMenuItemClickListener; 5536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.view.View; 5636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport android.widget.ImageView; 5731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport android.widget.TextView; 5836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 5936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport org.hamcrest.Description; 6031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport org.hamcrest.Matcher; 6136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport org.hamcrest.TypeSafeMatcher; 625c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelleyimport org.junit.Before; 6336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport org.junit.Rule; 6436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport org.junit.Test; 6536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleyimport org.junit.runner.RunWith; 665c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelleyimport org.mockito.Mock; 675c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelleyimport org.mockito.MockitoAnnotations; 6836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 6931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport java.util.concurrent.TimeoutException; 7031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 7131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelleyimport javax.annotation.Nullable; 7231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 7336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley/** 7436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley * Espresso tests for {@link WearableDrawerLayout}. 7536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley */ 7636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley@LargeTest 7736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley@RunWith(AndroidJUnit4.class) 7836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelleypublic class WearableDrawerLayoutEspressoTest { 7936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 8036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley private static final long MAX_WAIT_MS = 4000; 8136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 8236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Rule public final ActivityTestRule<DrawerTestActivity> activityRule = 8336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new ActivityTestRule<>( 8436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley DrawerTestActivity.class, true /* touchMode */, false /* initialLaunch*/); 8536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 8636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley private final Intent mSinglePageIntent = 8736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new DrawerTestActivity.Builder().setStyle(DrawerStyle.BOTH_DRAWER_NAV_SINGLE_PAGE) 8836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .build(); 895c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Mock WearableNavigationDrawerView.OnItemSelectedListener mNavDrawerItemSelectedListener; 9036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 915c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Before 925c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley public void setUp() { 935c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley MockitoAnnotations.initMocks(this); 9436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 9536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 9636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 9736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void openingNavigationDrawerDoesNotCloseActionDrawer() { 9836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN a drawer layout with a peeking action and navigation drawer 9936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity(mSinglePageIntent); 10036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley DrawerTestActivity activity = activityRule.getActivity(); 10136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley WearableDrawerView actionDrawer = 10236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley (WearableDrawerView) activity.findViewById(R.id.action_drawer); 10336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley WearableDrawerView navigationDrawer = 10436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley (WearableDrawerView) activity.findViewById(R.id.navigation_drawer); 10536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley assertTrue(actionDrawer.isPeeking()); 10636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley assertTrue(navigationDrawer.isPeeking()); 10736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 10836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN the top drawer is opened 10936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley openDrawer(navigationDrawer); 11036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)) 11136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 11236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView( 11336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley allOf(withId(R.id.navigation_drawer), isOpened(true)), 11436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 11536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 11636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the action drawer should still be peeking 11736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley assertTrue(actionDrawer.isPeeking()); 11836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 11936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 12036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 12136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void swipingDownNavigationDrawerDoesNotCloseActionDrawer() { 12236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN a drawer layout with a peeking action and navigation drawer 12336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity(mSinglePageIntent); 12436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)).check(matches(isPeeking())); 12536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)).check(matches(isPeeking())); 12636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 12736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN the top drawer is opened by swiping down 12836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.drawer_layout)).perform(swipeDown()); 12936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)) 13036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 13136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView( 13236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley allOf(withId(R.id.navigation_drawer), isOpened(true)), 13336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 13436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 13536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the action drawer should still be peeking 13636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)).check(matches(isPeeking())); 13736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 13836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 13936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 14036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 14136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void firstNavDrawerItemShouldBeSelectedInitially() { 14236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN a top drawer 14336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN it is first opened 14436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity(mSinglePageIntent); 14536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.drawer_layout)).perform(swipeDown()); 14636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)) 14736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 14836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView( 14936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley allOf(withId(R.id.navigation_drawer), isOpened(true)), 15036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 15136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 15236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the text should display "0". 15397f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska onView(withId(R.id.ws_nav_drawer_text)).check(matches(withText("0"))); 15436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 15536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 15636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 15736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void selectingNavItemChangesTextAndClosedDrawer() { 15836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN an open top drawer 15936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity(mSinglePageIntent); 16036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.drawer_layout)).perform(swipeDown()); 16136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)) 16236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 16336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView( 16436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley allOf(withId(R.id.navigation_drawer), isOpened(true)), 16536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 16636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 16736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN the second item is selected 16897f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska onView(withId(R.id.ws_nav_drawer_icon_1)).perform(click()); 16936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 17036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the text should display "1" and it should close. 17197f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska onView(withId(R.id.ws_nav_drawer_text)) 17236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 17336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView( 17497f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska allOf(withId(R.id.ws_nav_drawer_text), withText("1")), 17536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 17636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)) 17736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 17836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView( 17936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley allOf(withId(R.id.navigation_drawer), isClosed(true)), 18036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 18136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 18236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 18336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 1845c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley public void programmaticallySelectingNavItemChangesTextInSinglePage() { 1855c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley // GIVEN an open top drawer 1865c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley activityRule.launchActivity(new DrawerTestActivity.Builder() 1875c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .setStyle(DrawerStyle.BOTH_DRAWER_NAV_SINGLE_PAGE) 1885c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .openTopDrawerInOnCreate() 1895c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .build()); 1905c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley final WearableNavigationDrawerView navDrawer = 1915c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley activityRule.getActivity().findViewById(R.id.navigation_drawer); 1925c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley navDrawer.addOnItemSelectedListener(mNavDrawerItemSelectedListener); 1935c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 1945c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley // WHEN the second item is selected programmatically 1955c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley selectNavItem(navDrawer, 1); 1965c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 1975c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley // THEN the text should display "1" and the listener should be notified. 19897f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska onView(withId(R.id.ws_nav_drawer_text)) 1995c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .check(matches(withText("1"))); 2005c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley verify(mNavDrawerItemSelectedListener).onItemSelected(1); 2015c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 2025c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 2035c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Test 2045c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley public void programmaticallySelectingNavItemChangesTextInMultiPage() { 2055c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley // GIVEN an open top drawer 2065c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley activityRule.launchActivity(new DrawerTestActivity.Builder() 2075c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .setStyle(DrawerStyle.BOTH_DRAWER_NAV_MULTI_PAGE) 2085c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .openTopDrawerInOnCreate() 2095c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .build()); 2105c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley final WearableNavigationDrawerView navDrawer = 2115c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley activityRule.getActivity().findViewById(R.id.navigation_drawer); 2125c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley navDrawer.addOnItemSelectedListener(mNavDrawerItemSelectedListener); 2135c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 2145c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley // WHEN the second item is selected programmatically 2155c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley selectNavItem(navDrawer, 1); 2165c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 2175c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley // THEN the text should display "1" and the listener should be notified. 21897f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska onView(allOf(withId(R.id.ws_navigation_drawer_item_text), isDisplayed())) 2195c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley .check(matches(withText("1"))); 2205c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley verify(mNavDrawerItemSelectedListener).onItemSelected(1); 2215c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 2225c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 2235c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Test 22436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void navDrawerShouldOpenWhenCalledInOnCreate() { 22536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN an activity which calls openDrawer(Gravity.TOP) in onCreate 22636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN it is launched 22736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity( 22836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new DrawerTestActivity.Builder() 22936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .setStyle(DrawerStyle.BOTH_DRAWER_NAV_SINGLE_PAGE) 23036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .openTopDrawerInOnCreate() 23136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .build()); 23236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 23336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the nav drawer should be open 23436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)).check(matches(isOpened(true))); 23536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 23636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 23736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 23836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void actionDrawerShouldOpenWhenCalledInOnCreate() { 23936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN an activity with only an action drawer which is opened in onCreate 24036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN it is launched 24136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity( 24236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new DrawerTestActivity.Builder() 24336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .setStyle(DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE) 24436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .openBottomDrawerInOnCreate() 24536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .build()); 24636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 24736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the action drawer should be open 24836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)).check(matches(isOpened(true))); 24936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 25036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 25136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 25236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void navDrawerShouldOpenWhenCalledInOnCreateAndThenCloseWhenRequested() { 25336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN an activity which calls openDrawer(Gravity.TOP) in onCreate, then closes it 25436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN it is launched 25536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity( 25636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new DrawerTestActivity.Builder() 25736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .setStyle(DrawerStyle.BOTH_DRAWER_NAV_SINGLE_PAGE) 25836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .openTopDrawerInOnCreate() 25936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .closeFirstDrawerOpened() 26036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .build()); 26136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 26236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the nav drawer should be open and then close 26336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)) 26436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .check(matches(isOpened(true))) 26536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 26636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView( 26736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley allOf(withId(R.id.navigation_drawer), isClosed(true)), 26836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 26936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 27036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 27136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 27236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void openedNavDrawerShouldPreventSwipeToClose() { 27336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN an activity which calls openDrawer(Gravity.TOP) in onCreate 27436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity( 27536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new DrawerTestActivity.Builder() 27636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .setStyle(DrawerStyle.BOTH_DRAWER_NAV_SINGLE_PAGE) 27736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .openTopDrawerInOnCreate() 27836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .build()); 27936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 28036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the view should prevent swipe to close 28136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)).check(matches(not(allowsSwipeToClose()))); 28236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 28336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 28436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 28536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void closedNavDrawerShouldNotPreventSwipeToClose() { 28636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN an activity which doesn't start with the nav drawer open 28736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity(mSinglePageIntent); 28836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 28936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN the view should allow swipe to close 29036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.navigation_drawer)).check(matches(allowsSwipeToClose())); 29136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 29236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 29336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 29436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void scrolledDownActionDrawerCanScrollUpWhenReOpened() { 29536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN a freshly launched activity 29636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity(mSinglePageIntent); 29736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley WearableActionDrawerView actionDrawer = 29836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley (WearableActionDrawerView) activityRule.getActivity() 29936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .findViewById(R.id.action_drawer); 30036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley RecyclerView recyclerView = (RecyclerView) actionDrawer.getDrawerContent(); 30136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 30236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN the action drawer is opened and scrolled to the last item (Item 6) 30336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley openDrawer(actionDrawer); 30436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley scrollToPosition(recyclerView, 5); 30536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)) 30636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 30736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView(allOf(withId(R.id.action_drawer), isOpened(true)), 30836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)) 30936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 31036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView(allOf(withText("Item 6"), isCompletelyDisplayed()), 31136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 31236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // and then it is peeked 31336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley peekDrawer(actionDrawer); 31436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)) 31536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform(waitForMatchingView(allOf(withId(R.id.action_drawer), isPeeking()), 31636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 31736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // and re-opened 31836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley openDrawer(actionDrawer); 31936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)) 32036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform( 32136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley waitForMatchingView(allOf(withId(R.id.action_drawer), isOpened(true)), 32236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 32336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 32436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN item 6 should be visible, but swiping down should scroll up, not close the drawer. 32536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withText("Item 6")).check(matches(isDisplayed())); 32636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)).perform(swipeDown()).check(matches(isOpened(true))); 32736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 32836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 32936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 33036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void actionDrawerPeekIconShouldNotBeNull() { 33136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN a drawer layout with a peeking action drawer whose menu is initialized in XML 33236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity(mSinglePageIntent); 33336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley DrawerTestActivity activity = activityRule.getActivity(); 33436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley ImageView peekIconView = 33536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley (ImageView) activity 33697f7aa4e4dd8f5c1f14d93d3f67540c72a5bbe57Aga Madurska .findViewById(R.id.ws_action_drawer_peek_action_icon); 33736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN its peek icon should not be null 33836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley assertNotNull(peekIconView.getDrawable()); 33936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 34036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 34136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 34236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void tappingActionDrawerPeekIconShouldTriggerFirstAction() { 34336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN a drawer layout with a peeking action drawer, title, and mock click listener 34436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity( 34536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new DrawerTestActivity.Builder() 34636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .setStyle(DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE) 34736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .build()); 34836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley WearableActionDrawerView actionDrawer = 34936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley (WearableActionDrawerView) activityRule.getActivity() 35036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .findViewById(R.id.action_drawer); 35136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley OnMenuItemClickListener mockClickListener = mock(OnMenuItemClickListener.class); 35236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley actionDrawer.setOnMenuItemClickListener(mockClickListener); 35336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN the action drawer peek view is tapped 35469f9658a6e7f2ec1102ffc74bd19d053659cf392Sean Kelley onView(withId(R.id.ws_drawer_view_peek_container)) 35569f9658a6e7f2ec1102ffc74bd19d053659cf392Sean Kelley .perform(waitForMatchingView( 35669f9658a6e7f2ec1102ffc74bd19d053659cf392Sean Kelley allOf( 35769f9658a6e7f2ec1102ffc74bd19d053659cf392Sean Kelley withId(R.id.ws_drawer_view_peek_container), 35869f9658a6e7f2ec1102ffc74bd19d053659cf392Sean Kelley isCompletelyDisplayed()), 35969f9658a6e7f2ec1102ffc74bd19d053659cf392Sean Kelley MAX_WAIT_MS)) 36036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform(click()); 36136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN its click listener should be notified 36236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley verify(mockClickListener).onMenuItemClick(any(MenuItem.class)); 36336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 36436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 36536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Test 36636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void tappingActionDrawerPeekIconShouldTriggerFirstActionAfterItWasOpened() { 36736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // GIVEN a drawer layout with an open action drawer with a title, and mock click listener 36836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley activityRule.launchActivity( 36936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley new DrawerTestActivity.Builder() 37036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .setStyle(DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE) 37136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .openBottomDrawerInOnCreate() 37236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .build()); 37336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley WearableActionDrawerView actionDrawer = 37436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley (WearableActionDrawerView) activityRule.getActivity() 37536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .findViewById(R.id.action_drawer); 37636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley OnMenuItemClickListener mockClickListener = mock(OnMenuItemClickListener.class); 37736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley actionDrawer.setOnMenuItemClickListener(mockClickListener); 37836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 37936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // WHEN the action drawer is closed to its peek state and then tapped 38036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley peekDrawer(actionDrawer); 38136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley onView(withId(R.id.action_drawer)) 38236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley .perform(waitForMatchingView(allOf(withId(R.id.action_drawer), isPeeking()), 38336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley MAX_WAIT_MS)); 38436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley actionDrawer.getPeekContainer().callOnClick(); 38536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 38636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley // THEN its click listener should be notified 38736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley verify(mockClickListener).onMenuItemClick(any(MenuItem.class)); 38836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 38936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 39031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Test 39131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void changingActionDrawerItemShouldUpdateView() { 39231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // GIVEN a drawer layout with an open action drawer 39331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley activityRule.launchActivity( 39431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley new DrawerTestActivity.Builder() 39531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .setStyle(DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE) 39631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .openBottomDrawerInOnCreate() 39731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .build()); 39831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley WearableActionDrawerView actionDrawer = 39931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley activityRule.getActivity().findViewById(R.id.action_drawer); 40031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final MenuItem secondItem = actionDrawer.getMenu().getItem(1); 40131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 40231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // WHEN its second item is changed 40331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley actionDrawer.post(new Runnable() { 40431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 40531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void run() { 40631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley secondItem.setTitle("Modified item"); 40731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 40831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley }); 40931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 41031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // THEN the new item should be displayed 41131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley onView(withText("Modified item")).check(matches(isDisplayed())); 41231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 41331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 41431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Test 41531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void removingActionDrawerItemShouldUpdateView() { 41631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // GIVEN a drawer layout with an open action drawer 41731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley activityRule.launchActivity( 41831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley new DrawerTestActivity.Builder() 41931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .setStyle(DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE) 42031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .openBottomDrawerInOnCreate() 42131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .build()); 42231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final WearableActionDrawerView actionDrawer = 42331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley activityRule.getActivity().findViewById(R.id.action_drawer); 42431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley MenuItem secondItem = actionDrawer.getMenu().getItem(1); 42531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final int itemId = secondItem.getItemId(); 42631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final String title = secondItem.getTitle().toString(); 42731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final int initialSize = getChildByType(actionDrawer, RecyclerView.class) 42831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .getAdapter() 42931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .getItemCount(); 43031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 43131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // WHEN its second item is removed 43231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley actionDrawer.post(new Runnable() { 43331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 43431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void run() { 43531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley actionDrawer.getMenu().removeItem(itemId); 43631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 43731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley }); 43831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 43931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // THEN it should decrease by 1 in size and it should no longer contain the item's text 44031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley onView(allOf(withParent(withId(R.id.action_drawer)), isAssignableFrom(RecyclerView.class))) 44131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .perform(waitForRecyclerToBeSize(initialSize - 1, MAX_WAIT_MS)) 44231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .perform(waitForMatchingView(recyclerWithoutText(is(title)), MAX_WAIT_MS)); 44331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 44431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 44531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Test 44631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void addingActionDrawerItemShouldUpdateView() { 44731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // GIVEN a drawer layout with an open action drawer 44831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley activityRule.launchActivity( 44931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley new DrawerTestActivity.Builder() 45031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .setStyle(DrawerStyle.ONLY_ACTION_DRAWER_WITH_TITLE) 45131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .openBottomDrawerInOnCreate() 45231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .build()); 45331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final WearableActionDrawerView actionDrawer = 45431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley activityRule.getActivity().findViewById(R.id.action_drawer); 45531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 45631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley RecyclerView recycler = getChildByType(actionDrawer, RecyclerView.class); 45731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final RecyclerView.LayoutManager layoutManager = recycler.getLayoutManager(); 45831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final int initialSize = recycler.getAdapter().getItemCount(); 45931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 46031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // WHEN an item is added and the view is scrolled down (to make sure the view is created) 46131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley actionDrawer.post(new Runnable() { 46231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 46331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void run() { 46431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley actionDrawer.getMenu().add(0, 42, Menu.NONE, "New Item"); 46531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley layoutManager.scrollToPosition(initialSize); 46631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 46731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley }); 46831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 46931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // THEN it should decrease by 1 in size and the there should be a view with the item's text 47031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley onView(allOf(withParent(withId(R.id.action_drawer)), isAssignableFrom(RecyclerView.class))) 47131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .perform(waitForRecyclerToBeSize(initialSize + 1, MAX_WAIT_MS)) 47231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .perform(waitForMatchingView(withText("New Item"), MAX_WAIT_MS)); 47331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 47431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 47536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley private void scrollToPosition(final RecyclerView recyclerView, final int position) { 47636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley recyclerView.post(new Runnable() { 47736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Override 47836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void run() { 47936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley recyclerView.scrollToPosition(position); 48036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 48136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley }); 48236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 48336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 4845c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley private void selectNavItem(final WearableNavigationDrawerView navDrawer, final int index) { 4855c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley navDrawer.post(new Runnable() { 4865c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Override 4875c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley public void run() { 4885c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley navDrawer.setCurrentItem(index, false); 4895c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 4905c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley }); 4915c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 4925c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 49336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley private void peekDrawer(final WearableDrawerView drawer) { 49436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley drawer.post(new Runnable() { 49536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Override 49636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void run() { 49736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley drawer.getController().peekDrawer(); 49836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 49936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley }); 50036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 50136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 50236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley private void openDrawer(final WearableDrawerView drawer) { 50336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley drawer.post(new Runnable() { 50436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Override 50536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void run() { 50636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley drawer.getController().openDrawer(); 50736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 50836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley }); 50936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 51036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 5115c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley private static TypeSafeMatcher<View> isOpened(final boolean isOpened) { 5125c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley return new TypeSafeMatcher<View>() { 5135c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Override 5145c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley public void describeTo(Description description) { 5155c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley description.appendText("is opened == " + isOpened); 5165c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 5175c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 5185c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Override 5195c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley public boolean matchesSafely(View view) { 5205c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley return ((WearableDrawerView) view).isOpened() == isOpened; 5215c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 5225c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley }; 5235c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 5245c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 5255c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley private static TypeSafeMatcher<View> isClosed(final boolean isClosed) { 5265c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley return new TypeSafeMatcher<View>() { 5275c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Override 5285c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley protected boolean matchesSafely(View view) { 5295c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley WearableDrawerView drawer = (WearableDrawerView) view; 5305c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley return drawer.isClosed() == isClosed; 5315c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 5325c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 5335c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley @Override 5345c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley public void describeTo(Description description) { 5355c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley description.appendText("is closed"); 5365c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 5375c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley }; 5385c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley } 5395c859ba8bcd6f30ec170f61d983379ebd03f4dbcSean Kelley 54036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley private TypeSafeMatcher<View> isPeeking() { 54136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley return new TypeSafeMatcher<View>() { 54236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Override 54336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley protected boolean matchesSafely(View view) { 54436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley WearableDrawerView drawer = (WearableDrawerView) view; 54536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley return drawer.isPeeking(); 54636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 54736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 54836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Override 54936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void describeTo(Description description) { 55036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley description.appendText("is peeking"); 55136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 55236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley }; 55336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 55436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 55536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley private TypeSafeMatcher<View> allowsSwipeToClose() { 55636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley return new TypeSafeMatcher<View>() { 55736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Override 55836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley protected boolean matchesSafely(View view) { 55936545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley return !view.canScrollHorizontally(-2) && !view.canScrollHorizontally(2); 56036545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 56136545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley 56236545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley @Override 56336545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley public void describeTo(Description description) { 56436545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley description.appendText("can be swiped closed"); 56536545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 56636545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley }; 56736545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley } 56831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 56931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley /** 57031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley * Returns a {@link TypeSafeMatcher} that returns {@code true} when the {@link RecyclerView} 57131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley * does not contain a {@link TextView} with text matched by {@code textMatcher}. 57231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley */ 57331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley private TypeSafeMatcher<View> recyclerWithoutText(final Matcher<String> textMatcher) { 57431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return new TypeSafeMatcher<View>() { 57531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 57631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 57731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void describeTo(Description description) { 57831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley description.appendText("Without recycler text "); 57931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley textMatcher.describeTo(description); 58031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 58131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 58231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 58331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public boolean matchesSafely(View view) { 58431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley if (!(view instanceof RecyclerView)) { 58531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return false; 58631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 58731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 58831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley RecyclerView recycler = ((RecyclerView) view); 58931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley if (recycler.isAnimating()) { 59031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // While the RecyclerView is animating, it will return null ViewHolders and we 59131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // won't be able to tell whether the item has been removed or not. 59231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return false; 59331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 59431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 59531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley for (int i = 0; i < recycler.getAdapter().getItemCount(); i++) { 59631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley RecyclerView.ViewHolder holder = recycler.findViewHolderForAdapterPosition(i); 59731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley if (holder != null) { 59831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley TextView text = getChildByType(holder.itemView, TextView.class); 59931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley if (text != null && textMatcher.matches(text.getText())) { 60031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return false; 60131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 60231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 60331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 60431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 60531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return true; 60631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 60731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley }; 60831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 60931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 61031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley /** 61131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley * Waits for the {@link RecyclerView} to contain {@code targetCount} items, up to {@code millis} 61231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley * milliseconds. Throws exception if the time limit is reached before reaching the desired 61331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley * number of items. 61431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley */ 61531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public ViewAction waitForRecyclerToBeSize(final int targetCount, final long millis) { 61631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return new ViewAction() { 61731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 61831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public Matcher<View> getConstraints() { 61931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return isAssignableFrom(RecyclerView.class); 62031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 62131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 62231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 62331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public String getDescription() { 62431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return "Waiting for recycler to be size=" + targetCount; 62531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 62631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 62731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Override 62831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley public void perform(UiController uiController, View view) { 62931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley if (!(view instanceof RecyclerView)) { 63031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return; 63131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 63231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 63331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley RecyclerView recycler = (RecyclerView) view; 63431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley uiController.loopMainThreadUntilIdle(); 63531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final long startTime = System.currentTimeMillis(); 63631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley final long endTime = startTime + millis; 63731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley do { 63831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley if (recycler.getAdapter().getItemCount() == targetCount) { 63931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return; 64031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 64131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley uiController.loopMainThreadForAtLeast(100); // at least 3 frames 64231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } while (System.currentTimeMillis() < endTime); 64331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 64431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley // timeout happens 64531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley throw new PerformException.Builder() 64631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .withActionDescription(this.getDescription()) 64731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .withViewDescription(HumanReadables.describe(view)) 64831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .withCause(new TimeoutException()) 64931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley .build(); 65031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 65131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley }; 65231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 65331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 65431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley /** 65531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley * Returns the first child of {@code root} to be an instance of class {@code T}, or {@code null} 65631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley * if none were found. 65731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley */ 65831da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley @Nullable 65931da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley private <T> T getChildByType(View root, Class<T> classOfChildToFind) { 66031da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley for (View child : TreeIterables.breadthFirstViewTraversal(root)) { 66131da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley if (classOfChildToFind.isInstance(child)) { 66231da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return (T) child; 66331da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 66431da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 66531da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley 66631da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley return null; 66731da69009a893e97db8c5288b58dc9d84c3a6e85Sean Kelley } 66836545bb3f2b12af352e550c278cff9026a18ca54Sean Kelley} 669