Image for post
Image for post

Espresso and the Navigation Drawer

Victoria Gonda
Jan 26, 2018 · 2 min read

Espresso has a full feature set when it comes to testing your Android UI. Almost everything you might need can be easily achieved using the provided API. Sometimes, you can still run into things that Espresso doesn’t explicitly cover, requiring deeper investigation, and more writing. Often this turns into much more code, requiring you to write custom matchers, and actions.

I ran into one of these cases the other day while testing a navigation drawer. I wanted to close the navigation drawer using an outside tap instead of the provided close drawer action. This wasn’t as straightforward as I hoped.

Because there is no “click outside this view” function, I first tried writing my test to perform a click on an element under the navigation drawer, still visible to the user while the drawer is open. It’s grayed out, but you can still see it, right?

@Test
fun clickingOutsideClosesNavigationDrawer() {
activity.launchActivity(null)
onView(withContentDescription(R.string.label_drawer_open))
.perform(click())
// Click on button visible when drawer open
onView(withId(R.id.button))
.perform(click())
onView(withId(R.id.navigation_view))
.check(matches(not(isDisplayed())))
}

This did not work. Even though it may be visible under that shadow, it fails because it is not “displayed.” Time to try something else.

We’re going to have to pick coordinates to tap on directly. We can pick these by looking at the boundaries of the navigation drawer view, and adding a couple pixels to move them just outside the view. Then we can use clickOnCoordinates to click on this location.

Note: these specific calculations are for a start gravity navigation drawer.

We create a helper function to accomplish this. We need both the drawer view, and the ID of the layout.

private fun clickOutsideDrawer(
parentDrawerLayout: View, @LayoutRes drawId: Int) {
onView(withId(drawId))
.perform(
CoordinatesClickViewAction.clickOnCoordinates(
parentDrawerLayout.x + parentDrawerLayout.width + 10,
parentDrawerLayout.height / 2f))
}

Then, we can use it in our test to click outside the navigation drawer!

@Test
fun clickingOutsideClosesNavigationDrawer() {
activity.launchActivity(null)
onView(withContentDescription(R.string.label_drawer_open))
.perform(click())
val parentDrawerLayout =
activity.activity.findViewById<View>(R.id.navigation_view)
clickOutsideDrawer(parentDrawerLayout, R.id.drawer_main)
onView(withId(R.id.navigation_view))
.check(matches(not(isDisplayed())))
}

Happy coding!

victoriagonda

Developer blog focused mainly on Android and Kotlin

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store