123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// found in the LICENSE file. 423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)package org.chromium.chrome.browser.appmenu; 623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.app.Activity; 823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.content.pm.ActivityInfo; 923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.test.suitebuilder.annotation.SmallTest; 1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.view.KeyEvent; 1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.view.MenuItem; 1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.view.View; 1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.widget.ListPopupWindow; 1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import android.widget.ListView; 1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.base.ThreadUtils; 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.base.test.util.Feature; 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.chrome.shell.ChromeShellActivity; 1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.chrome.shell.ChromeShellActivity.AppMenuHandlerFactory; 2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.chrome.shell.ChromeShellTestBase; 2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.chrome.shell.R; 2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.content.browser.test.util.Criteria; 2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.content.browser.test.util.CriteriaHelper; 2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)/** 2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Tests AppMenu popup 2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)public class AppMenuTest extends ChromeShellTestBase { 2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private AppMenu mAppMenu; 3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private AppMenuHandlerForTest mAppMenuHandler; 3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * AppMenuHandler that will be used to intercept item selections for testing. 3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public static class AppMenuHandlerForTest extends AppMenuHandler { 3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int mLastSelectedItemId = -1; 3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * AppMenuHandler for intercepting options item selections. 4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public AppMenuHandlerForTest(Activity activity, AppMenuPropertiesDelegate delegate, 4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int menuResourceId) { 4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) super(activity, delegate, menuResourceId); 4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) void onOptionsItemSelected(MenuItem item) { 4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mLastSelectedItemId = item.getItemId(); 4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) protected void setUp() throws Exception { 5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) super.setUp(); 5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ChromeShellActivity.setAppMenuHandlerFactory(new AppMenuHandlerFactory() { 5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public AppMenuHandler getAppMenuHandler(Activity activity, 5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) AppMenuPropertiesDelegate delegate, int menuResourceId) { 6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenuHandler = new AppMenuHandlerForTest(activity, delegate, menuResourceId); 6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return mAppMenuHandler; 6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) }); 6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) launchChromeShellWithBlankPage(); 6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); 6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) showAppMenuAndAssertMenuShown(); 6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenu = getActivity().getAppMenuHandler().getAppMenu(); 6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ThreadUtils.runOnUiThread(new Runnable() { 7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void run() { 7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mAppMenu.getPopup().getListView().setSelection(0); 7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) }); 7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public boolean isSatisfied() { 7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return getCurrentFocusedRow() == 0; 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) })); 8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) getInstrumentation().waitForIdleSync(); 8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Test bounds when accessing the menu through the keyboard. 8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Make sure that the menu stays open when trying to move past the first and last items. 8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @SmallTest 8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Feature({"Browser", "Main"}) 9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void testKeyboardMenuBoundaries() throws InterruptedException { 9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) moveToBoundary(false, true); 9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertEquals(getCount() - 1, getCurrentFocusedRow()); 9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) moveToBoundary(true, true); 9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertEquals(0, getCurrentFocusedRow()); 9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) moveToBoundary(false, true); 9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertEquals(getCount() - 1, getCurrentFocusedRow()); 9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Test that typing ENTER immediately opening the menu works. 10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @SmallTest 10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Feature({"Browser", "Main"}) 10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void testKeyboardMenuEnterOnOpen() throws InterruptedException { 10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) hitEnterAndAssertAppMenuDismissed(); 10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Test that hitting ENTER past the top item doesn't crash Chrome. 11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @SmallTest 11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Feature({"Browser", "Main"}) 11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void testKeyboardEnterAfterMovePastTopItem() throws InterruptedException { 11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) moveToBoundary(true, true); 11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertEquals(0, getCurrentFocusedRow()); 11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) hitEnterAndAssertAppMenuDismissed(); 11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 12023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Test that hitting ENTER past the bottom item doesn't crash Chrome. 12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Catches regressions for http://crbug.com/181067 12223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @SmallTest 12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Feature({"Browser", "Main"}) 12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void testKeyboardEnterAfterMovePastBottomItem() throws InterruptedException { 12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) moveToBoundary(false, true); 12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertEquals(getCount() - 1, getCurrentFocusedRow()); 12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) hitEnterAndAssertAppMenuDismissed(); 12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Test that hitting ENTER on the top item actually triggers the top item. 13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Catches regressions for https://crbug.com/191239 for shrunken menus. 13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @SmallTest 13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Feature({"Browser", "Main"}) 13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void testKeyboardMenuEnterOnTopItemLandscape() throws InterruptedException { 13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) showAppMenuAndAssertMenuShown(); 14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) moveToBoundary(true, false); 14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertEquals(0, getCurrentFocusedRow()); 14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) hitEnterAndAssertAppMenuDismissed(); 14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /** 14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Test that hitting ENTER on the top item doesn't crash Chrome. 14723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @SmallTest 14923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Feature({"Browser", "Main"}) 15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void testKeyboardMenuEnterOnTopItemPortrait() throws InterruptedException { 15123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) showAppMenuAndAssertMenuShown(); 15323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) moveToBoundary(true, false); 15423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertEquals(0, getCurrentFocusedRow()); 15523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) hitEnterAndAssertAppMenuDismissed(); 15623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 15723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /** 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Test that changing orientation hides the menu. 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) @SmallTest 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) @Feature({"Browser", "Main"}) 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public void testChangingOrientationHidesMenu() throws InterruptedException { 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) showAppMenuAndAssertMenuShown(); 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assertTrue("AppMenu did not dismiss", 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CriteriaHelper.pollForCriteria(new Criteria() { 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) @Override 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public boolean isSatisfied() { 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return !mAppMenuHandler.isAppMenuShowing(); 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) })); 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private void showAppMenuAndAssertMenuShown() throws InterruptedException { 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) final View menuButton = getActivity().findViewById(R.id.menu_button); 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ThreadUtils.runOnUiThread(new Runnable() { 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) @Override 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public void run() { 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) menuButton.performClick(); 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }); 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assertTrue("AppMenu did not show", 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CriteriaHelper.pollForCriteria(new Criteria() { 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) @Override 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public boolean isSatisfied() { 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return mAppMenuHandler.isAppMenuShowing(); 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) })); 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private void hitEnterAndAssertAppMenuDismissed() throws InterruptedException { 19423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) getInstrumentation().waitForIdleSync(); 19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) pressKey(KeyEvent.KEYCODE_ENTER); 19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertTrue("AppMenu did not dismiss", 19723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CriteriaHelper.pollForCriteria(new Criteria() { 19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public boolean isSatisfied() { 20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return !mAppMenuHandler.isAppMenuShowing(); 20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) })); 20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private void moveToBoundary(boolean towardsTop, boolean movePast) throws InterruptedException { 20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Move to the boundary. 20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) final int end = towardsTop ? 0 : getCount() - 1; 20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int increment = towardsTop ? -1 : 1; 20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for (int index = getCurrentFocusedRow(); index != end; index += increment) { 21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN); 21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) final int expectedPosition = index + increment; 21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertTrue("Focus did not move to the next menu item", 21323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CriteriaHelper.pollForCriteria(new Criteria() { 21423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public boolean isSatisfied() { 21623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return getCurrentFocusedRow() == expectedPosition; 21723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 21823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) })); 21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Try moving past it by one. 22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (movePast) { 22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN); 22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertTrue("Focus moved past the edge menu item", 22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CriteriaHelper.pollForCriteria(new Criteria() { 22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public boolean isSatisfied() { 22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return getCurrentFocusedRow() == end; 22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) })); 23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // The menu should stay open. 23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) assertTrue(mAppMenu.isShowing()); 23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 23623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private void pressKey(final int keycode) { 238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch final View view = mAppMenu.getPopup().getListView(); 239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ThreadUtils.runOnUiThread(new Runnable() { 240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch @Override 241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public void run() { 242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode)); 243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode)); 244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch }); 24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) getInstrumentation().waitForIdleSync(); 24723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 24823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 24923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private int getCurrentFocusedRow() { 25023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ListPopupWindow popup = mAppMenu.getPopup(); 25123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (popup == null || popup.getListView() == null) return ListView.INVALID_POSITION; 25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ListView listView = popup.getListView(); 25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return listView.getSelectedItemPosition(); 25423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private int getCount() { 25723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ListPopupWindow popup = mAppMenu.getPopup(); 25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (popup == null || popup.getListView() == null) return 0; 25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return popup.getListView().getCount(); 26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 262