1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.browser.app.appmenu; 6 7 import android.content.pm.ActivityInfo; 8 import android.support.test.InstrumentationRegistry; 9 import android.view.KeyEvent; 10 import android.view.Menu; 11 import android.view.MenuItem; 12 import android.view.View; 13 import android.widget.LinearLayout; 14 import android.widget.ListView; 15 import android.widget.TextView; 16 17 import androidx.test.filters.SmallTest; 18 19 import org.hamcrest.Matchers; 20 import org.junit.Assert; 21 import org.junit.Before; 22 import org.junit.Rule; 23 import org.junit.Test; 24 import org.junit.runner.RunWith; 25 26 import org.chromium.base.Callback; 27 import org.chromium.base.task.PostTask; 28 import org.chromium.base.test.util.CallbackHelper; 29 import org.chromium.base.test.util.CommandLineFlags; 30 import org.chromium.base.test.util.Criteria; 31 import org.chromium.base.test.util.CriteriaHelper; 32 import org.chromium.base.test.util.DisableIf; 33 import org.chromium.base.test.util.DisabledTest; 34 import org.chromium.base.test.util.Feature; 35 import org.chromium.base.test.util.Restriction; 36 import org.chromium.base.test.util.UrlUtils; 37 import org.chromium.chrome.R; 38 import org.chromium.chrome.browser.ChromeTabbedActivity; 39 import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; 40 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; 41 import org.chromium.chrome.browser.flags.ChromeFeatureList; 42 import org.chromium.chrome.browser.flags.ChromeSwitches; 43 import org.chromium.chrome.browser.share.ShareUtils; 44 import org.chromium.chrome.browser.tab.Tab; 45 import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler; 46 import org.chromium.chrome.browser.ui.appmenu.AppMenuTestSupport; 47 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; 48 import org.chromium.chrome.test.ChromeTabbedActivityTestRule; 49 import org.chromium.chrome.test.util.ChromeRenderTestRule; 50 import org.chromium.chrome.test.util.ChromeTabUtils; 51 import org.chromium.chrome.test.util.browser.Features.DisableFeatures; 52 import org.chromium.chrome.test.util.browser.Features.EnableFeatures; 53 import org.chromium.content_public.browser.UiThreadTaskTraits; 54 import org.chromium.content_public.browser.test.util.TestThreadUtils; 55 import org.chromium.content_public.browser.test.util.TestTouchUtils; 56 import org.chromium.ui.modaldialog.ModalDialogProperties; 57 import org.chromium.ui.modelutil.PropertyModel; 58 import org.chromium.ui.test.util.UiDisableIf; 59 import org.chromium.ui.test.util.UiRestriction; 60 61 import java.io.IOException; 62 import java.util.concurrent.TimeoutException; 63 64 /** 65 * Tests tabbed mode app menu popup. 66 */ 67 @RunWith(ChromeJUnit4ClassRunner.class) 68 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) 69 public class TabbedAppMenuTest { 70 @Rule 71 public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); 72 @Rule 73 public ChromeRenderTestRule mRenderTestRule = 74 ChromeRenderTestRule.Builder.withPublicCorpus().build(); 75 76 private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>foo</html>"); 77 private static final String TEST_URL2 = UrlUtils.encodeHtmlDataUri("<html>bar</html>"); 78 79 private AppMenuHandler mAppMenuHandler; 80 81 int mLastSelectedItemId = -1; 82 private Callback<MenuItem> mItemSelectedCallback = 83 (item) -> mLastSelectedItemId = item.getItemId(); 84 85 @Before setUp()86 public void setUp() { 87 // We need list selection; ensure we are not in touch mode. 88 InstrumentationRegistry.getInstrumentation().setInTouchMode(false); 89 90 mActivityTestRule.startMainActivityWithURL(TEST_URL); 91 92 AppMenuTestSupport.overrideOnOptionItemSelectedListener( 93 mActivityTestRule.getAppMenuCoordinator(), mItemSelectedCallback); 94 mAppMenuHandler = mActivityTestRule.getAppMenuCoordinator().getAppMenuHandler(); 95 96 showAppMenuAndAssertMenuShown(); 97 98 PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> getListView().setSelection(0)); 99 CriteriaHelper.pollInstrumentationThread( 100 () -> Criteria.checkThat(getCurrentFocusedRow(), Matchers.is(0))); 101 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 102 } 103 104 /** 105 * Verify opening a new tab from the menu. 106 */ 107 @Test 108 @SmallTest 109 @Feature({"Browser", "Main"}) testMenuNewTab()110 public void testMenuNewTab() { 111 final int tabCountBefore = mActivityTestRule.getActivity().getCurrentTabModel().getCount(); 112 ChromeTabUtils.newTabFromMenu(InstrumentationRegistry.getInstrumentation(), 113 (ChromeTabbedActivity) mActivityTestRule.getActivity()); 114 final int tabCountAfter = mActivityTestRule.getActivity().getCurrentTabModel().getCount(); 115 Assert.assertTrue("Expected: " + (tabCountBefore + 1) + " Got: " + tabCountAfter, 116 tabCountBefore + 1 == tabCountAfter); 117 } 118 119 /** 120 * Test bounds when accessing the menu through the keyboard. 121 * Make sure that the menu stays open when trying to move past the first and last items. 122 */ 123 @Test 124 @SmallTest 125 @Feature({"Browser", "Main"}) testKeyboardMenuBoundaries()126 public void testKeyboardMenuBoundaries() { 127 moveToBoundary(false, true); 128 Assert.assertEquals(getCount() - 1, getCurrentFocusedRow()); 129 moveToBoundary(true, true); 130 Assert.assertEquals(0, getCurrentFocusedRow()); 131 moveToBoundary(false, true); 132 Assert.assertEquals(getCount() - 1, getCurrentFocusedRow()); 133 } 134 135 /** 136 * Test that typing ENTER immediately opening the menu works. 137 */ 138 @Test 139 @SmallTest 140 @Feature({"Browser", "Main"}) testKeyboardMenuEnterOnOpen()141 public void testKeyboardMenuEnterOnOpen() { 142 hitEnterAndAssertAppMenuDismissed(); 143 } 144 145 /** 146 * Test that hitting ENTER past the top item doesn't crash Chrome. 147 */ 148 @Test 149 @SmallTest 150 @Feature({"Browser", "Main"}) testKeyboardEnterAfterMovePastTopItem()151 public void testKeyboardEnterAfterMovePastTopItem() { 152 moveToBoundary(true, true); 153 Assert.assertEquals(0, getCurrentFocusedRow()); 154 hitEnterAndAssertAppMenuDismissed(); 155 } 156 157 /** 158 * Test that hitting ENTER past the bottom item doesn't crash Chrome. 159 * Catches regressions for http://crbug.com/181067 160 */ 161 @Test 162 @SmallTest 163 @Feature({"Browser", "Main"}) testKeyboardEnterAfterMovePastBottomItem()164 public void testKeyboardEnterAfterMovePastBottomItem() { 165 moveToBoundary(false, true); 166 Assert.assertEquals(getCount() - 1, getCurrentFocusedRow()); 167 hitEnterAndAssertAppMenuDismissed(); 168 } 169 170 /** 171 * Test that hitting ENTER on the top item actually triggers the top item. 172 * Catches regressions for https://crbug.com/191239 for shrunken menus. 173 */ 174 /* 175 @SmallTest 176 @Feature({"Browser", "Main"}) 177 */ 178 @Test 179 @DisabledTest(message = "crbug.com/945861") testKeyboardMenuEnterOnTopItemLandscape()180 public void testKeyboardMenuEnterOnTopItemLandscape() { 181 mActivityTestRule.getActivity().setRequestedOrientation( 182 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 183 showAppMenuAndAssertMenuShown(); 184 moveToBoundary(true, false); 185 Assert.assertEquals(0, getCurrentFocusedRow()); 186 hitEnterAndAssertAppMenuDismissed(); 187 } 188 189 /** 190 * Test that hitting ENTER on the top item doesn't crash Chrome. 191 */ 192 @Test 193 @SmallTest 194 @Feature({"Browser", "Main"}) testKeyboardMenuEnterOnTopItemPortrait()195 public void testKeyboardMenuEnterOnTopItemPortrait() { 196 mActivityTestRule.getActivity().setRequestedOrientation( 197 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 198 showAppMenuAndAssertMenuShown(); 199 moveToBoundary(true, false); 200 Assert.assertEquals(0, getCurrentFocusedRow()); 201 hitEnterAndAssertAppMenuDismissed(); 202 } 203 204 @Test 205 @SmallTest 206 @Feature({"Browser", "Main"}) 207 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) testHideMenuOnToggleOverview()208 public void testHideMenuOnToggleOverview() throws TimeoutException { 209 CallbackHelper overviewModeFinishedShowingCallback = new CallbackHelper(); 210 OverviewModeBehavior.OverviewModeObserver overviewModeObserver = 211 new EmptyOverviewModeObserver() { 212 @Override 213 public void onOverviewModeFinishedShowing() { 214 overviewModeFinishedShowingCallback.notifyCalled(); 215 } 216 }; 217 218 // App menu is shown during setup. 219 Assert.assertTrue("App menu should be showing.", mAppMenuHandler.isAppMenuShowing()); 220 Assert.assertFalse("Overview shouldn't be showing.", 221 mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible()); 222 223 TestThreadUtils.runOnUiThreadBlocking(() -> { 224 mActivityTestRule.getActivity().getLayoutManager().addOverviewModeObserver( 225 overviewModeObserver); 226 mActivityTestRule.getActivity().getLayoutManager().showOverview(false); 227 }); 228 overviewModeFinishedShowingCallback.waitForCallback(0); 229 230 Assert.assertTrue("Overview should be showing.", 231 mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible()); 232 Assert.assertFalse("App menu shouldn't be showing.", mAppMenuHandler.isAppMenuShowing()); 233 TestThreadUtils.runOnUiThreadBlocking(() -> { 234 Assert.assertTrue("App menu should be allowed to show.", 235 AppMenuTestSupport.shouldShowAppMenu( 236 mActivityTestRule.getAppMenuCoordinator())); 237 }); 238 showAppMenuAndAssertMenuShown(); 239 240 TestThreadUtils.runOnUiThreadBlocking( 241 () -> mActivityTestRule.getActivity().getLayoutManager().hideOverview(false)); 242 Assert.assertFalse("Overview shouldn't be showing.", 243 mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible()); 244 CriteriaHelper.pollUiThread( 245 () -> !mAppMenuHandler.isAppMenuShowing(), "App menu shouldn't be showing."); 246 } 247 248 @Test 249 @SmallTest 250 @Feature({"Browser", "Main", "Bookmark", "RenderTest"}) 251 @DisableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_REGROUP, 252 ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_ICONS}) 253 @DisableIf.Device(type = {UiDisableIf.TABLET}) // See https://crbug.com/1065043. 254 public void testBookmarkMenuItem()255 testBookmarkMenuItem() throws IOException { 256 MenuItem bookmarkStar = 257 AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 258 .findItem(R.id.bookmark_this_page_id); 259 Assert.assertFalse("Bookmark item should not be checked.", bookmarkStar.isChecked()); 260 Assert.assertEquals("Incorrect content description.", 261 mActivityTestRule.getActivity().getString(R.string.menu_bookmark), 262 bookmarkStar.getTitleCondensed()); 263 mRenderTestRule.render(getListView().getChildAt(0), "icon_row"); 264 265 TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); 266 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(true); 267 showAppMenuAndAssertMenuShown(); 268 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 269 270 bookmarkStar = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 271 .findItem(R.id.bookmark_this_page_id); 272 Assert.assertTrue("Bookmark item should be checked.", bookmarkStar.isChecked()); 273 Assert.assertEquals("Incorrect content description for bookmarked page.", 274 mActivityTestRule.getActivity().getString(R.string.edit_bookmark), 275 bookmarkStar.getTitleCondensed()); 276 mRenderTestRule.render(getListView().getChildAt(0), "icon_row_page_bookmarked"); 277 278 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(null); 279 } 280 281 @Test 282 @SmallTest 283 @Feature({"Browser", "Main", "RenderTest"}) 284 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 285 @EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_REGROUP + "<Study"}) 286 @CommandLineFlags.Add({"force-fieldtrials=Study/Group", 287 "force-fieldtrial-params=Study.Group:action_bar/backward_button"}) 288 public void testBackButtonMenuItem()289 testBackButtonMenuItem() throws IOException { 290 MenuItem backArrow = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 291 .findItem(R.id.backward_menu_id); 292 Assert.assertFalse("Backward button item should be disabled.", backArrow.isEnabled()); 293 Assert.assertEquals("Incorrect content description.", 294 mActivityTestRule.getActivity().getString(R.string.back), 295 backArrow.getTitleCondensed()); 296 mRenderTestRule.render(getListView().getChildAt(0), "icon_row_backward_diabled"); 297 298 TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); 299 mActivityTestRule.loadUrl(TEST_URL2); 300 showAppMenuAndAssertMenuShown(); 301 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 302 303 backArrow = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 304 .findItem(R.id.backward_menu_id); 305 Assert.assertTrue("Backward button item should be enabled.", backArrow.isEnabled()); 306 307 LinearLayout actionBar = (LinearLayout) getListView().getChildAt(0); 308 Assert.assertEquals(5, actionBar.getChildCount()); 309 310 mRenderTestRule.render(getListView().getChildAt(0), "icon_row_backward_enabled"); 311 312 selectMenuItem(R.id.backward_menu_id); 313 TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); 314 ShareUtils shareUtils = new ShareUtils(); 315 CriteriaHelper.pollUiThread(() -> { 316 Tab tab = mActivityTestRule.getActivity().getActivityTab(); 317 Criteria.checkThat(tab, Matchers.notNullValue()); 318 Criteria.checkThat(tab.getUrlString(), Matchers.is(TEST_URL)); 319 Criteria.checkThat(shareUtils.shouldEnableShare(tab), Matchers.is(false)); 320 }); 321 showAppMenuAndAssertMenuShown(); 322 backArrow = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 323 .findItem(R.id.backward_menu_id); 324 Assert.assertFalse("Backward button item should be disabled.", backArrow.isEnabled()); 325 } 326 327 @Test 328 @SmallTest 329 @Feature({"Browser", "Main", "RenderTest"}) 330 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 331 @EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_REGROUP + "<Study"}) 332 @CommandLineFlags.Add({"force-fieldtrials=Study/Group", 333 "force-fieldtrial-params=Study.Group:action_bar/share_button"}) 334 public void testShareButtonMenuItem()335 testShareButtonMenuItem() throws IOException { 336 MenuItem shareButton = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 337 .findItem(R.id.share_menu_button_id); 338 Assert.assertFalse("Share button item should be disabled.", shareButton.isEnabled()); 339 Assert.assertEquals("Incorrect content description.", 340 mActivityTestRule.getActivity().getString(R.string.share), 341 shareButton.getTitleCondensed()); 342 mRenderTestRule.render(getListView().getChildAt(0), "icon_row_share_diabled"); 343 344 TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); 345 mActivityTestRule.loadUrl(mActivityTestRule.getTestServer().getURL( 346 "/chrome/test/data/android/contextualsearch/tap_test.html")); 347 showAppMenuAndAssertMenuShown(); 348 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 349 350 shareButton = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 351 .findItem(R.id.share_menu_button_id); 352 Assert.assertTrue("Share button item should be enabled.", shareButton.isEnabled()); 353 354 LinearLayout actionBar = (LinearLayout) getListView().getChildAt(0); 355 Assert.assertEquals(5, actionBar.getChildCount()); 356 mRenderTestRule.render(getListView().getChildAt(0), "icon_row_share_enabled"); 357 } 358 359 @Test 360 @SmallTest 361 @Feature({"Browser", "Main", "RenderTest"}) 362 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 363 @EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_THREE_BUTTON_ACTIONBAR + "<Study"}) 364 @CommandLineFlags.Add({"force-fieldtrials=Study/Group", 365 "force-fieldtrial-params=Study.Group:three_button_action_bar/action_chip_view"}) 366 public void testActionChipViewMenuItem()367 testActionChipViewMenuItem() throws IOException { 368 LinearLayout actionBar = (LinearLayout) getListView().getChildAt(0); 369 Assert.assertEquals(3, actionBar.getChildCount()); 370 mRenderTestRule.render(getListView().getChildAt(0), "tinted_icon_row_three_buttons"); 371 372 int downloadRowIndex = findIndexOfMenuItemById(R.id.downloads_row_menu_id); 373 Assert.assertNotEquals("No download row found.", -1, downloadRowIndex); 374 mRenderTestRule.render(getListView().getChildAt(downloadRowIndex), 375 "download_row_rounded_action_chip_view"); 376 377 MenuItem bookmarkRow = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 378 .findItem(R.id.all_bookmarks_row_menu_id); 379 MenuItem bookmarkMenuItem = bookmarkRow.getSubMenu().getItem(1); 380 Assert.assertFalse("Bookmark item should not be checked.", bookmarkMenuItem.isChecked()); 381 int bookmarkRowIndex = findIndexOfMenuItemById(R.id.all_bookmarks_row_menu_id); 382 Assert.assertTrue("No bookmark row found.", bookmarkRowIndex != -1); 383 mRenderTestRule.render(getListView().getChildAt(bookmarkRowIndex), 384 "bookmark_row_rounded_action_chip_view"); 385 386 TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); 387 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(true); 388 showAppMenuAndAssertMenuShown(); 389 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 390 391 bookmarkRow = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 392 .findItem(R.id.all_bookmarks_row_menu_id); 393 bookmarkMenuItem = bookmarkRow.getSubMenu().getItem(1); 394 Assert.assertTrue("Bookmark item should be checked.", bookmarkMenuItem.isChecked()); 395 mRenderTestRule.render(getListView().getChildAt(bookmarkRowIndex), 396 "bookmark_row_rounded_action_chip_view_bookmarked"); 397 398 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(null); 399 } 400 401 @Test 402 @SmallTest 403 @Feature({"Browser", "Main", "RenderTest"}) 404 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 405 @EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_THREE_BUTTON_ACTIONBAR + "<Study"}) 406 @CommandLineFlags.Add({"force-fieldtrials=Study/Group", 407 "force-fieldtrial-params=Study.Group:three_button_action_bar/destination_chip_view"}) 408 public void testDestinationChipViewMenuItem()409 testDestinationChipViewMenuItem() throws IOException { 410 LinearLayout actionBar = (LinearLayout) getListView().getChildAt(0); 411 Assert.assertEquals(3, actionBar.getChildCount()); 412 mRenderTestRule.render(getListView().getChildAt(0), "tinted_icon_row_three_buttons"); 413 414 int downloadRowIndex = findIndexOfMenuItemById(R.id.downloads_row_menu_id); 415 Assert.assertNotEquals("No download row found.", -1, downloadRowIndex); 416 mRenderTestRule.render(getListView().getChildAt(downloadRowIndex), 417 "download_row_rounded_destination_chip_view"); 418 419 MenuItem bookmarkRow = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 420 .findItem(R.id.all_bookmarks_row_menu_id); 421 MenuItem bookmarkMenuItem = bookmarkRow.getSubMenu().getItem(1); 422 Assert.assertFalse("Bookmark item should not be checked.", bookmarkMenuItem.isChecked()); 423 int bookmarkRowIndex = findIndexOfMenuItemById(R.id.all_bookmarks_row_menu_id); 424 Assert.assertTrue("No bookmark row found.", bookmarkRowIndex != -1); 425 mRenderTestRule.render(getListView().getChildAt(bookmarkRowIndex), 426 "bookmark_row_rounded_destination_chip_view"); 427 428 TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); 429 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(true); 430 showAppMenuAndAssertMenuShown(); 431 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 432 433 bookmarkRow = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) 434 .findItem(R.id.all_bookmarks_row_menu_id); 435 bookmarkMenuItem = bookmarkRow.getSubMenu().getItem(1); 436 Assert.assertTrue("Bookmark item should be checked.", bookmarkMenuItem.isChecked()); 437 mRenderTestRule.render(getListView().getChildAt(bookmarkRowIndex), 438 "bookmark_row_rounded_destination_chip_view_bookmarked"); 439 440 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(null); 441 } 442 443 @Test 444 @SmallTest 445 @Feature({"Browser", "Main", "RenderTest"}) 446 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 447 @EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_THREE_BUTTON_ACTIONBAR + "<Study"}) 448 @CommandLineFlags.Add({"force-fieldtrials=Study/Group", 449 "force-fieldtrial-params=Study.Group:three_button_action_bar/add_to_option"}) 450 public void testAddToMenuItem_not_bookmarked()451 testAddToMenuItem_not_bookmarked() throws IOException { 452 LinearLayout actionBar = (LinearLayout) getListView().getChildAt(0); 453 Assert.assertEquals(3, actionBar.getChildCount()); 454 mRenderTestRule.render(getListView().getChildAt(0), "tinted_icon_row_three_buttons"); 455 456 int addToIndex = findIndexOfMenuItemById(R.id.add_to_menu_id); 457 Assert.assertNotEquals("No add to row found.", -1, addToIndex); 458 mRenderTestRule.render(getListView().getChildAt(addToIndex), "add_to_menu_item"); 459 460 View addToItem = getListView().getChildAt(addToIndex); 461 PropertyModel dialogModel = clickAndGetCurrentDialog(addToItem); 462 Assert.assertNotNull("No add to dialog found.", dialogModel); 463 LinearLayout addToCustomView = 464 (LinearLayout) dialogModel.get(ModalDialogProperties.CUSTOM_VIEW); 465 Assert.assertEquals("The dialog should have 2 children, one is title, another is ListView.", 466 2, addToCustomView.getChildCount()); 467 TextView addToTitle = (TextView) addToCustomView.getChildAt(0); 468 mRenderTestRule.render(addToTitle, "menu_add_to_dialog_title"); 469 ListView addToList = (ListView) addToCustomView.getChildAt(1); 470 Assert.assertEquals(3, addToList.getChildCount()); 471 mRenderTestRule.render(addToList, "items_in_add_to_dialog_not_bookmarked"); 472 } 473 474 @Test 475 @SmallTest 476 @Feature({"Browser", "Main", "RenderTest"}) 477 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 478 @EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_THREE_BUTTON_ACTIONBAR + "<Study"}) 479 @CommandLineFlags.Add({"force-fieldtrials=Study/Group", 480 "force-fieldtrial-params=Study.Group:three_button_action_bar/add_to_option"}) 481 public void testAddToMenuItem_bookmarked()482 testAddToMenuItem_bookmarked() throws IOException { 483 TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); 484 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(true); 485 showAppMenuAndAssertMenuShown(); 486 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 487 LinearLayout actionBar = (LinearLayout) getListView().getChildAt(0); 488 Assert.assertEquals("Add to Bookmarks/Downloads/Home screen should be shown", 3, 489 actionBar.getChildCount()); 490 mRenderTestRule.render(getListView().getChildAt(0), "tinted_icon_row_three_buttons"); 491 492 int addToIndex = findIndexOfMenuItemById(R.id.add_to_menu_id); 493 Assert.assertNotEquals("No add to row found.", -1, addToIndex); 494 mRenderTestRule.render(getListView().getChildAt(addToIndex), "add_to_menu_item"); 495 496 View addToItem = getListView().getChildAt(addToIndex); 497 PropertyModel dialogModel = clickAndGetCurrentDialog(addToItem); 498 Assert.assertNotNull("No add to dialog found.", dialogModel); 499 LinearLayout addToCustomView = 500 (LinearLayout) dialogModel.get(ModalDialogProperties.CUSTOM_VIEW); 501 Assert.assertEquals("The dialog should have 2 children, one is title, another is ListView.", 502 2, addToCustomView.getChildCount()); 503 TextView addToTitle = (TextView) addToCustomView.getChildAt(0); 504 mRenderTestRule.render(addToTitle, "menu_add_to_dialog_title"); 505 ListView addToList = (ListView) addToCustomView.getChildAt(1); 506 Assert.assertEquals(3, addToList.getChildCount()); 507 mRenderTestRule.render(addToList, "items_in_add_to_dialog_bookmarked"); 508 509 AppMenuPropertiesDelegateImpl.setPageBookmarkedForTesting(null); 510 } 511 512 @Test 513 @SmallTest 514 @Feature({"Browser", "Main", "RenderTest"}) 515 @EnableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_REGROUP}) testDividerLineMenuItem()516 public void testDividerLineMenuItem() throws IOException { 517 int firstDividerLineIndex = findIndexOfMenuItemById(R.id.divider_line_id); 518 Assert.assertTrue("No divider line found.", firstDividerLineIndex != -1); 519 mRenderTestRule.render(getListView().getChildAt(firstDividerLineIndex), "divider_line"); 520 } 521 showAppMenuAndAssertMenuShown()522 private void showAppMenuAndAssertMenuShown() { 523 TestThreadUtils.runOnUiThreadBlocking(() -> { 524 AppMenuTestSupport.showAppMenu(mActivityTestRule.getAppMenuCoordinator(), null, false); 525 Assert.assertTrue(mAppMenuHandler.isAppMenuShowing()); 526 }); 527 } 528 hitEnterAndAssertAppMenuDismissed()529 private void hitEnterAndAssertAppMenuDismissed() { 530 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 531 pressKey(KeyEvent.KEYCODE_ENTER); 532 CriteriaHelper.pollInstrumentationThread( 533 () -> !mAppMenuHandler.isAppMenuShowing(), "AppMenu did not dismiss"); 534 } 535 moveToBoundary(boolean towardsTop, boolean movePast)536 private void moveToBoundary(boolean towardsTop, boolean movePast) { 537 // Move to the boundary. 538 final int end = towardsTop ? 0 : getCount() - 1; 539 int increment = towardsTop ? -1 : 1; 540 for (int index = getCurrentFocusedRow(); index != end; index += increment) { 541 pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN); 542 final int expectedPosition = index + increment; 543 CriteriaHelper.pollInstrumentationThread(() -> { 544 Criteria.checkThat(getCurrentFocusedRow(), Matchers.is(expectedPosition)); 545 }); 546 } 547 548 // Try moving past it by one. 549 if (movePast) { 550 pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN); 551 CriteriaHelper.pollInstrumentationThread( 552 () -> Criteria.checkThat(getCurrentFocusedRow(), Matchers.is(end))); 553 } 554 555 // The menu should stay open. 556 Assert.assertTrue(mAppMenuHandler.isAppMenuShowing()); 557 } 558 pressKey(final int keycode)559 private void pressKey(final int keycode) { 560 final View view = getListView(); 561 PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { 562 view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode)); 563 view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode)); 564 }); 565 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); 566 } 567 getCurrentFocusedRow()568 private int getCurrentFocusedRow() { 569 ListView listView = getListView(); 570 if (listView == null) return ListView.INVALID_POSITION; 571 return listView.getSelectedItemPosition(); 572 } 573 getCount()574 private int getCount() { 575 ListView listView = getListView(); 576 if (listView == null) return 0; 577 return listView.getCount(); 578 } 579 getListView()580 private ListView getListView() { 581 return AppMenuTestSupport.getListView(mActivityTestRule.getAppMenuCoordinator()); 582 } 583 selectMenuItem(int id)584 private void selectMenuItem(int id) { 585 CriteriaHelper.pollUiThread( 586 () -> { mActivityTestRule.getActivity().onMenuOrKeyboardAction(id, true); }); 587 } 588 findIndexOfMenuItemById(int id)589 private int findIndexOfMenuItemById(int id) { 590 Menu menu = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()); 591 int firstMenuItemIndex = -1; 592 boolean foundMenuItem = false; 593 for (int i = 0; i < menu.size(); i++) { 594 MenuItem item = menu.getItem(i); 595 if (item.isVisible()) { 596 firstMenuItemIndex++; 597 } 598 if (item.getItemId() == id) { 599 foundMenuItem = true; 600 break; 601 } 602 } 603 604 return foundMenuItem ? firstMenuItemIndex : -1; 605 } 606 clickAndGetCurrentDialog(View view)607 private PropertyModel clickAndGetCurrentDialog(View view) { 608 TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(), view); 609 CriteriaHelper.pollUiThread(() -> { 610 PropertyModel propertyModel = mActivityTestRule.getActivity() 611 .getModalDialogManager() 612 .getCurrentDialogForTest(); 613 Criteria.checkThat(propertyModel, Matchers.notNullValue()); 614 }); 615 return TestThreadUtils.runOnUiThreadBlockingNoException( 616 () 617 -> mActivityTestRule.getActivity() 618 .getModalDialogManager() 619 .getCurrentDialogForTest()); 620 } 621 } 622