michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.tests.components; michael@0: michael@0: import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; michael@0: import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertFalse; michael@0: import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; michael@0: michael@0: import java.util.List; michael@0: michael@0: import org.mozilla.gecko.R; michael@0: import org.mozilla.gecko.menu.MenuItemActionBar; michael@0: import org.mozilla.gecko.menu.MenuItemDefault; michael@0: import org.mozilla.gecko.tests.UITestContext; michael@0: import org.mozilla.gecko.tests.helpers.WaitHelper; michael@0: import org.mozilla.gecko.util.HardwareUtils; michael@0: michael@0: import android.view.View; michael@0: michael@0: import com.jayway.android.robotium.solo.Condition; michael@0: import com.jayway.android.robotium.solo.RobotiumUtils; michael@0: import com.jayway.android.robotium.solo.Solo; michael@0: michael@0: /** michael@0: * A class representing any interactions that take place on the app menu. michael@0: */ michael@0: public class AppMenuComponent extends BaseComponent { michael@0: public enum MenuItem { michael@0: FORWARD(R.string.forward), michael@0: NEW_TAB(R.string.new_tab); michael@0: michael@0: private final int resourceID; michael@0: private String stringResource; michael@0: michael@0: MenuItem(final int resourceID) { michael@0: this.resourceID = resourceID; michael@0: } michael@0: michael@0: public String getString(final Solo solo) { michael@0: if (stringResource == null) { michael@0: stringResource = solo.getString(resourceID); michael@0: } michael@0: michael@0: return stringResource; michael@0: } michael@0: }; michael@0: michael@0: public AppMenuComponent(final UITestContext testContext) { michael@0: super(testContext); michael@0: } michael@0: michael@0: private void assertMenuIsNotOpen() { michael@0: fAssertFalse("Menu is not open", isMenuOpen()); michael@0: } michael@0: michael@0: private View getOverflowMenuButtonView() { michael@0: return mSolo.getView(R.id.menu); michael@0: } michael@0: michael@0: /** michael@0: * Try to find a MenuItemActionBar/MenuItemDefault with the given text set as contentDescription / text. michael@0: * michael@0: * Will return null when the Android legacy menu is in use. michael@0: * michael@0: * This method is dependent on not having two views with equivalent contentDescription / text. michael@0: */ michael@0: private View findAppMenuItemView(String text) { michael@0: final List views = mSolo.getViews(); michael@0: michael@0: final List menuItemActionBarList = RobotiumUtils.filterViews(MenuItemActionBar.class, views); michael@0: for (MenuItemActionBar menuItem : menuItemActionBarList) { michael@0: if (menuItem.getContentDescription().equals(text)) { michael@0: return menuItem; michael@0: } michael@0: } michael@0: michael@0: final List menuItemDefaultList = RobotiumUtils.filterViews(MenuItemDefault.class, views); michael@0: for (MenuItemDefault menuItem : menuItemDefaultList) { michael@0: if (menuItem.getText().equals(text)) { michael@0: return menuItem; michael@0: } michael@0: } michael@0: michael@0: return null; michael@0: } michael@0: michael@0: public void pressMenuItem(MenuItem menuItem) { michael@0: openAppMenu(); michael@0: michael@0: final String text = menuItem.getString(mSolo); michael@0: final View menuItemView = findAppMenuItemView(text); michael@0: michael@0: if (menuItemView != null) { michael@0: fAssertTrue("The menu item is enabled", menuItemView.isEnabled()); michael@0: fAssertEquals("The menu item is visible", View.VISIBLE, menuItemView.getVisibility()); michael@0: michael@0: mSolo.clickOnView(menuItemView); michael@0: } else { michael@0: // We could not find a view representing this menu item: Let's let Robotium try to michael@0: // locate and click it in the legacy Android menu (devices with Android 2.x). michael@0: // michael@0: // Even though we already opened the menu to see if we can locate the menu item, michael@0: // Robotium will also try to open the menu if it doesn't find an open dialog (Does michael@0: // not happen in this case). michael@0: mSolo.clickOnMenuItem(text, true); michael@0: } michael@0: } michael@0: michael@0: private void openAppMenu() { michael@0: assertMenuIsNotOpen(); michael@0: michael@0: if (HardwareUtils.hasMenuButton()) { michael@0: mSolo.sendKey(Solo.MENU); michael@0: } else { michael@0: pressOverflowMenuButton(); michael@0: } michael@0: michael@0: waitForMenuOpen(); michael@0: } michael@0: michael@0: private void pressOverflowMenuButton() { michael@0: final View overflowMenuButton = getOverflowMenuButtonView(); michael@0: michael@0: fAssertTrue("The overflow menu button is enabled", overflowMenuButton.isEnabled()); michael@0: fAssertEquals("The overflow menu button is visible", View.VISIBLE, overflowMenuButton.getVisibility()); michael@0: michael@0: mSolo.clickOnView(overflowMenuButton, true); michael@0: } michael@0: michael@0: private boolean isMenuOpen() { michael@0: // The presence of the "New tab" menu item is our best guess about whether michael@0: // the menu is open or not. michael@0: return mSolo.searchText(MenuItem.NEW_TAB.getString(mSolo)); michael@0: } michael@0: michael@0: private void waitForMenuOpen() { michael@0: WaitHelper.waitFor("menu to open", new Condition() { michael@0: @Override michael@0: public boolean isSatisfied() { michael@0: return isMenuOpen(); michael@0: } michael@0: }); michael@0: } michael@0: }