Click on menu-item that is sometimes in the overfl

2019-05-08 21:14发布

问题:

currently to click on menu-item that is sometimes on some devices in the overflow-menu I am doing the following:

fun invokeMenu(@IdRes menuId: Int, @StringRes menuStringRes: Int) {
 try {
  onView(withId(menuId)).perform(click())
 } catch (nmv: NoMatchingViewException) {
  openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().targetContext)
  onView(withText(menuStringRes)).perform(click())
 }
}

But I am searching for a better approach - ideally something where I just have to know the menu-id. How do you do this in your espresso tests?

回答1:

Unfortunately, your ideal case cannot be acomplished. This is due to the construction of support libraries.

Let's start from PopupMenu, which has a reference to MenuPopupHelper, which has reference to MenuPopup. This is an abstract class extended ie. by StandardMenuPopup. It has reference to MenuAdapter. If you look into the line 92 of MenuAdapter you will see, the line:

itemView.initialize(getItem(position), 0);

This is the key method invocation. It can be invoked either in ActionMenuItemView or ListMenuItemView. Their implementations differ in the case, that id is attached to ActionMenuItemView, and is not attached to ListMenuItemView

Moreover, MenuAdapter.getItemId(int position) returns just position. The id of menu item is lost in overflow menu.


Hovewer, your code can be simplified to one liner. Define a function:

public static Matcher<View> withMenuIdOrText(@IdRes int id, @StringRes int menuText) {
    Matcher<View> matcher = withId(id);
    try {
        onView(matcher).check(matches(isDisplayed()));
        return matcher;
    } catch (Exception NoMatchingViewException) {
        openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().getTargetContext());
        return withText(menuText);
    }
}

Usage:

onView(withMenuIdOrText(R.id.menu_id, R.string.menu_text)).perform(click());