Click home icon with Espresso

25,087

Solution 1

To not depend on the app locale, you can use the code from Matt Logan by replacing "Navigate up" with R.string.abc_action_bar_up_description:

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

This helped me a lot because I have an app in more than 5 languages and I had to act like this.

Solution 2

Use the withContentDescription() Matcher:

onView(withContentDescription("Navigate up")).perform(click());

Solution 3

I had trouble navigating back from one Activity to another, but then I found top-level actions:

Espresso.pressBack();

Solution 4

I found a real solution to this issue. By using the hierarchyviewer I found that the toolbar looks like this: hierarchyviewer screenshot

This means we could match the hamburger icon (not back button) like this:

onView(withContentDescription("Open navigation")).perform(click());

But a better solution to me was to find out that the hamburger icon is the only ImageButton and a direct child view of the v7 Toolbar. So I wrote a helper method to match it:

public static Matcher<View> androidHomeMatcher() {
    return allOf(
        withParent(withClassName(is(Toolbar.class.getName()))),
        withClassName(anyOf(
            is(ImageButton.class.getName()),
            is(AppCompatImageButton.class.getName())
    )));
}

@Test
public void clickHamburgerIcon() throws Exception {
    onView(androidHomeMatcher()).perform(click());
    // ...
}

This solution is better because it should match the view no matter which locale you use in your test. :-)

EDIT: Note that Toolbar might be android.support.v7.widget.Toolbar or android.widget.Toolbar - depending on your use case!

EDIT: The support lib version 24.2.0 uses AppCompatImageButton instead of ImageButton, so I added it, too.

EDIT: You have to import the correct methods to get this to work. Here are the imports used:

import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;

Solution 5

I was having problems with "Navigate up" in an emulator, this worked for me:

onView(isRoot()).perform(ViewActions.pressMenuKey());
Share:
25,087

Related videos on Youtube

ligi
Author by

ligi

https://ligi.de

Updated on July 07, 2020

Comments

  • ligi
    ligi almost 4 years

    I am trying to click the home icon in some Espresso tests via:

    onView(withId(android.R.id.home)).perform(click());
    

    This works fine for Android > 3.0 - but fails for older versions as appcompat does not seem to use this id for this element then. What is a good approach to do what I want to do?

    • Matt Logan
      Matt Logan over 9 years
      Wondering if you found an answer to this?
    • ligi
      ligi over 9 years
      AFAIR not really - I think I worked around this then. Might be worth a try if this changed in the most recent appcompat though
    • Matt Logan
      Matt Logan over 9 years
      Just found a solution (for me at least). See answer.
    • sunlover3
      sunlover3 over 6 years
      @ligi Hello! Can you change the accepted answer, please?
    • ligi
      ligi over 6 years
      @sunlover3 ack - just changed the accepted answer to yours - you are right - this solution is better. Does it work for appcompat and native?
    • sunlover3
      sunlover3 over 6 years
      @ligi Great! Thank you. It should work, because the OS developers who work on this part should not change these ids. Otherwise, all the tests developed will crash. For the moment, all my tests regarding this part are working.
  • nickmartens1980
    nickmartens1980 over 9 years
    This works, however, this may fail on devices that are not set to English
  • DesignatedNerd
    DesignatedNerd over 9 years
    If you look for this log in your failures in your language: +------->ImageButton{id=-1, desc=Navigate up,, the desc value will be the translated description in the device's current language. I'd imagine that's buried somewhere within the android.R.string declarations, but I haven't been able to ferret out where it's hidden.
  • Matt Logan
    Matt Logan over 9 years
    Not sure why the different language thing is a big deal, unless you're running your automated tests on devices set to a different language. Even in this case, you could just switch on the device's default Locale to set the appropriate "Navigate up" translation.
  • Ghedeon
    Ghedeon over 9 years
    Use with caution, because: 1) apparently in 4.3 content description is "<action bar title>, Navigate up" and matching will fail. 2) You can have more than one view with a such description. In particular, only onView(allOf(withContentDescription(containsString("Navigate up")), isClickable())).perform(click()) works for me.
  • bryant1410
    bryant1410 about 8 years
    Please notice that back navigation is not the same as up navigation: developer.android.com/design/patterns/navigation.html
  • Roc Boronat
    Roc Boronat about 8 years
    This should be the accepted answer. The accepted one only works on English devices... #fail
  • sunlover3
    sunlover3 about 8 years
    Thanks. I always think of using general commands, so this is why I searched for the android native string id. Good luck!
  • sunlover3
    sunlover3 almost 8 years
    I would like to help you. Can you tell me how did you receive this error? You must be careful that before calling onView on any view, be sure that nothing overlaps it (like a dialog or some other screen). My code works pretty fine, you have a mistake in your code structure.
  • Frikster
    Frikster over 7 years
    I have the same problem as @AutonomousApps. how can I check to see of anything is overlapping? Shouldn't the withContentDescription bring the view to the top level view that contains the Navigate up button?
  • sotrh
    sotrh over 7 years
    For Kotlin devs, import is using something like import org.hamcrest.Matchers.`is` as _is.
  • Felipe Porge Xavier
    Felipe Porge Xavier about 7 years
    The only that worked for my case. I was trying to close a search view.
  • Alexei
    Alexei about 5 years
    I found solution without workaround. Here: val upButton = onView(allOf(instanceOf(ImageButton::class.java), withParent(withId(toolBar))))
  • Beloo
    Beloo almost 5 years
    yes, it works, but only with Toolbar widget. For system navigation you should choose another solution
  • Brian
    Brian about 4 years
    Hello! While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.
  • Clément Jean
    Clément Jean over 3 years
    for people using androidx, it's androidx.appcompat.R.string.abc_action_bar_up_description
  • Oya Canli
    Oya Canli over 3 years
    with navigation component, this is only working in English, when I try in French it fails. @AthaMit's answer works for both languages
  • Oya Canli
    Oya Canli over 3 years
    Thanks! The accepted anwser only works in English for me since I migrated to Jetpack navigation. This solution worked in French as well.
  • sunlover3
    sunlover3 over 3 years
    @OyaCanli I'm sure that since 2016 the things might have changed. Thanks for the update!