Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.widget.cts;
     18 
     19 import static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertFalse;
     21 import static org.junit.Assert.assertNotNull;
     22 import static org.junit.Assert.assertNull;
     23 import static org.junit.Assert.assertTrue;
     24 import static org.mockito.Mockito.any;
     25 import static org.mockito.Mockito.mock;
     26 import static org.mockito.Mockito.never;
     27 import static org.mockito.Mockito.times;
     28 import static org.mockito.Mockito.verify;
     29 import static org.mockito.Mockito.verifyNoMoreInteractions;
     30 
     31 import android.app.Instrumentation;
     32 import android.graphics.Color;
     33 import android.graphics.drawable.Drawable;
     34 import android.os.SystemClock;
     35 import android.view.KeyEvent;
     36 import android.view.Menu;
     37 import android.view.MenuItem;
     38 import android.view.View;
     39 import android.widget.Toolbar;
     40 import android.widget.cts.util.TestUtils;
     41 
     42 import androidx.test.InstrumentationRegistry;
     43 import androidx.test.annotation.UiThreadTest;
     44 import androidx.test.filters.MediumTest;
     45 import androidx.test.rule.ActivityTestRule;
     46 import androidx.test.runner.AndroidJUnit4;
     47 
     48 import com.android.compatibility.common.util.PollingCheck;
     49 import com.android.compatibility.common.util.WidgetTestUtils;
     50 
     51 import org.junit.Before;
     52 import org.junit.Rule;
     53 import org.junit.Test;
     54 import org.junit.runner.RunWith;
     55 
     56 @MediumTest
     57 @RunWith(AndroidJUnit4.class)
     58 public class ToolbarTest {
     59     private Instrumentation mInstrumentation;
     60     private ToolbarCtsActivity mActivity;
     61     private Toolbar mMainToolbar;
     62 
     63     @Rule
     64     public ActivityTestRule<ToolbarCtsActivity> mActivityRule =
     65             new ActivityTestRule<>(ToolbarCtsActivity.class);
     66 
     67     @Before
     68     public void setup() {
     69         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     70         mActivity = mActivityRule.getActivity();
     71         mMainToolbar = mActivity.getMainToolbar();
     72     }
     73 
     74     @Test
     75     public void testConstructor() {
     76         new Toolbar(mActivity);
     77 
     78         new Toolbar(mActivity, null);
     79 
     80         new Toolbar(mActivity, null, android.R.attr.toolbarStyle);
     81 
     82         new Toolbar(mActivity, null, 0, android.R.style.Widget_Material_Toolbar);
     83     }
     84 
     85     @Test
     86     public void testTitleAndSubtitleContent() throws Throwable {
     87         // Note that this method is *not* annotated to run on the UI thread, and every
     88         // call to setTitle / setSubtitle is wrapped to wait until the next draw pass
     89         // of our main toolbar. While this is not strictly necessary to check the result
     90         // of getTitle / getSubtitle, this logic follows the path of deferred layout
     91         // and invalidation of the TextViews that show the title / subtitle in the Toolbar.
     92 
     93         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
     94                 () -> mMainToolbar.setTitle(R.string.toolbar_title));
     95         assertEquals(mActivity.getString(R.string.toolbar_title), mMainToolbar.getTitle());
     96 
     97         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
     98                 () -> mMainToolbar.setTitle("New title"));
     99         assertEquals("New title", mMainToolbar.getTitle());
    100 
    101         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    102                 () -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
    103         assertEquals(mActivity.getString(R.string.toolbar_subtitle), mMainToolbar.getSubtitle());
    104 
    105         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    106                 () -> mMainToolbar.setSubtitle("New subtitle"));
    107         assertEquals("New subtitle", mMainToolbar.getSubtitle());
    108     }
    109 
    110     @Test
    111     public void testTitleAndSubtitleAppearance() throws Throwable {
    112         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    113                 () -> mMainToolbar.setTitle(R.string.toolbar_title));
    114         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    115                 () -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
    116 
    117         // Since there are no APIs to get reference to the underlying implementation of
    118         // title and subtitle, here we are testing that calling the relevant APIs doesn't crash
    119 
    120         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    121                 () -> mMainToolbar.setTitleTextColor(Color.RED));
    122         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    123                 () -> mMainToolbar.setSubtitleTextColor(Color.BLUE));
    124 
    125         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    126                 () -> mMainToolbar.setTitleTextAppearance(
    127                         mActivity, R.style.TextAppearance_NotColors));
    128         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    129                 () -> mMainToolbar.setSubtitleTextAppearance(
    130                         mActivity, R.style.TextAppearance_WithColor));
    131     }
    132 
    133     @Test
    134     public void testMenuContent() throws Throwable {
    135         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    136                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    137 
    138         final Menu menu = mMainToolbar.getMenu();
    139 
    140         assertEquals(6, menu.size());
    141         assertEquals(R.id.action_highlight, menu.getItem(0).getItemId());
    142         assertEquals(R.id.action_edit, menu.getItem(1).getItemId());
    143         assertEquals(R.id.action_delete, menu.getItem(2).getItemId());
    144         assertEquals(R.id.action_ignore, menu.getItem(3).getItemId());
    145         assertEquals(R.id.action_share, menu.getItem(4).getItemId());
    146         assertEquals(R.id.action_print, menu.getItem(5).getItemId());
    147 
    148         assertFalse(mMainToolbar.hasExpandedActionView());
    149 
    150         Toolbar.OnMenuItemClickListener menuItemClickListener =
    151                 mock(Toolbar.OnMenuItemClickListener.class);
    152         mMainToolbar.setOnMenuItemClickListener(menuItemClickListener);
    153 
    154         menu.performIdentifierAction(R.id.action_highlight, 0);
    155         verify(menuItemClickListener, times(1)).onMenuItemClick(
    156                 menu.findItem(R.id.action_highlight));
    157 
    158         menu.performIdentifierAction(R.id.action_share, 0);
    159         verify(menuItemClickListener, times(1)).onMenuItemClick(
    160                 menu.findItem(R.id.action_share));
    161     }
    162 
    163     @Test
    164     public void testMenuOverflowShowHide() throws Throwable {
    165         // Inflate menu and check that we're not showing overflow menu yet
    166         mActivityRule.runOnUiThread(() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    167         assertFalse(mMainToolbar.isOverflowMenuShowing());
    168 
    169         // Ask to show overflow menu and check that it's showing
    170         mActivityRule.runOnUiThread(() -> mMainToolbar.showOverflowMenu());
    171         PollingCheck.waitFor(() -> mMainToolbar.isOverflowMenuShowing());
    172 
    173         // Ask to hide the overflow menu and check that it's not showing
    174         mActivityRule.runOnUiThread(() -> mMainToolbar.hideOverflowMenu());
    175         PollingCheck.waitFor(() -> !mMainToolbar.isOverflowMenuShowing());
    176     }
    177 
    178     @Test
    179     public void testMenuOverflowSubmenu() throws Throwable {
    180         // Inflate menu and check that we're not showing overflow menu yet
    181         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    182                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    183         assertFalse(mMainToolbar.isOverflowMenuShowing());
    184 
    185         // Ask to show overflow menu and check that it's showing
    186         mActivityRule.runOnUiThread(mMainToolbar::showOverflowMenu);
    187         PollingCheck.waitFor(() -> mMainToolbar.isOverflowMenuShowing());
    188 
    189         // Register a mock menu item click listener on the toolbar
    190         Toolbar.OnMenuItemClickListener menuItemClickListener =
    191                 mock(Toolbar.OnMenuItemClickListener.class);
    192         mMainToolbar.setOnMenuItemClickListener(menuItemClickListener);
    193 
    194         final Menu menu = mMainToolbar.getMenu();
    195 
    196         // Ask to "perform" the share action and check that the menu click listener has
    197         // been notified
    198         mActivityRule.runOnUiThread(() -> menu.performIdentifierAction(R.id.action_share, 0));
    199         verify(menuItemClickListener, times(1)).onMenuItemClick(
    200                 menu.findItem(R.id.action_share));
    201 
    202         // Ask to dismiss all the popups and check that we're not showing the overflow menu
    203         mActivityRule.runOnUiThread(mMainToolbar::dismissPopupMenus);
    204         PollingCheck.waitFor(() -> !mMainToolbar.isOverflowMenuShowing());
    205     }
    206 
    207     @Test
    208     public void testMenuOverflowIcon() throws Throwable {
    209         // Inflate menu and check that we're not showing overflow menu yet
    210         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    211                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    212 
    213         final Drawable overflowIcon = mActivity.getDrawable(R.drawable.icon_red);
    214         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    215                 () -> mMainToolbar.setOverflowIcon(overflowIcon));
    216 
    217         final Drawable toolbarOverflowIcon = mMainToolbar.getOverflowIcon();
    218         TestUtils.assertAllPixelsOfColor("Overflow icon is red", toolbarOverflowIcon,
    219                 toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
    220                 true, Color.RED, 1, false);
    221     }
    222 
    223     @Test
    224     public void testActionView() throws Throwable {
    225         // Inflate menu and check that we don't have an expanded action view
    226         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    227                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu_search));
    228         assertFalse(mMainToolbar.hasExpandedActionView());
    229 
    230         // Expand search menu item's action view and verify that main toolbar has an expanded
    231         // action view
    232         final MenuItem searchMenuItem = mMainToolbar.getMenu().findItem(R.id.action_search);
    233         mActivityRule.runOnUiThread(searchMenuItem::expandActionView);
    234         PollingCheck.waitFor(() ->
    235                 searchMenuItem.isActionViewExpanded() && mMainToolbar.hasExpandedActionView());
    236 
    237         // Collapse search menu item's action view and verify that main toolbar doesn't have an
    238         // expanded action view
    239         mActivityRule.runOnUiThread(searchMenuItem::collapseActionView);
    240         PollingCheck.waitFor(() ->
    241                 !searchMenuItem.isActionViewExpanded() && !mMainToolbar.hasExpandedActionView());
    242 
    243         // Expand search menu item's action view again
    244         mActivityRule.runOnUiThread(searchMenuItem::expandActionView);
    245         PollingCheck.waitFor(() ->
    246                 searchMenuItem.isActionViewExpanded() && mMainToolbar.hasExpandedActionView());
    247 
    248         // Now collapse search menu item's action view via toolbar's API and verify that main
    249         // toolbar doesn't have an expanded action view
    250         mActivityRule.runOnUiThread(mMainToolbar::collapseActionView);
    251         PollingCheck.waitFor(() ->
    252                 !searchMenuItem.isActionViewExpanded() && !mMainToolbar.hasExpandedActionView());
    253     }
    254 
    255     @Test
    256     public void testNavigationConfiguration() throws Throwable {
    257         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    258                 () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
    259         Drawable toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
    260         TestUtils.assertAllPixelsOfColor("Navigation icon is green", toolbarNavigationIcon,
    261                 toolbarNavigationIcon.getIntrinsicWidth(),
    262                 toolbarNavigationIcon.getIntrinsicHeight(),
    263                 true, Color.GREEN, 1, false);
    264 
    265         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    266                 () -> mMainToolbar.setNavigationIcon(mActivity.getDrawable(R.drawable.icon_blue)));
    267         toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
    268         TestUtils.assertAllPixelsOfColor("Navigation icon is blue", toolbarNavigationIcon,
    269                 toolbarNavigationIcon.getIntrinsicWidth(),
    270                 toolbarNavigationIcon.getIntrinsicHeight(),
    271                 true, Color.BLUE, 1, false);
    272 
    273         mActivityRule.runOnUiThread(
    274                 () -> mMainToolbar.setNavigationContentDescription(R.string.toolbar_navigation));
    275         assertEquals(mActivity.getResources().getString(R.string.toolbar_navigation),
    276                 mMainToolbar.getNavigationContentDescription());
    277 
    278         mActivityRule.runOnUiThread(
    279                 () -> mMainToolbar.setNavigationContentDescription("Navigation legend"));
    280         assertEquals("Navigation legend", mMainToolbar.getNavigationContentDescription());
    281     }
    282 
    283     @Test
    284     public void testCollapseConfiguration() throws Throwable {
    285         // Inflate menu and expand action view to display collapse button
    286         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    287                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu_search));
    288         final MenuItem searchMenuItem = mMainToolbar.getMenu().findItem(R.id.action_search);
    289         mActivityRule.runOnUiThread(searchMenuItem::expandActionView);
    290         PollingCheck.waitFor(() ->
    291                 searchMenuItem.isActionViewExpanded() && mMainToolbar.hasExpandedActionView());
    292 
    293         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    294                 () -> mMainToolbar.setCollapseIcon(R.drawable.icon_green));
    295         Drawable toolbarCollapseIcon = mMainToolbar.getCollapseIcon();
    296         TestUtils.assertAllPixelsOfColor("Collapse icon is green", toolbarCollapseIcon,
    297                 toolbarCollapseIcon.getIntrinsicWidth(),
    298                 toolbarCollapseIcon.getIntrinsicHeight(),
    299                 true, Color.GREEN, 1, false);
    300 
    301         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    302                 () -> mMainToolbar.setCollapseIcon(mActivity.getDrawable(R.drawable.icon_blue)));
    303         toolbarCollapseIcon = mMainToolbar.getCollapseIcon();
    304         TestUtils.assertAllPixelsOfColor("Collapse icon is blue", toolbarCollapseIcon,
    305                 toolbarCollapseIcon.getIntrinsicWidth(),
    306                 toolbarCollapseIcon.getIntrinsicHeight(),
    307                 true, Color.BLUE, 1, false);
    308 
    309         mActivityRule.runOnUiThread(
    310                 () -> mMainToolbar.setCollapseContentDescription(R.string.toolbar_collapse));
    311         assertEquals(mActivity.getResources().getString(R.string.toolbar_collapse),
    312                 mMainToolbar.getCollapseContentDescription());
    313 
    314         mActivityRule.runOnUiThread(
    315                 () -> mMainToolbar.setCollapseContentDescription("Collapse legend"));
    316         assertEquals("Collapse legend", mMainToolbar.getCollapseContentDescription());
    317     }
    318 
    319     @Test
    320     public void testLogoConfiguration() throws Throwable {
    321         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    322                 () -> mMainToolbar.setLogo(R.drawable.icon_yellow));
    323         Drawable toolbarLogo = mMainToolbar.getLogo();
    324         TestUtils.assertAllPixelsOfColor("Logo is yellow", toolbarLogo,
    325                 toolbarLogo.getIntrinsicWidth(),
    326                 toolbarLogo.getIntrinsicHeight(),
    327                 true, Color.YELLOW, 1, false);
    328 
    329         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    330                 () -> mMainToolbar.setLogo(mActivity.getDrawable(R.drawable.icon_red)));
    331         toolbarLogo = mMainToolbar.getLogo();
    332         TestUtils.assertAllPixelsOfColor("Logo is red", toolbarLogo,
    333                 toolbarLogo.getIntrinsicWidth(),
    334                 toolbarLogo.getIntrinsicHeight(),
    335                 true, Color.RED, 1, false);
    336 
    337         mActivityRule.runOnUiThread(
    338                 () -> mMainToolbar.setLogoDescription(R.string.toolbar_logo));
    339         assertEquals(mActivity.getResources().getString(R.string.toolbar_logo),
    340                 mMainToolbar.getLogoDescription());
    341 
    342         mActivityRule.runOnUiThread(
    343                 () -> mMainToolbar.setLogoDescription("Logo legend"));
    344         assertEquals("Logo legend", mMainToolbar.getLogoDescription());
    345     }
    346 
    347     @UiThreadTest
    348     @Test
    349     public void testContentInsetsLtr() {
    350         mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
    351 
    352         mMainToolbar.setContentInsetsAbsolute(20, 25);
    353         assertEquals(20, mMainToolbar.getContentInsetLeft());
    354         assertEquals(20, mMainToolbar.getContentInsetStart());
    355         assertEquals(25, mMainToolbar.getContentInsetRight());
    356         assertEquals(25, mMainToolbar.getContentInsetEnd());
    357 
    358         mMainToolbar.setContentInsetsRelative(40, 20);
    359         assertEquals(40, mMainToolbar.getContentInsetLeft());
    360         assertEquals(40, mMainToolbar.getContentInsetStart());
    361         assertEquals(20, mMainToolbar.getContentInsetRight());
    362         assertEquals(20, mMainToolbar.getContentInsetEnd());
    363     }
    364 
    365     @UiThreadTest
    366     @Test
    367     public void testContentInsetsRtl() {
    368         mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
    369 
    370         mMainToolbar.setContentInsetsAbsolute(20, 25);
    371         assertEquals(20, mMainToolbar.getContentInsetLeft());
    372         assertEquals(25, mMainToolbar.getContentInsetStart());
    373         assertEquals(25, mMainToolbar.getContentInsetRight());
    374         assertEquals(20, mMainToolbar.getContentInsetEnd());
    375 
    376         mMainToolbar.setContentInsetsRelative(40, 20);
    377         assertEquals(20, mMainToolbar.getContentInsetLeft());
    378         assertEquals(40, mMainToolbar.getContentInsetStart());
    379         assertEquals(40, mMainToolbar.getContentInsetRight());
    380         assertEquals(20, mMainToolbar.getContentInsetEnd());
    381     }
    382 
    383     @Test
    384     public void testCurrentContentInsetsLtr() throws Throwable {
    385         mActivityRule.runOnUiThread(
    386                 () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
    387 
    388         mActivityRule.runOnUiThread(() -> mMainToolbar.setContentInsetsRelative(20, 25));
    389         assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
    390         assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
    391         assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
    392         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    393 
    394         mActivityRule.runOnUiThread(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
    395         assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
    396         // Since we haven't configured the navigation icon itself, the current content insets
    397         // should stay the same
    398         assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
    399         assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
    400         assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
    401         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    402 
    403         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    404                 () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
    405         assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
    406         // Since we have configured the navigation icon, and the currently set start inset with
    407         // navigation is bigger than currently set start content inset, we should be getting that
    408         // bigger value now
    409         assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
    410         assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
    411         assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
    412         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    413 
    414         mActivityRule.runOnUiThread(() -> mMainToolbar.setContentInsetEndWithActions(35));
    415         assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
    416         // Since we haven't configured the menu content, the current content insets
    417         // should stay the same
    418         assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
    419         assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
    420         assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
    421         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    422 
    423         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    424                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    425         assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
    426         // Since we have configured the menu content, and the currently set start inset with
    427         // navigation is bigger than currently set end content inset, we should be getting that
    428         // bigger value now
    429         assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
    430         assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
    431         assertEquals(35, mMainToolbar.getCurrentContentInsetRight());
    432         assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
    433     }
    434 
    435     @Test
    436     public void testCurrentContentInsetsRtl() throws Throwable {
    437         mActivityRule.runOnUiThread(
    438                 () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
    439 
    440         mActivityRule.runOnUiThread(() -> mMainToolbar.setContentInsetsRelative(20, 25));
    441         assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
    442         assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
    443         assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
    444         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    445 
    446         mActivityRule.runOnUiThread(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
    447         assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
    448         // Since we haven't configured the navigation icon itself, the current content insets
    449         // should stay the same
    450         assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
    451         assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
    452         assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
    453         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    454 
    455         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    456                 () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
    457         assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
    458         // Since we have configured the navigation icon, and the currently set start inset with
    459         // navigation is bigger than currently set start content inset, we should be getting that
    460         // bigger value now
    461         assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
    462         assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
    463         assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
    464         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    465 
    466         mActivityRule.runOnUiThread(() -> mMainToolbar.setContentInsetEndWithActions(35));
    467         assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
    468         // Since we haven't configured the menu content, the current content insets
    469         // should stay the same
    470         assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
    471         assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
    472         assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
    473         assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
    474 
    475         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    476                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    477         assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
    478         // Since we have configured the menu content, and the currently set start inset with
    479         // navigation is bigger than currently set end content inset, we should be getting that
    480         // bigger value now
    481         assertEquals(35, mMainToolbar.getCurrentContentInsetLeft());
    482         assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
    483         assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
    484         assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
    485     }
    486 
    487     @UiThreadTest
    488     @Test
    489     public void testPopupTheme() {
    490         mMainToolbar.setPopupTheme(R.style.ToolbarPopupTheme_Test);
    491         assertEquals(R.style.ToolbarPopupTheme_Test, mMainToolbar.getPopupTheme());
    492     }
    493 
    494     @UiThreadTest
    495     @Test
    496     public void testNavigationOnClickListener() {
    497         View.OnClickListener mockListener = mock(View.OnClickListener.class);
    498         mMainToolbar.setNavigationOnClickListener(mockListener);
    499 
    500         verify(mockListener, never()).onClick(any(View.class));
    501 
    502         mMainToolbar.getNavigationView().performClick();
    503         verify(mockListener, times(1)).onClick(any(View.class));
    504 
    505         verifyNoMoreInteractions(mockListener);
    506     }
    507 
    508     @Test
    509     public void testItemViewAttributes() throws Throwable {
    510         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    511                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    512 
    513         Menu menu = mMainToolbar.getMenu();
    514 
    515         MenuItem menuItem1 = menu.findItem(R.id.action_highlight);
    516         assertNotNull(menuItem1.getContentDescription());
    517         assertNotNull(menuItem1.getTooltipText());
    518 
    519         View itemView1 = mActivity.findViewById(menuItem1.getItemId());
    520         assertEquals(menuItem1.getContentDescription(), itemView1.getContentDescription());
    521         assertEquals(menuItem1.getTooltipText(), itemView1.getTooltipText());
    522 
    523         MenuItem menuItem2 = menu.findItem(R.id.action_edit);
    524         assertNull(menuItem2.getContentDescription());
    525         assertNull(menuItem2.getTooltipText());
    526 
    527         View itemView2 = mActivity.findViewById(menuItem2.getItemId());
    528         assertEquals(menuItem2.getTitle(), itemView2.getContentDescription());
    529         assertEquals(menuItem2.getTitle(), itemView2.getTooltipText());
    530     }
    531 
    532     @Test
    533     public void testKeyShortcuts() throws Throwable {
    534         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mMainToolbar,
    535                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
    536 
    537         final Boolean[] shareItemClicked = new Boolean[]{false};
    538         mMainToolbar.getMenu().findItem(R.id.action_share).setOnMenuItemClickListener(
    539                 item -> shareItemClicked[0] = true);
    540 
    541         // Make sure valid menu shortcuts get handled by toolbar menu
    542         long now = SystemClock.uptimeMillis();
    543         KeyEvent handledShortcutKey = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
    544                 KeyEvent.KEYCODE_S, 0, KeyEvent.META_CTRL_ON);
    545         mInstrumentation.runOnMainSync(() ->
    546                 assertTrue(mActivity.dispatchKeyShortcutEvent(handledShortcutKey))
    547         );
    548         assertTrue(shareItemClicked[0]);
    549 
    550         final KeyEvent unhandledShortcutKey = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
    551                 KeyEvent.KEYCODE_A, 0, KeyEvent.META_CTRL_ON);
    552 
    553         // Make sure we aren't eating unused shortcuts.
    554         mInstrumentation.runOnMainSync(() ->
    555                 assertFalse(mActivity.dispatchKeyShortcutEvent(unhandledShortcutKey))
    556         );
    557 
    558         mActivity.resetCounts();
    559 
    560         // Make sure that unhandled shortcuts don't prepare menus (since toolbar is handling that).
    561         mInstrumentation.sendKeySync(unhandledShortcutKey);
    562         assertEquals(1, mActivity.mKeyShortcutCount);
    563         assertEquals(0, mActivity.mPrepareMenuCount);
    564         assertEquals(0, mActivity.mCreateMenuCount);
    565     }
    566 }
    567