1e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas/*
2e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * Copyright (C) 2016 The Android Open Source Project
3e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas *
4e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * Licensed under the Apache License, Version 2.0 (the "License");
5e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * you may not use this file except in compliance with the License.
6e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * You may obtain a copy of the License at
7e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas *
8e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas *      http://www.apache.org/licenses/LICENSE-2.0
9e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas *
10e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * Unless required by applicable law or agreed to in writing, software
11e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * distributed under the License is distributed on an "AS IS" BASIS,
12e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * See the License for the specific language governing permissions and
14e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas * limitations under the License.
15e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas */
16e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikaspackage android.support.design.widget;
17e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
18910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.BottomNavigationViewActions.setIconForMenuItem;
19910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.design.testutils.BottomNavigationViewActions.setItemIconTintList;
20e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport static android.support.test.espresso.Espresso.onView;
21e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport static android.support.test.espresso.action.ViewActions.click;
22910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.assertion.ViewAssertions.matches;
23910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA;
2403cbbe6c4bb2f52c0f67e961e12d869d93163b59Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
25910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.withId;
26910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.withText;
27910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
28910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.hamcrest.core.AllOf.allOf;
29910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.junit.Assert.assertEquals;
30578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikasimport static org.junit.Assert.assertFalse;
31910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.junit.Assert.assertNotNull;
32578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikasimport static org.junit.Assert.assertTrue;
33578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikasimport static org.mockito.Matchers.any;
34910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.mock;
356b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Korenimport static org.mockito.Mockito.never;
36910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.times;
37910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.verify;
38910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport static org.mockito.Mockito.verifyNoMoreInteractions;
39578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikasimport static org.mockito.Mockito.when;
40e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
41ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheevimport android.app.Activity;
42e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport android.content.res.Resources;
43ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheevimport android.os.Build;
44b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Korenimport android.os.Parcelable;
45910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport android.support.annotation.ColorInt;
46e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport android.support.design.test.R;
47910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport android.support.design.testutils.TestDrawable;
48910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport android.support.design.testutils.TestUtilsMatchers;
4980c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikasimport android.support.test.annotation.UiThreadTest;
5035232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikasimport android.support.test.filters.LargeTest;
51ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheevimport android.support.test.filters.SdkSuppress;
52754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.SmallTest;
53910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikasimport android.support.v4.content.res.ResourcesCompat;
54e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport android.view.Menu;
55e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport android.view.MenuItem;
56ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheevimport android.view.MotionEvent;
57ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheevimport android.view.PointerIcon;
58ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheevimport android.view.View;
59c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Korenimport android.view.ViewGroup;
60e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
61e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport org.junit.Before;
62e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport org.junit.Test;
63e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
64e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport java.util.HashMap;
65e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikasimport java.util.Map;
66e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
67e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikaspublic class BottomNavigationViewTest
68e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        extends BaseInstrumentationTestCase<BottomNavigationViewActivity> {
69e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    private static final int[] MENU_CONTENT_ITEM_IDS = { R.id.destination_home,
70e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas            R.id.destination_profile, R.id.destination_people };
71e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    private Map<Integer, String> mMenuStringContent;
72e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
73e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    private BottomNavigationView mBottomNavigation;
74e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
75e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    public BottomNavigationViewTest() {
76e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        super(BottomNavigationViewActivity.class);
77e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    }
78e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
79e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    @Before
80e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    public void setUp() throws Exception {
81e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        final BottomNavigationViewActivity activity = mActivityTestRule.getActivity();
82e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        mBottomNavigation = (BottomNavigationView) activity.findViewById(R.id.bottom_navigation);
83e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
84e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        final Resources res = activity.getResources();
85e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        mMenuStringContent = new HashMap<>(MENU_CONTENT_ITEM_IDS.length);
86e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        mMenuStringContent.put(R.id.destination_home, res.getString(R.string.navigate_home));
87e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        mMenuStringContent.put(R.id.destination_profile, res.getString(R.string.navigate_profile));
88e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        mMenuStringContent.put(R.id.destination_people, res.getString(R.string.navigate_people));
89e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    }
90e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
9180c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas    @UiThreadTest
9280c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas    @Test
9380c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas    @SmallTest
9480c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas    public void testAddItemsWithoutMenuInflation() {
9580c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        BottomNavigationView navigation = new BottomNavigationView(mActivityTestRule.getActivity());
9680c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        mActivityTestRule.getActivity().setContentView(navigation);
9780c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        navigation.getMenu().add("Item1");
9880c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        navigation.getMenu().add("Item2");
9980c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        assertEquals(2, navigation.getMenu().size());
10080c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        navigation.getMenu().removeItem(0);
10180c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        navigation.getMenu().removeItem(0);
10280c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas        assertEquals(0, navigation.getMenu().size());
10380c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas    }
10480c46a0294ce910b675c27326cd677a724ddd7bfAurimas Liutikas
105e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    @Test
106e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    @SmallTest
107e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    public void testBasics() {
108e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        // Check the contents of the Menu object
109e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        final Menu menu = mBottomNavigation.getMenu();
110e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        assertNotNull("Menu should not be null", menu);
111e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        assertEquals("Should have matching number of items", MENU_CONTENT_ITEM_IDS.length,
112e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas                menu.size());
113e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
114e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas            final MenuItem currItem = menu.getItem(i);
115e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas            assertEquals("ID for Item #" + i, MENU_CONTENT_ITEM_IDS[i], currItem.getItemId());
116e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        }
117e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
118e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    }
119e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
120e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    @Test
12135232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikas    @LargeTest
122e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    public void testNavigationSelectionListener() {
123e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        BottomNavigationView.OnNavigationItemSelectedListener mockedListener =
124e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas                mock(BottomNavigationView.OnNavigationItemSelectedListener.class);
125e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        mBottomNavigation.setOnNavigationItemSelectedListener(mockedListener);
126e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
127578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // Make the listener return true to allow selecting the item.
128578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        when(mockedListener.onNavigationItemSelected(any(MenuItem.class))).thenReturn(true);
129e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
13003cbbe6c4bb2f52c0f67e961e12d869d93163b59Aurimas Liutikas                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
131578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // Verify our listener has been notified of the click
132e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        verify(mockedListener, times(1)).onNavigationItemSelected(
133e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas                mBottomNavigation.getMenu().findItem(R.id.destination_profile));
134578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // Verify the item is now selected
135578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
136578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas
1376b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Select the same item again
1386b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
1396b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
1406b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify our listener has been notified of the click
1416b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verify(mockedListener, times(2)).onNavigationItemSelected(
1426b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_profile));
1436b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the item is still selected
1446b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
1456b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
146578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // Make the listener return false to disallow selecting the item.
147578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        when(mockedListener.onNavigationItemSelected(any(MenuItem.class))).thenReturn(false);
148578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
149578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
150578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // Verify our listener has been notified of the click
151578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        verify(mockedListener, times(1)).onNavigationItemSelected(
152578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas                mBottomNavigation.getMenu().findItem(R.id.destination_people));
153578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // Verify the previous item is still selected
154578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        assertFalse(mBottomNavigation.getMenu().findItem(R.id.destination_people).isChecked());
155578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
156e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
157e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        // Set null listener to test that the next click is not going to notify the
158578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // previously set listener and will allow selecting items.
159e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        mBottomNavigation.setOnNavigationItemSelectedListener(null);
160e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas
161e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        // Click one of our items
162578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)),
16303cbbe6c4bb2f52c0f67e961e12d869d93163b59Aurimas Liutikas                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
164e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify that our previous listener has not been notified of the click
165e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas        verifyNoMoreInteractions(mockedListener);
166578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        // Verify the correct item is now selected.
167578015fc3e5ddc0fdb95db7ad0d00822c54be6dfAurimas Liutikas        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_home).isChecked());
168e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas    }
169910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
170e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    @UiThreadTest
171e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    @Test
172e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    @SmallTest
173e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    public void testSetSelectedItemId() {
174e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        BottomNavigationView.OnNavigationItemSelectedListener mockedListener =
175e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren                mock(BottomNavigationView.OnNavigationItemSelectedListener.class);
176e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        mBottomNavigation.setOnNavigationItemSelectedListener(mockedListener);
177e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
178e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Make the listener return true to allow selecting the item.
179e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        when(mockedListener.onNavigationItemSelected(any(MenuItem.class))).thenReturn(true);
180e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Programmatically select an item
181e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        mBottomNavigation.setSelectedItemId(R.id.destination_profile);
182e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify our listener has been notified of the click
183e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        verify(mockedListener, times(1)).onNavigationItemSelected(
184e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_profile));
185e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify the item is now selected
186e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
187e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
1886b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Select the same item
1896b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        mBottomNavigation.setSelectedItemId(R.id.destination_profile);
1906b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify our listener has been notified of the click
1916b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verify(mockedListener, times(2)).onNavigationItemSelected(
1926b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_profile));
1936b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the item is still selected
1946b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
1956b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
196e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Make the listener return false to disallow selecting the item.
197e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        when(mockedListener.onNavigationItemSelected(any(MenuItem.class))).thenReturn(false);
198e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Programmatically select an item
199e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        mBottomNavigation.setSelectedItemId(R.id.destination_people);
200e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify our listener has been notified of the click
201e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        verify(mockedListener, times(1)).onNavigationItemSelected(
202e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_people));
203e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify the previous item is still selected
204e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertFalse(mBottomNavigation.getMenu().findItem(R.id.destination_people).isChecked());
205e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
206e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
207e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Set null listener to test that the next click is not going to notify the
208e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // previously set listener and will allow selecting items.
209e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        mBottomNavigation.setOnNavigationItemSelectedListener(null);
210e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
211e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Select one of our items
212e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        mBottomNavigation.setSelectedItemId(R.id.destination_home);
213e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify that our previous listener has not been notified of the click
214e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        verifyNoMoreInteractions(mockedListener);
215e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify the correct item is now selected.
216e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_home).isChecked());
217e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    }
218e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
2196b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren    @Test
2206b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren    @SmallTest
2216b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren    public void testNavigationReselectionListener() {
2226b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Add an OnNavigationItemReselectedListener
2236b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        BottomNavigationView.OnNavigationItemReselectedListener reselectedListener =
2246b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mock(BottomNavigationView.OnNavigationItemReselectedListener.class);
2256b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        mBottomNavigation.setOnNavigationItemReselectedListener(reselectedListener);
2266b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
2276b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Select an item
2286b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
2296b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
2306b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the item is now selected
2316b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
2326b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the listener was not called
2336b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verify(reselectedListener, never()).onNavigationItemReselected(any(MenuItem.class));
2346b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
2356b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Select the same item again
2366b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
2376b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
2386b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the item is still selected
2396b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
2406b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the listener was called
2416b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verify(reselectedListener, times(1)).onNavigationItemReselected(
2426b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_profile));
2436b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
2446b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Add an OnNavigationItemSelectedListener
2456b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        BottomNavigationView.OnNavigationItemSelectedListener selectedListener =
2466b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mock(BottomNavigationView.OnNavigationItemSelectedListener.class);
2476b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        mBottomNavigation.setOnNavigationItemSelectedListener(selectedListener);
2486b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Make the listener return true to allow selecting the item.
2496b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        when(selectedListener.onNavigationItemSelected(any(MenuItem.class))).thenReturn(true);
2506b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
2516b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Select another item
2526b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
2536b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
2546b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the item is now selected
2556b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_people).isChecked());
2566b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the correct listeners were called
2576b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verify(selectedListener, times(1)).onNavigationItemSelected(
2586b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_people));
2596b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verify(reselectedListener, never()).onNavigationItemReselected(
2606b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_people));
2616b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
2626b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Select the same item again
2636b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
2646b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
2656b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the item is still selected
2666b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_people).isChecked());
2676b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the correct listeners were called
2686b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verifyNoMoreInteractions(selectedListener);
2696b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verify(reselectedListener, times(1)).onNavigationItemReselected(
2706b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                mBottomNavigation.getMenu().findItem(R.id.destination_people));
2716b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
2726b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Remove the OnNavigationItemReselectedListener
2736b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        mBottomNavigation.setOnNavigationItemReselectedListener(null);
2746b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
2756b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Select the same item again
2766b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
2776b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
2786b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the item is still selected
2796b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_people).isChecked());
2806b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        // Verify the reselectedListener was not called
2816b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren        verifyNoMoreInteractions(reselectedListener);
2826b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren    }
2836b3a399a8ed6afa4c9da88690a61efca61b61d21Jonathan Koren
284e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    @UiThreadTest
285e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    @Test
286e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    @SmallTest
287e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    public void testSelectedItemIdWithEmptyMenu() {
288e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // First item initially selected
289e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertEquals(R.id.destination_home, mBottomNavigation.getSelectedItemId());
290e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
291e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Remove all the items
292e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        for (int id : mMenuStringContent.keySet()) {
293e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren            mBottomNavigation.getMenu().removeItem(id);
294e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        }
295e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify selected ID is zero
296e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertEquals(0, mBottomNavigation.getSelectedItemId());
297e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
298e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Add an item
299e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        mBottomNavigation.getMenu().add(0, R.id.destination_home, 0, R.string.navigate_home);
300e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify item is selected
301e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertEquals(R.id.destination_home, mBottomNavigation.getSelectedItemId());
302e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
303e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Try selecting an invalid ID
304e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        mBottomNavigation.setSelectedItemId(R.id.destination_people);
305e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        // Verify the view has not changed
306e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren        assertEquals(R.id.destination_home, mBottomNavigation.getSelectedItemId());
307e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren    }
308e4c7e61dbe94a77c5389eb20952d6b7ed6536cafJonathan Koren
309910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas    @Test
310910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas    @SmallTest
311910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas    public void testIconTinting() {
312910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        final Resources res = mActivityTestRule.getActivity().getResources();
313910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        @ColorInt final int redFill = ResourcesCompat.getColor(res, R.color.test_red, null);
314910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        @ColorInt final int greenFill = ResourcesCompat.getColor(res, R.color.test_green, null);
315910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        @ColorInt final int blueFill = ResourcesCompat.getColor(res, R.color.test_blue, null);
316910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        final int iconSize = res.getDimensionPixelSize(R.dimen.drawable_small_size);
317910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(withId(R.id.bottom_navigation)).perform(setIconForMenuItem(R.id.destination_home,
318910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                new TestDrawable(redFill, iconSize, iconSize)));
319910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(withId(R.id.bottom_navigation)).perform(setIconForMenuItem(R.id.destination_profile,
320910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                new TestDrawable(greenFill, iconSize, iconSize)));
321910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(withId(R.id.bottom_navigation)).perform(setIconForMenuItem(R.id.destination_people,
322910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                new TestDrawable(blueFill, iconSize, iconSize)));
323910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
324910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        @ColorInt final int defaultTintColor = ResourcesCompat.getColor(res,
325910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                R.color.emerald_translucent, null);
326910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
327910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // We're allowing a margin of error in checking the color of the items' icons.
328910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // This is due to the translucent color being used in the icon tinting
329910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // and off-by-one discrepancies of SRC_IN when it's compositing
330910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // translucent color. Note that all the checks below are written for the current
331910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // logic on BottomNavigationView that uses the default SRC_IN tint mode - effectively
332910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // replacing all non-transparent pixels in the destination (original icon) with
333910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // our translucent tint color.
334910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        final int allowedComponentVariance = 1;
335910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
336910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // Note that here we're tying ourselves to the implementation details of the internal
337910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // structure of the BottomNavigationView. Specifically, we're checking the drawable the
338910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // ImageView with id R.id.icon. If the internal implementation of BottomNavigationView
339910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // changes, the second Matcher in the lookups below will need to be tweaked.
340910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_home)))).check(
341910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(defaultTintColor, allowedComponentVariance)));
342910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_profile)))).check(
343910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(defaultTintColor, allowedComponentVariance)));
344910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_people)))).check(
345910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(defaultTintColor, allowedComponentVariance)));
346910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
347910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        @ColorInt final int newTintColor = ResourcesCompat.getColor(res,
348910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                R.color.red_translucent, null);
349910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(withId(R.id.bottom_navigation)).perform(setItemIconTintList(
350910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                ResourcesCompat.getColorStateList(res, R.color.color_state_list_red_translucent,
351910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                        null)));
352910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // Check that all menu items with icons now have icons tinted with the newly set color
353910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_home)))).check(
354910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(newTintColor, allowedComponentVariance)));
355910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_profile)))).check(
356910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(newTintColor, allowedComponentVariance)));
357910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_people)))).check(
358910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(newTintColor, allowedComponentVariance)));
359910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas
360910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // And now remove all icon tinting
361910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(withId(R.id.bottom_navigation)).perform(setItemIconTintList(null));
362910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // And verify that all menu items with icons now have the original colors for their icons.
363910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // Note that since there is no tinting at this point, we don't allow any color variance
364910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        // in these checks.
365910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_home)))).check(
366910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(redFill, allowedComponentVariance)));
367910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_profile)))).check(
368910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(greenFill, allowedComponentVariance)));
369910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas        onView(allOf(withId(R.id.icon), isDescendantOfA(withId(R.id.destination_people)))).check(
370910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas                matches(TestUtilsMatchers.drawable(blueFill, allowedComponentVariance)));
371910de28f0a195668fad38ad2367c1f7237a7af98Aurimas Liutikas    }
37269557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas
37369557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas    @UiThreadTest
37469557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas    @Test
37569557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas    @SmallTest
37669557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas    public void testItemChecking() throws Throwable {
37769557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        final Menu menu = mBottomNavigation.getMenu();
37869557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        assertTrue(menu.getItem(0).isChecked());
37969557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        checkAndVerifyExclusiveItem(menu, R.id.destination_home);
38069557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        checkAndVerifyExclusiveItem(menu, R.id.destination_profile);
38169557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        checkAndVerifyExclusiveItem(menu, R.id.destination_people);
38269557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas    }
38369557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas
384ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev    @UiThreadTest
385ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev    @Test
386ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev    @SmallTest
387ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
388ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev    public void testPointerIcon() throws Throwable {
389ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev        final Activity activity = mActivityTestRule.getActivity();
390ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev        final PointerIcon expectedIcon = PointerIcon.getSystemIcon(activity, PointerIcon.TYPE_HAND);
391ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev        final MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
392ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev        final Menu menu = mBottomNavigation.getMenu();
393ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev        for (int i = 0; i < menu.size(); i++) {
394ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            final MenuItem item = menu.getItem(i);
395ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            assertTrue(item.isEnabled());
396ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            final View itemView = activity.findViewById(item.getItemId());
397ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            assertEquals(expectedIcon, itemView.onResolvePointerIcon(event, 0));
398ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            item.setEnabled(false);
399ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            assertEquals(null, itemView.onResolvePointerIcon(event, 0));
400ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            item.setEnabled(true);
401ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev            assertEquals(expectedIcon, itemView.onResolvePointerIcon(event, 0));
402ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev        }
403ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev    }
404ee6c89547f0f0321b66c7c21e1990e7870a45b3cVladislav Kaznacheev
4056249e1022b21b1b5a0ed40191561fe7ea5d1e1caAurimas Liutikas    @UiThreadTest
4066249e1022b21b1b5a0ed40191561fe7ea5d1e1caAurimas Liutikas    @Test
4076249e1022b21b1b5a0ed40191561fe7ea5d1e1caAurimas Liutikas    @SmallTest
4082befdb72bff253ec493612aca2b527da765ae0d1Aurimas Liutikas    public void testClearingMenu() throws Throwable {
4092befdb72bff253ec493612aca2b527da765ae0d1Aurimas Liutikas        mBottomNavigation.getMenu().clear();
4102befdb72bff253ec493612aca2b527da765ae0d1Aurimas Liutikas        assertEquals(0, mBottomNavigation.getMenu().size());
4112befdb72bff253ec493612aca2b527da765ae0d1Aurimas Liutikas        mBottomNavigation.inflateMenu(R.menu.bottom_navigation_view_content);
4122befdb72bff253ec493612aca2b527da765ae0d1Aurimas Liutikas        assertEquals(3, mBottomNavigation.getMenu().size());
4132befdb72bff253ec493612aca2b527da765ae0d1Aurimas Liutikas    }
4142befdb72bff253ec493612aca2b527da765ae0d1Aurimas Liutikas
415b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren    @Test
416b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren    @SmallTest
417b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren    public void testSavedState() throws Throwable {
418b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        // Select an item other than the first
419b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
420b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren                isDescendantOfA(withId(R.id.bottom_navigation)), isDisplayed())).perform(click());
421b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        assertTrue(mBottomNavigation.getMenu().findItem(R.id.destination_profile).isChecked());
422b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        // Save the state
423b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        final Parcelable state = mBottomNavigation.onSaveInstanceState();
424b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren
425b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        // Restore the state into a fresh BottomNavigationView
426b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        mActivityTestRule.runOnUiThread(new Runnable() {
427b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren            @Override
428b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren            public void run() {
429b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren                BottomNavigationView testView =
430b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren                        new BottomNavigationView(mActivityTestRule.getActivity());
431b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren                testView.inflateMenu(R.menu.bottom_navigation_view_content);
432b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren                testView.onRestoreInstanceState(state);
433b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren                assertTrue(testView.getMenu().findItem(R.id.destination_profile).isChecked());
434b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren            }
435b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren        });
436b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren    }
437b01c03a178cb74302b83e20820fb98a817b47e3eJonathan Koren
438c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren    @UiThreadTest
439c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren    @Test
440c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren    @SmallTest
441c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren    public void testContentDescription() {
442c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren        ViewGroup menuView = (ViewGroup) mBottomNavigation.getChildAt(0);
443c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren        final int count = menuView.getChildCount();
444c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren        for (int i = 0; i < count; i++) {
445c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren            View child = menuView.getChildAt(i);
446c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren            // We're using the same strings for content description
447c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren            assertEquals(mMenuStringContent.get(child.getId()),
448c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren                    child.getContentDescription().toString());
449c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren        }
450c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren
451c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren        menuView.getChildAt(0).getContentDescription();
452c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren    }
453c40f445372d08cc251ee70f3dfe65e4e87ee4276Jonathan Koren
45469557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas    private void checkAndVerifyExclusiveItem(final Menu menu, final int id) throws Throwable {
45569557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        menu.findItem(id).setChecked(true);
45669557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        for (int i = 0; i < menu.size(); i++) {
45769557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas            final MenuItem item = menu.getItem(i);
45869557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas            if (item.getItemId() == id) {
45969557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas                assertTrue(item.isChecked());
46069557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas            } else {
46169557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas                assertFalse(item.isChecked());
46269557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas            }
46369557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas        }
46469557a3a037e4124ecbc98560e84fa89472b3bf4Aurimas Liutikas    }
465e17fd0d6c2f79ad00d6d07e88f60d53e5b85a891Aurimas Liutikas}
466