2015-07-13 9 views
31

Używam Ekspres contrib do wykonywania czynności na RecyclerView i działa tak jak powinno, ex:Jak sprawdzić wnętrze urządzenia RecyclerView w ekspresie?

onView(withId(R.id.recycler_view)) 
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); //click on first item 

i muszę wykonywać na nim twierdzeń. Coś takiego:

onView(withId(R.id.recycler_view)) 
    .perform(RecyclerViewActions.actionOnItemAtPosition(0, check(matches(withText("Test Text")))); 

ale ponieważ RecyclerViewActions jest, oczywiście, oczekując akcję, to mówi niewłaściwy typ 2nd argumentu. Na espresso-contrib nie ma numeru RecyclerViewAssertions.

Czy istnieje sposób na zapewnienie asercji w widoku recyklera?

Odpowiedz

36

Powinieneś sprawdzić rozwiązanie Danny ROA za Custom RecyclerView Actions i używać go tak:

onView(withRecyclerView(R.id.recycler_view) 
    .atPositionOnView(1, R.id.ofElementYouWantToCheck)) 
    .check(matches(withText("Test text"))); 
+0

Nie działa dla mnie, jeśli element na tej pozycji aktualnie nie pasuje do ekranu. – riwnodennyk

+1

Najpierw należy przewinąć do pozycji? onView (withId (R.id.id.recycler_view)). perform (RecyclerViewActions.scrollTo (2)); – HowieH

+2

Wciąż to samo. Nie działa, np. dla pozycji = 30. Problem polega na tym, że 'RecyclerView.findViewHolderForAdapterPosition (position)' powinno być używane z 'RecyclerView.getChildAt()' jak pokazano w odpowiedzi poniżej. – riwnodennyk

51

całkiem proste. Nie jest potrzebna dodatkowa biblioteka. Zrobić:

onView(withId(R.id.recycler_view)) 
      .check(matches(atPosition(0, withText("Test Text")))); 

jeśli ViewHolder wykorzystuje ViewGroup, owinąć withText() z hasDescendant() jak:

onView(withId(R.id.recycler_view)) 
       .check(matches(atPosition(0, hasDescendant(withText("Test Text"))))); 

metodą można umieścić w swojej klasie Utils.

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); 
     } 
    }; 
} 

Jeśli pozycja może nie być widoczny na ekranie w pierwszym, a następnie wskaż go przed:

onView(withId(R.id.recycler_view)) 
      .perform(scrollToPosition(87)) 
      .check(matches(atPosition(87, withText("Test Text")))); 
20

Wystarczy, aby zwiększyć odpowiedź riwnodennyk jest, jeśli ViewHolder jest ViewGroup zamiast bezpośredniego View obiekt taki jak TextView, można dodać matcher hasDescendant, aby dopasować obiekt TextView w ViewGroup. Przykład: rozwiązanie

onView(withId(R.id.recycler_view)) 
    .check(matches(atPosition(0, hasDescendant(withText("First Element"))))); 
+2

Jesteś moim bohaterem !!! Dziękuję bardzo!!! – Cabezas

+1

Idealne, wszystko czego mi brakowało to "hasDescendant", dziękuję bardzo! –

1

Danny ROA jest niesamowite, ale to nie działa dla elementów poza ekranem Właśnie przewinęły się. Poprawka zastępuje następująco:

View targetView = recyclerView.getChildAt(this.position) 
           .findViewById(this.viewId); 

z tym:

View targetView = recyclerView.findViewHolderForAdapterPosition(this.position) 
           .itemView.findViewById(this.viewId); 

... w TestUtils class.

1

W moim przypadku, trzeba było połączyć Danny Roa i rozwiązanie riwnodennyk za:

onView(withId(R.id.recyclerview)) 
.perform(RecyclerViewActions.scrollToPosition(80)) 
.check(matches(atPositionOnView(80, withText("Test Test"), R.id.targetview))); 

i metoda:

public static Matcher<View> atPositionOnView(final int position, final Matcher<View> itemMatcher, 
     @NonNull final int targetViewId) { 

    return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) { 
     @Override 
     public void describeTo(Description description) { 
      description.appendText("has view id " + itemMatcher + " at position " + position); 
     } 

     @Override 
     public boolean matchesSafely(final RecyclerView recyclerView) { 
      RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position); 
      View targetView = viewHolder.itemView.findViewById(targetViewId); 
      return itemMatcher.matches(targetView); 
     } 
    }; 
} 
+0

To nadal nie działa. Próbuje sprawdzić tekst "Test Test" w instancji RecyclerView, a nie w widoku docelowym. – tomrozb

+0

możesz udostępnić pakiet importujący Matcher –

+0

'import org.hamcrest.Matcher' (od' hamcrest-core-1.3') – Vince

2

mam zmaga się w tej samej sprawie, gdzie mam recykler widok z 6 pozycjami, a następnie muszę wybrać ten na pozycji 5, a ten 5 nie jest widoczny w widoku.
Powyższe rozwiązanie również działa. Ponadto, wiem, że jest nieco późno, ale myślałem, że warto się nim dzielić.

Zrobiłem to z prostego rozwiązania, jak poniżej:

onView(withId(R.id.recylcer_view)) 
    .perform(RecyclerViewActions.actionOnItem(
     hasDescendant(withText("Text of item you want to scroll to")), 
     click())); 

RecyclerViewActions.actionOnItem - Wykonuje ViewAction w widoku dopasowane viewHolderMatcher.

  1. Scroll RecyclerView do widoku dopasowane itemViewMatcher
  2. Wykonywanie czynności na dopasowane widzenia

Więcej szczegółów można znaleźć na stronie: RecyclerViewActions.actionOnItem

+1

Dziękujemy! Działa to dobrze na widok 'RecyclerView' z * prostymi * widokami przedmiotów. Mam projekt z ** wieloma poziomami zagnieżdżenia w hierarchii widoku **. Jeśli używam Twojego rozwiązania, kończę z: 'PerformException: Błąd podczas wykonywania 'wykonywania ViewAction: pojedyncze kliknięcie dopasowania elementu: właściciel z widokiem: ma potomka: z tekstem: jest" Testowa nazwa wyświetlana "" na widoku "z id: com .example.com: id/my_recycler_view' – JJD

Powiązane problemy