8

I have a Fragment that contains RecyclerView. But since I have a lot of elements in this Fragment, I want to swipe up the list to see and check all the elements that are in this Fragment.

Earlier this method helped me, but now for some reason it does not work:

Espresso.onView(ViewMatchers.withId(R.id.recyclerView)).perform(ViewActions.swipeUp())

I have many RecyclerViews with same id in my project:

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"/>

Also in my tests I've written something like this:

onView(allOf( withId(R.id.recyclerView), isDisplayed()))
onView(withId(R.id.recyclerView)).perform(swipeUp())

But caught error only on second line.

android.support.test.espresso.AmbiguousViewMatcherException: 'with id: com.fentury.android:id/recyclerView' matches multiple views in the hierarchy. Problem views are marked with '****MATCHES****' below.

azizbekian
  • 60,783
  • 13
  • 169
  • 249
Morozov
  • 4,968
  • 6
  • 39
  • 70
  • Clarify what *"doesn't work"* is supposed to mean. Show your view hierarchy, so that we can understand what possibly may have gone wrong. – azizbekian Jun 14 '17 at 09:46

4 Answers4

7

You have multiple views with id R.id.recyclerView in your view hierarchy, therefore espresso lacks to perform correct matching. Make the ids of those RecyclerViews unique.


onView(allOf(withId(R.id.recyclerView), isDisplayed())) onView(withId(R.id.recyclerView)).perform(swipeUp())

But caught error only on second line.

Then perform matching this way:

onView(allOf(withId(R.id.recyclerView), isDisplayed())).perform(swipeUp())
Community
  • 1
  • 1
azizbekian
  • 60,783
  • 13
  • 169
  • 249
  • 1
    Bad advice, because in my application this recyclerView is used in many places. – Morozov Jun 14 '17 at 11:25
  • 1
    Then you have to perform matching using [some other criteria](https://developer.android.com/reference/android/support/test/espresso/matcher/ViewMatchers.html), i.e. `allOf(withParent(withId(R.id.parentId)), withId(R.id.recyclerView))` or some other combination. – azizbekian Jun 14 '17 at 11:28
1

Solution:

onView(allOf(withId(R.id.recyclerview), isDisplayed())).perform(swipeUp());
Serenity
  • 35,289
  • 20
  • 120
  • 115
Pinak Gauswami
  • 789
  • 6
  • 10
-1

You should use on data for recycler view where you can assert using recycler view's id as well as type of data it holds. This should help assuming different recycler views would not have same type of data but its better practice to use different ids for different view based on what its used for.

You may also want to use perform(ViewActions.scrollTo())

Amit Kaushik
  • 642
  • 7
  • 13
  • Sometimes you want to reuse the same layout file for two different fragments. Then you have the same ids. – StefanTo May 29 '18 at 14:03
-1

I had a similar problem with multiple RecyclerViews in two fragments inside a ViewPager when I found this question. Both fragments used the same layout file, containing just the RecyclerView with id = @id/list.

As there was no parent to match I made this custom ViewMatcher to match the list by Adapter-Class: (Kotlin)

fun hasAdapterOfType(T: Class<out RecyclerView.Adapter<out RecyclerView.ViewHolder>>): BoundedMatcher<View, RecyclerView> {

    return object : BoundedMatcher<View, RecyclerView>(RecyclerView::class.java) {
        override fun describeTo(description: Description) {
            description.appendText("RecycleView adapter class matches " + T.name)
        }

        override fun matchesSafely(view: RecyclerView): Boolean {
            return (view.adapter.javaClass.name == T.name)
        }
    }
}

Usage like this:

onView(allOf(withId(list), hasAdapterOfType(AccessAttemptListAdapter::class.java))).check(blabla)
StefanTo
  • 971
  • 1
  • 10
  • 28