| Index: chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
|
| diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6c31a21dd7335d44edbc349c50ebffe9ed62e423
|
| --- /dev/null
|
| +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
|
| @@ -0,0 +1,202 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.chrome.browser.appmenu;
|
| +
|
| +import android.app.Activity;
|
| +import android.content.pm.ActivityInfo;
|
| +import android.test.suitebuilder.annotation.SmallTest;
|
| +import android.view.KeyEvent;
|
| +import android.view.MenuItem;
|
| +import android.view.View;
|
| +
|
| +import org.chromium.base.ThreadUtils;
|
| +import org.chromium.base.test.util.Feature;
|
| +import org.chromium.chrome.shell.ChromeShellActivity;
|
| +import org.chromium.chrome.shell.ChromeShellActivity.AppMenuHandlerFactory;
|
| +import org.chromium.chrome.shell.ChromeShellTestBase;
|
| +import org.chromium.chrome.shell.R;
|
| +import org.chromium.content.browser.test.util.Criteria;
|
| +import org.chromium.content.browser.test.util.CriteriaHelper;
|
| +
|
| +/**
|
| + * Tests AppMenu popup
|
| + */
|
| +public class AppMenuTest extends ChromeShellTestBase {
|
| + private AppMenu mAppMenu;
|
| + private AppMenuHandlerForTest mAppMenuHandler;
|
| +
|
| + /**
|
| + * AppMenuHandler that will be used to intercept item selections for testing.
|
| + */
|
| + public static class AppMenuHandlerForTest extends AppMenuHandler {
|
| + int mLastSelectedItemId = -1;
|
| +
|
| + /**
|
| + * AppMenuHandler for intercepting options item selections.
|
| + */
|
| + public AppMenuHandlerForTest(Activity activity, AppMenuPropertiesDelegate delegate,
|
| + int menuResourceId) {
|
| + super(activity, delegate, menuResourceId);
|
| + }
|
| +
|
| + @Override
|
| + void onOptionsItemSelected(MenuItem item) {
|
| + mLastSelectedItemId = item.getItemId();
|
| + }
|
| +
|
| + }
|
| +
|
| + @Override
|
| + protected void setUp() throws Exception {
|
| + super.setUp();
|
| + ChromeShellActivity.setAppMenuHandlerFactory(new AppMenuHandlerFactory() {
|
| + @Override
|
| + public AppMenuHandler getAppMenuHandler(Activity activity,
|
| + AppMenuPropertiesDelegate delegate, int menuResourceId) {
|
| + mAppMenuHandler = new AppMenuHandlerForTest(activity, delegate, menuResourceId);
|
| + return mAppMenuHandler;
|
| + }
|
| + });
|
| + launchChromeShellWithBlankPage();
|
| + assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
|
| +
|
| + final View menuButton = getActivity().findViewById(R.id.menu_button);
|
| + ThreadUtils.runOnUiThread(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + menuButton.performClick();
|
| + }
|
| + });
|
| + assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + return getActivity().getAppMenuHandler().isAppMenuShowing();
|
| + }
|
| + }));
|
| + mAppMenu = getActivity().getAppMenuHandler().getAppMenu();
|
| + pressKey(KeyEvent.KEYCODE_SPACE);
|
| +
|
| + }
|
| + /**
|
| + * Test bounds when accessing the menu through the keyboard.
|
| + * Make sure that the menu stays open when trying to move past the first and last items.
|
| + */
|
| + @SmallTest
|
| + @Feature({"Browser", "Main"})
|
| + public void testKeyboardMenuBoundaries() throws InterruptedException {
|
| + moveToBoundary(false, true);
|
| + assertEquals(mAppMenu.getCount() - 1, mAppMenu.getCurrentFocusedPosition());
|
| + moveToBoundary(true, true);
|
| + assertEquals(0, mAppMenu.getCurrentFocusedPosition());
|
| + moveToBoundary(false, true);
|
| + assertEquals(mAppMenu.getCount() - 1, mAppMenu.getCurrentFocusedPosition());
|
| + }
|
| +
|
| + /**
|
| + * Test that typing ENTER immediately opening the menu works.
|
| + */
|
| + @SmallTest
|
| + @Feature({"Browser", "Main"})
|
| + public void testKeyboardMenuEnterOnOpen() throws InterruptedException {
|
| + hitEnterAndAssertItemSelected();
|
| + }
|
| +
|
| + /**
|
| + * Test that hitting ENTER past the top item doesn't crash Chrome.
|
| + */
|
| + @SmallTest
|
| + @Feature({"Browser", "Main"})
|
| + public void testKeyboardEnterAfterMovePastTopItem() throws InterruptedException {
|
| + moveToBoundary(true, true);
|
| + assertEquals(0, mAppMenu.getCurrentFocusedPosition());
|
| + hitEnterAndAssertItemSelected();
|
| + }
|
| +
|
| + /**
|
| + * Test that hitting ENTER past the bottom item doesn't crash Chrome.
|
| + * Catches regressions for http://crbug.com/181067
|
| + */
|
| + @SmallTest
|
| + @Feature({"Browser", "Main"})
|
| + public void testKeyboardEnterAfterMovePastBottomItem() throws InterruptedException {
|
| + moveToBoundary(false, true);
|
| + assertEquals(mAppMenu.getCount() - 1, mAppMenu.getCurrentFocusedPosition());
|
| + hitEnterAndAssertItemSelected();
|
| + }
|
| +
|
| + /**
|
| + * Test that hitting ENTER on the top item actually triggers the top item.
|
| + * Catches regressions for https://crbug.com/191239 for shrunken menus.
|
| + */
|
| + @SmallTest
|
| + @Feature({"Browser", "Main"})
|
| + public void testKeyboardMenuEnterOnTopItemLandscape() throws InterruptedException {
|
| + getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
| + moveToBoundary(true, false);
|
| + assertEquals(0, mAppMenu.getCurrentFocusedPosition());
|
| + hitEnterAndAssertItemSelected();
|
| + }
|
| +
|
| + /**
|
| + * Test that hitting ENTER on the top item doesn't crash Chrome.
|
| + */
|
| + @SmallTest
|
| + @Feature({"Browser", "Main"})
|
| + public void testKeyboardMenuEnterOnTopItemPortrait() throws InterruptedException {
|
| + getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
| + moveToBoundary(true, false);
|
| + assertEquals(0, mAppMenu.getCurrentFocusedPosition());
|
| + hitEnterAndAssertItemSelected();
|
| + }
|
| +
|
| + private void hitEnterAndAssertItemSelected() throws InterruptedException {
|
| + final int expectedItemId = mAppMenu.getCurrentFocusedItemId();
|
| + pressKey(KeyEvent.KEYCODE_ENTER);
|
| + assertTrue("Did not select a correct menu item",
|
| + CriteriaHelper.pollForCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + return mAppMenuHandler.mLastSelectedItemId == expectedItemId;
|
| + }
|
| + }));
|
| + }
|
| +
|
| + private void moveToBoundary(boolean towardsTop, boolean movePast) throws InterruptedException {
|
| + // Move to the boundary.
|
| + final int end = towardsTop ? 0 : mAppMenu.getCount() - 1;
|
| + int increment = towardsTop ? -1 : 1;
|
| + for (int index = mAppMenu.getCurrentFocusedPosition(); index != end; index += increment) {
|
| + pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN);
|
| + final int expectedPosition = index + increment;
|
| + assertTrue("Focus did not move to the next menu item",
|
| + CriteriaHelper.pollForCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + return mAppMenu.getCurrentFocusedPosition() == expectedPosition;
|
| + }
|
| + }));
|
| + }
|
| +
|
| + // Try moving past it by one.
|
| + if (movePast) {
|
| + pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN);
|
| + assertTrue("Focus moved past the edge menu item",
|
| + CriteriaHelper.pollForCriteria(new Criteria() {
|
| + @Override
|
| + public boolean isSatisfied() {
|
| + return mAppMenu.getCurrentFocusedPosition() == end;
|
| + }
|
| + }));
|
| + }
|
| +
|
| + // The menu should stay open.
|
| + assertTrue(mAppMenu.isShowing());
|
| + }
|
| +
|
| + private void pressKey(int keycode) {
|
| + getInstrumentation().sendKeyDownUpSync(keycode);
|
| + getInstrumentation().waitForIdleSync();
|
| + }
|
| +}
|
|
|