java - tutorial - ¿Cómo afirmar dentro de RecyclerView en Espresso?
test ui android (7)
Estoy usando espresso-contrib para realizar acciones en un RecyclerView
, y funciona como debería, por ejemplo:
onView(withId(R.id.recycler_view))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); //click on first item
y necesito realizar afirmaciones sobre eso. Algo como esto:
onView(withId(R.id.recycler_view))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, check(matches(withText("Test Text"))));
pero, como RecyclerViewActions está, por supuesto, esperando una acción, dice que es un tipo de segundo argumento incorrecto. No hay RecyclerViewAssertions
en espresso-contrib.
¿Hay alguna manera de realizar afirmaciones en una vista de reciclador?
Deberías echarle un vistazo a la solución de Danny Roa. Custom RecyclerView Actions Y usarla así:
onView(withRecyclerView(R.id.recycler_view)
.atPositionOnView(1, R.id.ofElementYouWantToCheck))
.check(matches(withText("Test text")));
En mi caso, fue necesario fusionar la solución de Danny Roa y Riwnodennyk:
onView(withId(R.id.recyclerview))
.perform(RecyclerViewActions.scrollToPosition(80))
.check(matches(atPositionOnView(80, withText("Test Test"), R.id.targetview)));
y el método:
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);
}
};
}
Este hilo es bastante antiguo, pero recientemente extendí el soporte de RecyclerViewAction para que también se pueda usar para las afirmaciones. Esto le permite probar elementos fuera de la pantalla sin especificar una posición mientras sigue usando los matchers de vista.
Echa un vistazo a este artículo> ¡ Mejor prueba de Android RecyclerView !
He estado luchando en el mismo tema donde tengo una vista de reciclador con 6 elementos y luego tengo que elegir el que está en la posición 5 y el quinto no está visible en la vista.
La solución anterior también funciona. Además, sé que es un poco tarde, pero pensé que valía la pena compartirlo.
Hice esto con una solución simple como la siguiente:
onView(withId(R.id.recylcer_view))
.perform(RecyclerViewActions.actionOnItem(
hasDescendant(withText("Text of item you want to scroll to")),
click()));
RecyclerViewActions.actionOnItem
- Realiza una ViewAction
en una vista emparejada por viewHolderMatcher
.
- Scroll
RecyclerView
a la vista que coincide conitemViewMatcher
- Realiza una acción en la vista combinada
Se pueden encontrar más detalles en: RecyclerViewActions.actionOnItem
La solución de Danny Roa es increíble, pero no funcionó para los elementos fuera de la pantalla a los que me acababa de desplazar. La solución está reemplazando esto:
View targetView = recyclerView.getChildAt(this.position)
.findViewById(this.viewId);
con este:
View targetView = recyclerView.findViewHolderForAdapterPosition(this.position)
.itemView.findViewById(this.viewId);
... en la clase TestUtils
.
Muy fácil. No se necesita biblioteca adicional. Hacer:
onView(withId(R.id.recycler_view))
.check(matches(atPosition(0, withText("Test Text"))));
si su ViewHolder usa ViewGroup, withText()
con un hasDescendant()
como:
onView(withId(R.id.recycler_view))
.check(matches(atPosition(0, hasDescendant(withText("Test Text")))));
con el método que puede poner en su clase de 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);
}
};
}
Si su artículo puede no estar visible en la pantalla al principio, desplácese hasta él antes de:
onView(withId(R.id.recycler_view))
.perform(scrollToPosition(87))
.check(matches(atPosition(87, withText("Test Text"))));
Para mejorar la respuesta de riwnodennyk, si su ViewHolder
es un ViewGroup
lugar de un objeto View
directo como TextView
, puede agregar hasDescendant
matcher para que coincida con el objeto TextView
en ViewGroup
. Ejemplo:
onView(withId(R.id.recycler_view))
.check(matches(atPosition(0, hasDescendant(withText("First Element")))));