Espresso: calling openActionBarOverflowOrOptionsMenu() opens the first item in the menu - android

I have the below espresso test:
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
// if I Thread.sleep() here, I can see that the MenuItem has been clicked already
onView(withText("Sign in")) //<= click on the MenuItem
.perform(click());
onView(withId(R.id.signupButton)) //<= click the signup button in my UI
.perform(click());
The first line up there opens the overflow menu and clicks the first item at the same time (which happens to be the signin item). So the test fails because it cannot find the MenuItem view. Is there anything I am doing wrong ? I am using an emulator API 22, compiling agains targetSdk 24 and using espresso 2.2.1.

Try that:
public class EspressoMatchers {
public static Matcher<View> withOverflowMenuButton() {
return anyOf(allOf(isDisplayed(), withContentDescription("More options")),
allOf(isDisplayed(), withClassName(endsWith("OverflowMenuButton"))));
}
}
To open overflow menu:
onView(allOf(EspressoMatchers.withOverflowMenuButton(),
isDescendantOfA(withId(R.id.toolbar)))).perform(click());
Then it should work fine. Just use right ID for your Toolbar. I know this is just a copy from Espresso class, but I also ran into this issue and this helped me.
Please remember to always click the menu items "by name", not by their ID, as ID won't work. So your "click item" should be fine:
onView(withText("Sign in")) //<= click on the MenuItem
.perform(click());

Related

How to get ActionMode.Menu working properly in OnActionModeStarted on Android Xamarin Forms?

I have the following code to introduce menu items into the system context menu upon text selection on a Label.
public override void OnActionModeStarted(ActionMode mode)
{
IMenu menu = mode.Menu;
menu.Add("MItem1");
menu.Add("MItem2");
menu.Add("MItem3");
menu.GetItem(0).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 0));
menu.GetItem(1).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 1));
menu.GetItem(2).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 2));
//test code -> this works fine
menu.Add(0, 999, 0, "test");
//item is found, item.IsEnabled == true, item.IsVisible == true
IMenuItem item = menu.FindItem(999);
base.OnActionModeStarted(mode);
}
It works fine on a Lenovo device and was previously working on a Samsung device, but over time due to, I suspect, one or two Samsung system updates, the method no longer has any effect.
I've run the code through the debugger and the code can be stepped through line by line, but the system menu is completed unaffected by the added menuitems and continues as if my code hasn't been called at all.
Any ideas?
I have both a workaround and a solution.
Workaround
I added:
mode.Hide(1);
to the above code. It helps refresh the menu and the correct menu items appear.
Solution
I did another Samsung OS upgrade and the problem has disappeared. Seems like it was an OS problem after all.

NavigationView menu does not update

I am writing here about an issue that was introduced when we migrated from the AppCompat library to the AndroidX library. While doing so, we switched from android.support.design.widget.NavigationView to com.google.android.material.navigation.NavigationView and that’s when the following issue started.
In our NavigationView design, in order to save space, we implemented an expandable menu, so that when users clicks on the “more” button, the menu expands to show more options. It starts off with only some options visible, and the rest are not visible, as follows;
Option 1
Option 2
More…
Upon clicking on the “More...” button, the menu expands to;
Option 1
Option 2
Option 3
Option 4
Option 5
Option 6
To do this we used following code;
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
....
if (item.getItemId() == R.id.nav_more)
{
item.setVisible(false); // hide the “More” item
getMenu().findItem(R.id.nav_option_3).setVisible(true);
getMenu().findItem(R.id.nav_option_4).setVisible(true);
getMenu().findItem(R.id.nav_option_5).setVisible(true);
getMenu().findItem(R.id.nav_option_6).setVisible(true);
return true;
}
.......
return false;
}
Well, this code has worked in the past, but when we migrated to using the androidx library, poof, it stopped working. Well, it did work a bit. The “More...” button got hidden, but the previously hidden options, were not being displayed.
As, it took me many hours to solve this issue, and to save others this headache, I will explain the issue and the solution.
The first thing to do in such cases, is to look at the source code. As the code is open source, I was able to get it at github. At first glance I didn’t get smarter. I found that the NavigationView has a NavigationMenuPresenter object field (called presenter), that has a method called updateMenuView() which calls adapter.update(), which calls prepareMenuItems() and notifyDataSetChanged(). This sounded like the needed fix, so using reflection, we accessed and called the updateMenuView() method, but surprisingly, it did not help!
So, I decided to take it to the extreme, and see what happens if I call getMenu().clear(), and believe it or not, nothing happened. It seems that any changes made to Menu after the NavigationView is shown, are ignored. But a quick look through source code, I could not see any reason for that.
So how do I solve this issue? I tried using the latest alpha version of the library, but I still have the same issue.
Well, after much work, I found the solution. It's actually simple. Just hold on for the answer.
Lionscribe
So I was back to the source code, searching for some clue, when I fell upon a method called setUpdateSuspended(boolean updateSuspended). Well, that sounded suspicious! I searched for usage of this method, and found it being called in the onClick callback. Here is a minimized version of the code;
#Override
public void onClick(View view) {
NavigationMenuItemView itemView = (NavigationMenuItemView) view;
setUpdateSuspended(true);
MenuItemImpl item = itemView.getItemData();
boolean result = menu.performItemAction(item, NavigationMenuPresenter.this, 0);
setUpdateSuspended(false);
}
Bingo! It seems that while handling clicks, the NavigationView suspends and will not recognize any changes done to menu. I am not sure the reason for this, but as we were updating the menu in the onNavigationItemSelected callback, which is called by the onClick method, the menu updates are ignored.
Well, once I understood the issue, the solution was simple and clean. I just wrapped the code in a Runnable, and posted it, so that it runs after the onClick method returns, and setUpdateSuspended is set back to false. Here is the updated code;
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
....
if (item.getItemId() == R.id.nav_more)
{
final MenuItem itemFinal = item;
post(new Runnable()
{
#Override
public void run()
{
getMenu().findItem(R.id.nav_option_3).setVisible(true);
getMenu().findItem(R.id.nav_option_4).setVisible(true);
getMenu().findItem(R.id.nav_option_5).setVisible(true);
getMenu().findItem(R.id.nav_option_6).setVisible(true);
itemFinal.setVisible(false); // hide the “More” item
}
});
return true;
}
.......
return false;
}
Viola! The expandable menu now works like it used to, the hidden items are now being shown!
I hope this will be of help to others with same issue.
Lionscribe

