I have a RecyclerView (R.id.recyclerView) where each row has an image (R.id.row_image) and a TextView. I want to click on the image in the first row.
I\'ve tried to use
I followed @Gabor's answer but when I included the libraries, I hit the dex limit!
So, I removed the libraries, added this getInstrumentation().waitForIdleSync();
and then just called onView(withId...))...
Works perfectly.
In your case you will have multiple image views with the same ID so you will have to figure out something on how you can select the particular list item.
With this code, you can scroll the recycler view to find your item withText and perform click or other action on it.
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
@Test
public void scrollRecyclerViewAndClick() {
onView(withId(R.id.recycler_view)).
perform(RecyclerViewActions.
actionOnItem(withText("specific string"), click()));
}
You should use a Custom ViewAction:
public void clickOnImageViewAtRow(int position) {
onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.actionOnItemAtPosition(position, new ClickOnImageView()));
}
public class ClickOnImageView implements ViewAction{
ViewAction click = click();
@Override
public Matcher<View> getConstraints() {
return click.getConstraints();
}
@Override
public String getDescription() {
return " click on custom image view";
}
@Override
public void perform(UiController uiController, View view) {
click.perform(uiController, view.findViewById(R.id.imageView));
}
}
As I posted here you can implement your custom RecyclerView
matcher. Let's assume you have RecyclerView
where each element has subject you wonna match:
public static Matcher<RecyclerView.ViewHolder> withItemSubject(final String subject) {
Checks.checkNotNull(subject);
return new BoundedMatcher<RecyclerView.ViewHolder, MyCustomViewHolder>(
MyCustomViewHolder.class) {
@Override
protected boolean matchesSafely(MyCustomViewHolder viewHolder) {
TextView subjectTextView = (TextView)viewHolder.itemView.findViewById(R.id.subject_text_view_id);
return ((subject.equals(subjectTextView.getText().toString())
&& (subjectTextView.getVisibility() == View.VISIBLE)));
}
@Override
public void describeTo(Description description) {
description.appendText("item with subject: " + subject);
}
};
}
And usage:
onView(withId(R.id.my_recycler_view_id)
.perform(RecyclerViewActions.actionOnHolderItem(withItemSubject("My subject"), click()));
Basically you can match anything you want. In this example we used subject TextView
but it can be any element inside the RecyclerView
item.
One more thing to clarify is check for visibility (subjectTextView.getVisibility() == View.VISIBLE)
. We need to have it because sometimes other views inside RecyclerView
can have the same subject but it would be with View.GONE
. This way we avoid multiple matches of our custom matcher and target only item that actually displays our subject.