Espresso: Matching Views in RecyclerView

I have been diving into Espresso at my current job at Foursquare. Our team also recently started using RecyclerView instead of ListView.

RecyclerView support is still pretty limited on Espresso through RecyclerViewActions.

Through RecyclerViewActions, you can perform actions on an item by position. However, there’s nothing built-in to perform actions on a specific view in an item.

For ListView, there’s onData  that gives you a DataInteraction object and allows you to go deeper into a list item by position.

There’s currently no equivalent for that in RecyclerView.

RecyclerViewMatcher

After trying out different solutions, I opted for a more generic solution so that it would work with any ViewMatchers.  You can see how I arrived to this solution on this commit.

RecyclerViewMatcher gets a reference to the RecyclerView and the child view based on position. Then, it determines if the view matches the child view or the view matches the target view in the child view.

public boolean matchesSafely(View view) {

    this.resources = view.getResources();

    if (childView == null) {

        RecyclerView recyclerView = (RecyclerView)

          view.getRootView().findViewById(recyclerViewId);

        if (recyclerView != null && recyclerView.getId() == recyclerViewId) {

            childView = recyclerView.getChildAt(position);
      }
      else {
          return false;
   }
}

if (targetViewId == -1) {
   return view == childView;
} else {
   View targetView = childView.findViewById(targetViewId);
   return view == targetView;
}

:: You can view the source code at` https://github.com/dannyroa/espresso-samples/tree/master/RecyclerView <https://github.com/dannyroa/espresso-samples/tree/master/RecyclerView>`__.

If you have an alternative solution, let me know in the comments.