How to open ActionMode menu with help of Espresso?

I'm trying to test the scenario like below.
Here is my code:
#Test
public void testRenameList() {
addNewList();
// Long click on the list
onView(recyclerViewItemWithText(mNewListName)).perform(longClick());
openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());
}
The following error occures on the last line:
android.support.test.espresso.AmbiguousViewMatcherException: '((is displayed on the screen to the user and with content description: is "More options") or (is displayed on the screen to the user and with class name: a string ending with "OverflowMenuButton"))' matches multiple views in the hierarchy.
I think, Espresso finds two menu: from ActionMode and from ActionBar.
The question is how to open menu exactly from ActionMode?
I've solved this issue by using UIAutomator.
I've replaced the line
openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());
by
UiObject btnMenu = mDevice.findObject(new UiSelector().description(mActivity.getString(R.string.menu_button_identifier)));
btnMenu.click();
The value of R.string.menu_button_identifier in English is "More options".

Setting content description for option menu android Talkback

I am implementing "Read Aloud" or "Talkback" for an app. Everything is working with contentDescription text, but with option menu, I found nothing related to contentDescription, I want system read "Menu "+ item's name.
EX: My menu has 2 items: "Create New Folder" and "Delete current folder", currently, when I focus a menu item (Support trackball and bluetooth key), system can talk exactly the menu's text. But I want it talks more like "1: Menu Create New Folder" and "2: Menu Delete current folder".
So, How can I change the read text? How can I get the focused menu item when bluetooth keyboard press UP/DOWN key?
MenuItemCompat in the v4 support libraries has a
android.support.v4.view.MenuItemCompat.setContentDescription(MenuItem menuItem, CharSequence contentDescription)
method for backwards compatibility on pre-Oreo devices.
For AndroidX see this answer:
https://stackoverflow.com/a/57950952/1236327
As my investigation, in Android internal source code, class ActionMenuItemView.java method setTitle(CharSequence title), the source code also sets setContentDescription(title), so Android will read your MenuItem's text as default. I don't know why the core has so inflexible in this case.
Updated:
Thanks for #sofakingforever answer.
Seem Google just added the setContentDescription(CharSequence contentDescription) method to the MenuItem class on API 26 (Android O).
Updated:
Thanks for new #tim.paetz answer .
Look like all versions are now supported setContentDescription for menu item using android support v4 libraries.
this answer post AndroidX
androidx.core.view.MenuItemCompat.setContentDescription(menuItem, contentDescription)
It seems they just added the setContentDescription(CharSequence contentDescription) method to the MenuItem class on API 26 (Android O)
Full sample:
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.client_menu_close, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem closeMenu = menu.findItem(R.id.client_menu_close_action);
androidx.core.view.MenuItemCompat.setContentDescription(closeMenu, R.string.str_accessibility_client_screen_close);
}

Android context sub-menu opened-closed-reopened by itself

I have a context menu which include a sub-menu, when-ever I tap on the item to open the sub-menu, the sub-menu opens/closes and reopens quickly. That's very annoying but more problematic some of my users don't see the sub-menu at all, it opens/closes and that's it!
Now after experimenting I figured out that long-pressing the item actually works as soon as I release the item: the sub-menu opens properly and stays open!
So I decided to build a very basic project believing I had a bug in my app, created a new app with the wizard, a single activity, a single text on which I registerForContextMenu and a context menu with a simple sub-menu.
The issue reproduced itself immediately!!! Does anyone experience the same issue and could tell me what am I doing wrong? I believe I followed documentation and samples, but I can't find any information on this problem anywhere!!!
I've posted the issue on Google groups and reported as an issue on Android project, but so far no-one responded, here are the links to both which include the test project (not sure how I can attach a file here?).
https://code.google.com/p/android/issues/detail?id=53239&can=4&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/SLteohmgyy0
To solve this, I had to get rid of any sub-menu in context menu and instead open another context menu on item selection.
The following got rid of the flickering and ensured the sub-menu remained open. Had to use a spare hidden view to open the new context menu though.
if (id == R.id.menu_item_for_sub_menu)
{
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
View v = vg.findViewById(R.id.fake_view_for_context);
if (v != null)
{
registerForContextMenu(v);
openContextMenu(v);
unregisterForContextMenu(v);
}
}
}, 0);
}

Categories

Resources