1c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov/* 2c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * Copyright (C) 2016 The Android Open Source Project 3c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * 4c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * Licensed under the Apache License, Version 2.0 (the "License"); 5c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * you may not use this file except in compliance with the License. 6c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * You may obtain a copy of the License at 7c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * 8c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * http://www.apache.org/licenses/LICENSE-2.0 9c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * 10c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * Unless required by applicable law or agreed to in writing, software 11c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * distributed under the License is distributed on an "AS IS" BASIS, 12c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * See the License for the specific language governing permissions and 14c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov * limitations under the License. 15c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov */ 16c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovpackage android.support.design.widget; 17c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 18910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.DrawerLayoutActions.closeDrawer; 19910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.DrawerLayoutActions.openDrawer; 20910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.addHeaderView; 21910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.inflateHeaderView; 22910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.removeHeaderView; 2324e362dd19caffb820011c08125c1a301ba819f8Yuichi Arakiimport static android.support.design.testutils.NavigationViewActions.removeMenuItem; 24910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.setCheckedItem; 25910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.setIconForMenuItem; 26910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.setItemBackground; 27910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.setItemBackgroundResource; 28910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.setItemIconTintList; 29910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.setItemTextAppearance; 30910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.NavigationViewActions.setItemTextColor; 3124e362dd19caffb820011c08125c1a301ba819f8Yuichi Arakiimport static android.support.design.testutils.TestUtilsActions.reinflateMenu; 329a2ea21c22dab29fd8f807052f13091036929c48Yuichi Arakiimport static android.support.design.testutils.TestUtilsActions.restoreHierarchyState; 3324e362dd19caffb820011c08125c1a301ba819f8Yuichi Arakiimport static android.support.design.testutils.TestUtilsMatchers.isActionViewOf; 34910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.TestUtilsMatchers.isChildOfA; 35910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.TestUtilsMatchers.withBackgroundFill; 36910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.TestUtilsMatchers.withStartDrawableFilledWith; 37910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.TestUtilsMatchers.withTextColor; 38910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.TestUtilsMatchers.withTextSize; 39910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.Espresso.onView; 40910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.action.ViewActions.click; 41910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.assertion.ViewAssertions.matches; 42910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.Visibility; 43910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; 44910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; 459a2ea21c22dab29fd8f807052f13091036929c48Yuichi Arakiimport static android.support.test.espresso.matcher.ViewMatchers.isChecked; 46910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed; 47910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; 48910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 499a2ea21c22dab29fd8f807052f13091036929c48Yuichi Arakiimport static android.support.test.espresso.matcher.ViewMatchers.isNotChecked; 50910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; 51910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.withId; 52910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.withText; 53910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas 54910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.hamcrest.core.AllOf.allOf; 55910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.junit.Assert.assertEquals; 569c937474b223328601b3c4cb3fa236971c721b2eYuichi Arakiimport static org.junit.Assert.assertFalse; 57910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.junit.Assert.assertNotNull; 58910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.junit.Assert.assertTrue; 59910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.mock; 60910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.times; 61910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.verify; 62910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.verifyNoMoreInteractions; 63910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas 64c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viveretteimport android.annotation.TargetApi; 65c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovimport android.content.res.Resources; 669c937474b223328601b3c4cb3fa236971c721b2eYuichi Arakiimport android.os.Build; 679a2ea21c22dab29fd8f807052f13091036929c48Yuichi Arakiimport android.os.Parcelable; 688ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.support.annotation.ColorInt; 69a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikovimport android.support.annotation.IdRes; 70c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovimport android.support.design.test.R; 71910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport android.support.design.testutils.TestDrawable; 72e6cf359406cd7baaa0659b54c1b7d8ac45db122aAurimas Liutikasimport android.support.test.filters.LargeTest; 7324e362dd19caffb820011c08125c1a301ba819f8Yuichi Arakiimport android.support.test.filters.SdkSuppress; 748ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.support.v4.content.res.ResourcesCompat; 75c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovimport android.support.v4.view.GravityCompat; 76c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovimport android.support.v4.widget.DrawerLayout; 778ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport android.support.v7.widget.RecyclerView; 781ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikovimport android.support.v7.widget.SwitchCompat; 799a2ea21c22dab29fd8f807052f13091036929c48Yuichi Arakiimport android.util.SparseArray; 80a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikovimport android.view.LayoutInflater; 81a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikovimport android.view.Menu; 82a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikovimport android.view.MenuItem; 83a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikovimport android.view.View; 84f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Arakiimport android.widget.TextView; 85f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki 868ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport org.hamcrest.Matcher; 87c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovimport org.junit.Before; 88c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovimport org.junit.Test; 89c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 908ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport java.util.HashMap; 918ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikovimport java.util.Map; 928ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 93e6cf359406cd7baaa0659b54c1b7d8ac45db122aAurimas Liutikas@LargeTest 94c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikovpublic class NavigationViewTest 95c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov extends BaseInstrumentationTestCase<NavigationViewActivity> { 968ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov private static final int[] MENU_CONTENT_ITEM_IDS = { R.id.destination_home, 978ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.id.destination_profile, R.id.destination_people, R.id.destination_settings }; 988ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov private Map<Integer, String> mMenuStringContent; 998ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 100c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov private DrawerLayout mDrawerLayout; 101c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 102f16fff9d2dc208f57e8d5d29da986e3e563da9a8Dake Gu private NavigationTestView mNavigationView; 103c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 104c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov public NavigationViewTest() { 105c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov super(NavigationViewActivity.class); 106c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov } 107c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 108c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov @Before 109c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov public void setUp() throws Exception { 110c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov final NavigationViewActivity activity = mActivityTestRule.getActivity(); 111c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov mDrawerLayout = (DrawerLayout) activity.findViewById(R.id.drawer_layout); 112f16fff9d2dc208f57e8d5d29da986e3e563da9a8Dake Gu mNavigationView = (NavigationTestView) mDrawerLayout.findViewById(R.id.start_drawer); 113c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 114c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov // Close the drawer to reset the state for the next test 115c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(closeDrawer(GravityCompat.START)); 1168ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 1178ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final Resources res = activity.getResources(); 1188ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov mMenuStringContent = new HashMap<>(MENU_CONTENT_ITEM_IDS.length); 1198ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov mMenuStringContent.put(R.id.destination_home, res.getString(R.string.navigate_home)); 1208ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov mMenuStringContent.put(R.id.destination_profile, res.getString(R.string.navigate_profile)); 1218ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov mMenuStringContent.put(R.id.destination_people, res.getString(R.string.navigate_people)); 1228ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov mMenuStringContent.put(R.id.destination_settings, 1238ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov res.getString(R.string.navigate_settings)); 124c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov } 125c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 126c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov @Test 127c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov public void testBasics() { 128c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov // Open our drawer 129c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 130c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 131a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Check the contents of the Menu object 132a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final Menu menu = mNavigationView.getMenu(); 133a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov assertNotNull("Menu should not be null", menu); 134f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki assertEquals("Should have matching number of items", MENU_CONTENT_ITEM_IDS.length + 1, 135a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov menu.size()); 136a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 137a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final MenuItem currItem = menu.getItem(i); 138a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov assertEquals("ID for Item #" + i, MENU_CONTENT_ITEM_IDS[i], currItem.getItemId()); 139a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 140a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 1418ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Check that we have the expected menu items in our NavigationView 1428ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 1438ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])), 1448ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches(isDisplayed())); 1458ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 1468ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 1478ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 1488ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov @Test 1499c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki public void testWillNotDraw() { 1509c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki // Open our drawer 1519c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 1529c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki 1539c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki if (Build.VERSION.SDK_INT >= 21) { 154f16fff9d2dc208f57e8d5d29da986e3e563da9a8Dake Gu if (mNavigationView.hasSystemWindowInsets()) { 155f16fff9d2dc208f57e8d5d29da986e3e563da9a8Dake Gu assertFalse(mNavigationView.willNotDraw()); 156f16fff9d2dc208f57e8d5d29da986e3e563da9a8Dake Gu } else { 157f16fff9d2dc208f57e8d5d29da986e3e563da9a8Dake Gu assertTrue(mNavigationView.willNotDraw()); 158f16fff9d2dc208f57e8d5d29da986e3e563da9a8Dake Gu } 1599c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki } else { 1609c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki assertTrue(mNavigationView.willNotDraw()); 1619c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki } 1629c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki } 1639c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki 1649c937474b223328601b3c4cb3fa236971c721b2eYuichi Araki @Test 1658ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov public void testTextAppearance() { 1668ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Open our drawer 1678ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 1688ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 169c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov final Resources res = mActivityTestRule.getActivity().getResources(); 1708ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final int defaultTextSize = res.getDimensionPixelSize(R.dimen.text_medium_size); 171c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov 1728ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Check the default style of the menu items in our NavigationView 1738ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 1748ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])), 1758ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check( 1768ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov matches(withTextSize(defaultTextSize))); 1778ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 1788ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 1798ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Set a new text appearance on our NavigationView 1808ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemTextAppearance(R.style.TextSmallStyle)); 1818ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 1828ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // And check that all the menu items have the new style 1838ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final int newTextSize = res.getDimensionPixelSize(R.dimen.text_small_size); 1848ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 1858ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])), 1868ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check( 1878ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov matches(withTextSize(newTextSize))); 1888ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 1898ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 1908ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 1918ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov @Test 1928ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov public void testTextColor() { 1938ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Open our drawer 1948ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 1958ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 1968ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final Resources res = mActivityTestRule.getActivity().getResources(); 1978ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final @ColorInt int defaultTextColor = ResourcesCompat.getColor(res, 1988ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.color.emerald_text, null); 1998ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2008ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Check the default text color of the menu items in our NavigationView 2018ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 2028ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])), 2038ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check( 2048ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov matches(withTextColor(defaultTextColor))); 2058ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 2068ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2078ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Set a new text color on our NavigationView 2088ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemTextColor( 2098ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov ResourcesCompat.getColorStateList(res, R.color.color_state_list_lilac, null))); 2108ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2118ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // And check that all the menu items have the new color 2128ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final @ColorInt int newTextColor = ResourcesCompat.getColor(res, 2138ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.color.lilac_default, null); 2148ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 2158ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])), 2168ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check( 2178ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov matches(withTextColor(newTextColor))); 2188ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 2198ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 2208ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2218ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov @Test 2228ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov public void testBackground() { 2238ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Open our drawer 2248ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 2258ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2268ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final Resources res = mActivityTestRule.getActivity().getResources(); 2278ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final @ColorInt int defaultFillColor = ResourcesCompat.getColor(res, 2288ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.color.sand_default, null); 2298ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2308ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Check the default fill color of the menu items in our NavigationView 2318ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 2328ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Note that here we're tying ourselves to the implementation details of the 2338ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // internal structure of the NavigationView. Specifically, we're looking at the 2348ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // direct child of RecyclerView which is expected to have the background set 2358ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // on it. If the internal implementation of NavigationView changes, the second 2368ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Matcher below will need to be tweaked. 2378ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov Matcher menuItemMatcher = allOf( 2388ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov hasDescendant(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i]))), 2398ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isChildOfA(isAssignableFrom(RecyclerView.class)), 2408ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer))); 2418ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2428ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(menuItemMatcher).check(matches(withBackgroundFill(defaultFillColor))); 2438ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 2448ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2458ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Set a new background (flat fill color) on our NavigationView 2468ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemBackgroundResource( 2478ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.drawable.test_background_blue)); 2488ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2498ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // And check that all the menu items have the new fill 2508ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final @ColorInt int newFillColorBlue = ResourcesCompat.getColor(res, 2518ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.color.test_blue, null); 2528ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 2538ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov Matcher menuItemMatcher = allOf( 2548ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov hasDescendant(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i]))), 2558ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isChildOfA(isAssignableFrom(RecyclerView.class)), 2568ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer))); 2578ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2588ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(menuItemMatcher).check(matches(withBackgroundFill(newFillColorBlue))); 2598ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 2608ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2618ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Set another new background on our NavigationView 2628ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemBackground( 2638ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov ResourcesCompat.getDrawable(res, R.drawable.test_background_green, null))); 2648ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2658ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // And check that all the menu items have the new fill 2668ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final @ColorInt int newFillColorGreen = ResourcesCompat.getColor(res, 2678ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.color.test_green, null); 2688ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 2698ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov Matcher menuItemMatcher = allOf( 2708ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov hasDescendant(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i]))), 2718ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isChildOfA(isAssignableFrom(RecyclerView.class)), 2728ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer))); 2738ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2748ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(menuItemMatcher).check(matches(withBackgroundFill(newFillColorGreen))); 2758ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 2768ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov } 2778ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2788ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov @Test 2798ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov public void testIconTinting() { 2808ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Open our drawer 2818ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 2828ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2838ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final Resources res = mActivityTestRule.getActivity().getResources(); 28488f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov final @ColorInt int redFill = ResourcesCompat.getColor(res, R.color.test_red, null); 28588f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov final @ColorInt int greenFill = ResourcesCompat.getColor(res, R.color.test_green, null); 28688f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov final @ColorInt int blueFill = ResourcesCompat.getColor(res, R.color.test_blue, null); 28788f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov final int iconSize = res.getDimensionPixelSize(R.dimen.drawable_small_size); 28888f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setIconForMenuItem(R.id.destination_home, 28988f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov new TestDrawable(redFill, iconSize, iconSize))); 29088f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setIconForMenuItem(R.id.destination_profile, 29188f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov new TestDrawable(greenFill, iconSize, iconSize))); 29288f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setIconForMenuItem(R.id.destination_people, 29388f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov new TestDrawable(blueFill, iconSize, iconSize))); 29488f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov 2958ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final @ColorInt int defaultTintColor = ResourcesCompat.getColor(res, 2968ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.color.emerald_translucent, null); 2978ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 2988ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // We're allowing a margin of error in checking the color of the items' icons. 2998ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // This is due to the translucent color being used in the icon tinting 3008ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // and off-by-one discrepancies of SRC_IN when it's compositing 3018ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // translucent color. Note that all the checks below are written for the current 3028ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // logic on NavigationView that uses the default SRC_IN tint mode - effectively 3038ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // replacing all non-transparent pixels in the destination (original icon) with 3048ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // our translucent tint color. 3058ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final int allowedComponentVariance = 1; 3068ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 3078ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Note that here we're tying ourselves to the implementation details of the 3088ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // internal structure of the NavigationView. Specifically, we're checking the 3098ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // start drawable of the text view with the specific text. If the internal 3108ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // implementation of NavigationView changes, the second Matcher in the lookups 3118ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // below will need to be tweaked. 3128ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)), 3138ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 3148ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov withStartDrawableFilledWith(defaultTintColor, allowedComponentVariance))); 3158ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)), 3168ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 3178ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov withStartDrawableFilledWith(defaultTintColor, allowedComponentVariance))); 3188ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)), 3198ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 3208ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov withStartDrawableFilledWith(defaultTintColor, allowedComponentVariance))); 3218ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 3228ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov final @ColorInt int newTintColor = ResourcesCompat.getColor(res, 3238ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov R.color.red_translucent, null); 3248ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 3258ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemIconTintList( 3268ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov ResourcesCompat.getColorStateList(res, R.color.color_state_list_red_translucent, 3278ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov null))); 3288ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Check that all menu items with icons now have icons tinted with the newly set color 3298ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)), 3308ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 3318ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov withStartDrawableFilledWith(newTintColor, allowedComponentVariance))); 3328ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)), 3338ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 3348ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov withStartDrawableFilledWith(newTintColor, allowedComponentVariance))); 3358ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)), 3368ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 3378ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov withStartDrawableFilledWith(newTintColor, allowedComponentVariance))); 3388ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov 3398ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // And now remove all icon tinting 3408ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemIconTintList(null)); 3418ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // And verify that all menu items with icons now have the original colors for their icons. 3428ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // Note that since there is no tinting at this point, we don't allow any color variance 3438ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov // in these checks. 3448ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)), 3458ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 34688f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov withStartDrawableFilledWith(redFill, 0))); 3478ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)), 3488ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 34988f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov withStartDrawableFilledWith(greenFill, 0))); 3508ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)), 3518ea47e618ba5dad21c7b023aa998979eebcf2103Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).check(matches( 35288f685bc75d52b18f45f22c99ef8d4910708a3e3Kirill Grouchnikov withStartDrawableFilledWith(blueFill, 0))); 353c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov } 354a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 355a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov /** 356a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov * Gets the list of header IDs (which can be empty) and verifies that the actual header content 357a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov * of our navigation view matches the expected header content. 358a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov */ 359a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov private void verifyHeaders(@IdRes int ... expectedHeaderIds) { 360a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final int expectedHeaderCount = (expectedHeaderIds != null) ? expectedHeaderIds.length : 0; 361a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final int actualHeaderCount = mNavigationView.getHeaderCount(); 362a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov assertEquals("Header count", expectedHeaderCount, actualHeaderCount); 363a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 364a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov if (expectedHeaderCount > 0) { 365a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov for (int i = 0; i < expectedHeaderCount; i++) { 366a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final View currentHeader = mNavigationView.getHeaderView(i); 367a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov assertEquals("Header at #" + i, expectedHeaderIds[i], currentHeader.getId()); 368a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 369a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 370a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 371a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 372a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov @Test 373a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov public void testHeaders() { 374a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Open our drawer 375a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 376a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 377a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // We should have no headers at the start 378a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyHeaders(); 379a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 380a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Inflate one header and check that it's there in the navigation view 381a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform( 382a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov inflateHeaderView(R.layout.design_navigation_view_header1)); 383a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyHeaders(R.id.header1); 384a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 385a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final LayoutInflater inflater = LayoutInflater.from(mActivityTestRule.getActivity()); 386a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 387a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Add one more header and check that it's there in the navigation view 388a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform( 389a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov addHeaderView(inflater, R.layout.design_navigation_view_header2)); 390a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyHeaders(R.id.header1, R.id.header2); 391a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 392a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final View header1 = mNavigationView.findViewById(R.id.header1); 393a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Remove the first header and check that we still have the second header 394a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform(removeHeaderView(header1)); 395a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyHeaders(R.id.header2); 396a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 397a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Add one more header and check that we now have two headers 398a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform( 399a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov inflateHeaderView(R.layout.design_navigation_view_header3)); 400a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyHeaders(R.id.header2, R.id.header3); 401a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 402a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Add another "copy" of the header from the just-added layout and check that we now 403a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // have three headers 404a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform( 405a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov addHeaderView(inflater, R.layout.design_navigation_view_header3)); 406a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyHeaders(R.id.header2, R.id.header3, R.id.header3); 407a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 408a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 40924e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki @SdkSuppress(minSdkVersion = 11) 410c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette @TargetApi(11) 411a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov @Test 4129a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki public void testHeaderState() { 4139a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki // Open our drawer 4149a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 4159a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 4169a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki // Inflate a header with a toggle switch and check that it's there in the navigation view 4179a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki onView(withId(R.id.start_drawer)).perform( 4189a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki inflateHeaderView(R.layout.design_navigation_view_header_switch)); 4199a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki verifyHeaders(R.id.header_frame); 4209a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 4219a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki onView(withId(R.id.header_toggle)) 4229a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki .check(matches(isNotChecked())) 4239a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki .perform(click()) 4249a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki .check(matches(isChecked())); 4259a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 4269a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki // Save the current state 4279a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki SparseArray<Parcelable> container = new SparseArray<>(); 4289a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki mNavigationView.saveHierarchyState(container); 4299a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 4309a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki // Remove the header 4319a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki final View header = mNavigationView.findViewById(R.id.header_frame); 4329a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki onView(withId(R.id.start_drawer)).perform(removeHeaderView(header)); 4339a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki verifyHeaders(); 4349a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 4359a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki // Inflate the header again 4369a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki onView(withId(R.id.start_drawer)).perform( 4379a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki inflateHeaderView(R.layout.design_navigation_view_header_switch)); 4389a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki verifyHeaders(R.id.header_frame); 4399a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 4409a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki // Restore the saved state 4419a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki onView(withId(R.id.start_drawer)).perform( 4429a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki restoreHierarchyState(container)); 4439a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 4449a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki // Confirm that the state was restored 4459a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki onView(withId(R.id.header_toggle)) 4469a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki .check(matches(isChecked())); 4479a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki } 4489a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki 44924e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki @SdkSuppress(minSdkVersion = 11) 450c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette @TargetApi(11) 45124e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki @Test 45224e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki public void testActionViewState() { 45324e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki // Open our drawer 45424e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 45524e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki 45624e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki final Menu menu = mNavigationView.getMenu(); 45724e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki onView(isActionViewOf(menu, R.id.destination_people)) 45824e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .check(matches(isNotChecked())) // Not checked by default 45924e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .perform(click()) // Check it 46024e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .check(matches(isChecked())); 46124e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki 46224e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki // Remove the other action view to simulate the case where it is not yet inflated 46324e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki onView(isActionViewOf(menu, R.id.destination_custom)) 46424e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .check(matches(isDisplayed())); 46524e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki onView(withId(R.id.start_drawer)) 46624e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .perform(removeMenuItem(R.id.destination_custom)); 46724e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki 46824e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki // Save the current state 46924e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki SparseArray<Parcelable> container = new SparseArray<>(); 47024e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki mNavigationView.saveHierarchyState(container); 47124e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki 47224e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki // Restore the saved state 47324e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki onView(withId(R.id.start_drawer)) 47424e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .perform(reinflateMenu(R.menu.navigation_view_content)) 47524e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .perform(restoreHierarchyState(container)); 47624e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki 47724e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki // Checked state should be restored 47824e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki onView(isActionViewOf(menu, R.id.destination_people)) 47924e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki .check(matches(isChecked())); 48024e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki } 48124e362dd19caffb820011c08125c1a301ba819f8Yuichi Araki 4829a2ea21c22dab29fd8f807052f13091036929c48Yuichi Araki @Test 483a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov public void testNavigationSelectionListener() { 484a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Open our drawer 485a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 486a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 487a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Click one of our items 488a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)), 489a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).perform(click()); 490a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Check that the drawer is still open 491a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov assertTrue("Drawer is still open after click", 492a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov mDrawerLayout.isDrawerOpen(GravityCompat.START)); 493a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 494a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Register a listener 4958cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov NavigationView.OnNavigationItemSelectedListener mockedListener = 4968cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov mock(NavigationView.OnNavigationItemSelectedListener.class); 4978cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov mNavigationView.setNavigationItemSelectedListener(mockedListener); 498a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 499a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Click one of our items 500a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)), 501a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).perform(click()); 502a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Check that the drawer is still open 503a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov assertTrue("Drawer is still open after click", 504a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov mDrawerLayout.isDrawerOpen(GravityCompat.START)); 505a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // And that our listener has been notified of the click 5068cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov verify(mockedListener, times(1)).onNavigationItemSelected( 5078cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov mNavigationView.getMenu().findItem(R.id.destination_profile)); 508a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 5098cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov // Set null listener to test that the next click is not going to notify the 5108cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov // previously set listener 511a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov mNavigationView.setNavigationItemSelectedListener(null); 512a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 513a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Click one of our items 514a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_settings)), 515a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).perform(click()); 516a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Check that the drawer is still open 517a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov assertTrue("Drawer is still open after click", 518a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov mDrawerLayout.isDrawerOpen(GravityCompat.START)); 519a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // And that our previous listener has not been notified of the click 5208cf1dce2d2266ea5b1d42e95af81490d4d201802Kirill Grouchnikov verifyNoMoreInteractions(mockedListener); 521a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 522a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 523a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov private void verifyCheckedAppearance(@IdRes int checkedItemId, 524a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov @ColorInt int uncheckedItemForeground, @ColorInt int checkedItemForeground, 525a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov @ColorInt int uncheckedItemBackground, @ColorInt int checkedItemBackground) { 526a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) { 527a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final boolean expectedToBeChecked = (MENU_CONTENT_ITEM_IDS[i] == checkedItemId); 528a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final @ColorInt int expectedItemForeground = 529a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov expectedToBeChecked ? checkedItemForeground : uncheckedItemForeground; 530a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final @ColorInt int expectedItemBackground = 531a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov expectedToBeChecked ? checkedItemBackground : uncheckedItemBackground; 532a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 533a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // For the background fill check we need to select a view that has its background 534a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // set by the current implementation (see disclaimer in testBackground) 535a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov Matcher menuItemMatcher = allOf( 536a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov hasDescendant(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i]))), 537a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isChildOfA(isAssignableFrom(RecyclerView.class)), 538a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer))); 539a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(menuItemMatcher).check(matches(withBackgroundFill(expectedItemBackground))); 540a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 541a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // And for the foreground color check we need to select a view with the text content 542a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov Matcher menuItemTextMatcher = allOf( 543a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])), 544a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer))); 545a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(menuItemTextMatcher).check(matches(withTextColor(expectedItemForeground))); 546a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 547a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 548a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 549a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov @Test 550a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov public void testCheckedAppearance() { 551a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Open our drawer 552a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 553a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 554a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Reconfigure our navigation view to use foreground (text) and background visuals 555a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // with explicitly different colors for the checked state 556a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final Resources res = mActivityTestRule.getActivity().getResources(); 557a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemTextColor( 558a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov ResourcesCompat.getColorStateList(res, R.color.color_state_list_sand, null))); 559a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setItemBackgroundResource( 560a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov R.drawable.test_drawable_state_list)); 561a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 562a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final @ColorInt int uncheckedItemForeground = ResourcesCompat.getColor(res, 563a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov R.color.sand_default, null); 564a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final @ColorInt int checkedItemForeground = ResourcesCompat.getColor(res, 565a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov R.color.sand_checked, null); 566a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final @ColorInt int uncheckedItemBackground = ResourcesCompat.getColor(res, 567a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov R.color.test_green, null); 568a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov final @ColorInt int checkedItemBackground = ResourcesCompat.getColor(res, 569a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov R.color.test_blue, null); 570a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 571a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Verify that all items are rendered with unchecked visuals 572a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyCheckedAppearance(0, uncheckedItemForeground, checkedItemForeground, 573a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov uncheckedItemBackground, checkedItemBackground); 574a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 575a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Mark one of the items as checked 576a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(withId(R.id.start_drawer)).perform(setCheckedItem(R.id.destination_profile)); 577a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // And verify that it's now rendered with checked visuals 578a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyCheckedAppearance(R.id.destination_profile, 579a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov uncheckedItemForeground, checkedItemForeground, 580a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov uncheckedItemBackground, checkedItemBackground); 581a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 582a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Register a navigation listener that "marks" the selected item 583a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov mNavigationView.setNavigationItemSelectedListener( 584a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov new NavigationView.OnNavigationItemSelectedListener() { 585a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov @Override 586a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov public boolean onNavigationItemSelected(MenuItem item) { 587a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov return true; 588a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 589a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov }); 590a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 591a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Click one of our items 592a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)), 593a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).perform(click()); 594a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // and verify that it's now checked 595a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyCheckedAppearance(R.id.destination_people, 596a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov uncheckedItemForeground, checkedItemForeground, 597a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov uncheckedItemBackground, checkedItemBackground); 598a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 599a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Register a navigation listener that doesn't "mark" the selected item 600a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov mNavigationView.setNavigationItemSelectedListener( 601a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov new NavigationView.OnNavigationItemSelectedListener() { 602a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov @Override 603a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov public boolean onNavigationItemSelected(MenuItem item) { 604a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov return false; 605a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 606a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov }); 607a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov 608a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // Click another items 609a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov onView(allOf(withText(mMenuStringContent.get(R.id.destination_settings)), 610a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)))).perform(click()); 611a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // and verify that the checked state remains on the previously clicked item 612a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // since the current navigation listener returns false from its callback 613a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov // implementation 614a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov verifyCheckedAppearance(R.id.destination_people, 615a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov uncheckedItemForeground, checkedItemForeground, 616a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov uncheckedItemBackground, checkedItemBackground); 617a3c0da0361aa877077aeb21df876226def2f98caKirill Grouchnikov } 6181ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov 6191ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov @Test 6201ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov public void testActionLayout() { 6211ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // Open our drawer 6221ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START)); 6231ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov 6241ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // There are four conditions to "find" the menu item with action layout (switch): 6251ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // 1. Is in the NavigationView 6261ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // 2. Is direct child of a class that extends RecyclerView 6271ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // 3. Has a child with "people" text 6281ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // 4. Has fully displayed child that extends SwitchCompat 6291ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // Note that condition 2 makes a certain assumption about the internal implementation 6301ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // details of the NavigationMenu, while conditions 3 and 4 aim to be as generic as 6311ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // possible and to not rely on the internal details of the current layout implementation 6321ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // of an individual menu item in NavigationMenu. 6331ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov Matcher menuItemMatcher = allOf( 6341ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov isDescendantOfA(withId(R.id.start_drawer)), 6351ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov isChildOfA(isAssignableFrom(RecyclerView.class)), 6361ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov hasDescendant(withText(mMenuStringContent.get(R.id.destination_people))), 6371ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov hasDescendant(allOf( 6381ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov isAssignableFrom(SwitchCompat.class), 6391ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov isCompletelyDisplayed()))); 6401ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov 6411ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // While we don't need to perform any action on our row, the invocation of perform() 6421ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // makes our matcher actually run. If for some reason NavigationView fails to inflate and 6431ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov // display our SwitchCompat action layout, the next line will fail in the matcher pass. 6441ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov onView(menuItemMatcher).perform(click()); 645f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki 646f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki // Check that the full custom view is displayed without title and icon. 647f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki final Resources res = mActivityTestRule.getActivity().getResources(); 648f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki Matcher customItemMatcher = allOf( 649f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki isDescendantOfA(withId(R.id.start_drawer)), 650f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki isChildOfA(isAssignableFrom(RecyclerView.class)), 651f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki hasDescendant(withText(res.getString(R.string.navigate_custom))), 652f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki hasDescendant(allOf( 653f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki isAssignableFrom(TextView.class), 654f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki withEffectiveVisibility(Visibility.GONE)))); 655f3865fbd67715b07d43da357dea742edf3bf9913Yuichi Araki onView(customItemMatcher).perform(click()); 6561ba555a31dcff069a4b9beb4d552203fab2d2691Kirill Grouchnikov } 657c10ba2544591704e7c4adbe98da6a485a8b19230Kirill Grouchnikov} 658