I have the following RecyclerView list:
I only want my test to click on the checkbox on the right, not the whole item. Here is what I tried:
onView(withId(R.id.recycler_view))
.perform(actionOnViewHolder<ViewHolder>(matcher = { vh ->
if (vh == null) return@actionOnViewHolder false
if (vh.position == no) {
// v1
(vh.itemView as ViewGroup).findViewById<View>(R.id.checkbox)?.performClick()
// v2
(vh.itemView as ViewGroup).getChildAt(2)?.performClick()
}
return@actionOnViewHolder false
}))
And some helper methods/classes:
inline fun <reified VH : RecyclerView.ViewHolder> actionOnViewHolder(
noinline matcher: (VH?) -> Boolean): RecyclerViewActions.PositionableRecyclerViewAction {
return RecyclerViewActions.actionOnHolderItem(
RecyclerViewViewHolderMatcher(VH::class.java, matcher), ViewActions.click())
}
class RecyclerViewViewHolderMatcher<VH : RecyclerView.ViewHolder>(
clazz: Class<VH>,
private val matcher: (VH?) -> Boolean) : BoundedMatcher<RecyclerView.ViewHolder, VH>(clazz) {
override fun describeTo(description: Description?) { }
override fun matchesSafely(item: VH): Boolean = matcher(item)
}
V1: (vh.itemView as ViewGroup).findViewById<View>(R.id.checkbox)
returns null, even though in debugger I can see that the view that 3 childs, the last one having the id: checkbox
.
V2: (vh.itemView as ViewGroup).getChildAt(2)
returns the view, but a click happens way later.
Also, I always return false
from the actionOnViewHolder
because I don't want to click()
or anything else on the whole ViewHolder.
Is there any way to do this better?