How to click on an item inside a RecyclerView in Espresso

前端 未结 10 2267
逝去的感伤
逝去的感伤 2020-12-01 05:33

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

相关标签:
10条回答
  • 2020-12-01 05:53

    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.

    0 讨论(0)
  • 2020-12-01 05:54

    With this code, you can scroll the recycler view to find your item withText and perform click or other action on it.

    dependencies

    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
    

    Code

    @Test
    public void scrollRecyclerViewAndClick() {
        onView(withId(R.id.recycler_view)).
                perform(RecyclerViewActions.
                actionOnItem(withText("specific string"), click()));
    }
    
    0 讨论(0)
  • 2020-12-01 05:56

    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));
        }
    }
    
    0 讨论(0)
  • 2020-12-01 06:00

    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.

    0 讨论(0)
提交回复
热议问题