web-dev-qa-db-fra.com

Élément de menu Click Espresso

J'ai un menu dans la barre d'actions que je crée à travers:

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    menu.add(Menu.NONE, 98,Menu.NONE,R.string.filter).setIcon(R.drawable.ic_filter_list_white_48dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    menu.add(Menu.NONE, 99,Menu.NONE,R.string.add).setIcon(R.drawable.ic_add_white_48dp).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);


    getMenuInflater().inflate(R.menu.menu_main, menu);

    return true;
}

et menu_main.xml ressemble à:

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    tools:context=".MainActivity">
    <item
        Android:id="@+id/action_settings"
        Android:title="@string/action_settings"
        Android:orderInCategory="100"
        app:showAsAction="never"
        Android:icon="@drawable/ic_settings_white_48dp"/>
</menu>

Lors d'un test dans Espresso, je voudrais cliquer sur l'icône "ajouter" (menuId 99). j'ai essayé

@Test
public void testAdd() {
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
    onView(withText(R.string.add)).perform(click());
}

mais cela échoue avec une NoMatchingViewException. (L'élément de paramètres, qui est défini dans le xml directement, je peux cliquer avec le même code.)

C'est pour targetSdkVersion 23 et AppCompatActivity. Les lignes pertinentes pour la barre d'outils sont:

Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
if( getSupportActionBar() != null ) {
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

et tool_bar.xml ressemble à:

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.Toolbar     xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark"
    Android:background="@color/ColorPrimary"
    Android:elevation="4dp"
    tools:ignore="UnusedAttribute">
</Android.support.v7.widget.Toolbar>
21
user1583209

Mise à jour : Je n'ai pas vu la finale de la ligne, ignorer mes réponses précédentes, j'ai essayé de la réparer rapidement et je me suis trompé. Je ne connaissais vraiment pas la réponse.

...setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)

Votre question est expliquée ici par l'équipe Espresso:

Icônes visibles correspondantes:

  // Click on the icon - we can find it by the r.Id.
  onView(withId(R.id.action_save))
    .perform(click());

Cliquer sur les éléments dans le menu de débordement est un peu plus délicat pour la barre d'actions normale car certains appareils ont un bouton de menu de débordement matériel (ils ouvriront les éléments de débordement dans un menu d'options) et certains appareils ont un bouton de menu de débordement logiciel (ils s'ouvriront un menu de débordement normal). Heureusement, Espresso s'en occupe pour nous.

  // Open the overflow menu OR open the options menu,
  // depending on if the device has a hardware or software overflow menu button.
  openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());

  // Click the item.
  onView(withText("World"))
    .perform(click());

Je comprends donc que les deux alternatives sont correctes mais dépendent de votre cas spécifique. Si vous testez un bouton, vous savez normalement s'il est visible ou non à ce moment.

Dans votre cas, le bouton est visible car il y a de la place, et il est correct d'utiliser withId comme ici :

import static Android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;

@Test
public void testClickInsertItem() {
    openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
    onView(withId(R.id.action_insert)).perform(click());
}

Mais this c'est correct aussi pour les éléments de débordement:

Oui, c'est comme ça que ça fonctionne dans Espresso. Le problème ici est que, dans Android, la vue représentant l'élément de menu n'a pas l'ID de l'élément de menu. Donc onView (withId (X)) ne parvient tout simplement pas à trouver une vue. Je n'ai pas de meilleure recommandation que d'utiliser simplement withText (). Si vous avez plusieurs vues avec le même texte, l'utilisation de la hiérarchie pour les travaux de distinction.

Maintenant, ma question est de savoir quoi faire lorsque vous testez sur différents appareils et vous ne savez pas quand sera la place pour un élément. Je ne connais pas la réponse, peut-être combiner les deux solutions.

37
albodelu

Vous pouvez utiliser cette méthode pour cliquer sur l'élément de menu. Cliquez d'abord sur le bouton de menu à l'aide de ce code

openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());

Ensuite, effectuez un clic sur l'élément de menu en fonction du texte. Remplacez le nom de votre élément de menu par "MenuItemName"

onView(withText("MenuItemName")).perform(click());
3
Ishan Fernando

C'est ma solution qui couvre les trois situations: bouton de menu matériel, menu de débordement, uniquement des icônes:

    try {
        openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
    } catch (Exception e) {
        //This is normal. Maybe we dont have overflow menu.
    }
    onView(anyOf(withText(R.string.<your label for the menu item>), withId(R.id.<id of the menu item>))).perform(click());
3
guni

Ne souffrez pas beaucoup. Disons Rendre les choses simples.

onView(withId(98)).perform(click());

Cela vous aidera à effectuer un clic sur Ajouter

1
Manish
Espresso.openContextualActionModeOverflowMenu() 

était la seule option qui fonctionnait pour mon Samsung Note 3. Cette openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); essaierait et échouerait sans aucune erreur

1
gorbysbm

Utilisez-le pour faire correspondre le texte de description de l'élément de menu:

onView(withContentDescription(R.string.add)).perform(click());

Ensuite, vous n'avez pas à faire correspondre sur l'ID (inexistant), ni sur l'icône dessinable.

N'oubliez pas non plus d'utiliser cet extrait de code de la documentation Espresso si vous devez vous assurer que le menu est développé:

// Open the overflow menu OR open the options menu,
// depending on if the device has a hardware or software overflow menu button.
openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());
1
Eirik W

La barre d'outils n'est pas l'ActionBar, pas besoin de l'appel:

openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());

Et si vous le faites, c'est sûr que votre élément n'y sera pas trouvé (il n'est pas dans l'ActionBar) et la ToolBar appartient à la "vue normale".