How to assert inside a RecyclerView in Espresso?
Pretty easy. No extra library is needed. Do:
onView(withId(R.id.recycler_view))
.check(matches(atPosition(0, withText("Test Text"))));
if your ViewHolder uses ViewGroup, wrap withText()
with a hasDescendant()
like:
onView(withId(R.id.recycler_view))
.check(matches(atPosition(0, hasDescendant(withText("Test Text")))));
with method you may put into your Utils
class.
public static Matcher<View> atPosition(final int position, @NonNull final Matcher<View> itemMatcher) {
checkNotNull(itemMatcher);
return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {
@Override
public void describeTo(Description description) {
description.appendText("has item at position " + position + ": ");
itemMatcher.describeTo(description);
}
@Override
protected boolean matchesSafely(final RecyclerView view) {
RecyclerView.ViewHolder viewHolder = view.findViewHolderForAdapterPosition(position);
if (viewHolder == null) {
// has no item on such position
return false;
}
return itemMatcher.matches(viewHolder.itemView);
}
};
}
If your item may be not visible on the screen at first, then scroll to it before:
onView(withId(R.id.recycler_view))
.perform(scrollToPosition(87))
.check(matches(atPosition(87, withText("Test Text"))));
You should check out Danny Roa's solution Custom RecyclerView Actions And use it like this:
onView(withRecyclerView(R.id.recycler_view)
.atPositionOnView(1, R.id.ofElementYouWantToCheck))
.check(matches(withText("Test text")));
Just to enhance riwnodennyk's answer, if your ViewHolder
is a ViewGroup
instead of a direct View
object like TextView
, then you can add hasDescendant
matcher to match the TextView
object in the ViewGroup
. Example:
onView(withId(R.id.recycler_view))
.check(matches(atPosition(0, hasDescendant(withText("First Element")))));