tarjetas studio recyclerview recycler listas crear activity android android-recyclerview android-espresso

android - studio - Usando Espresso para hacer clic en ver dentro del elemento RecyclerView



recyclerview in activity (6)

Ahora con android.support.test.espresso.contrib se ha vuelto más fácil:

1) Agregar dependencia de prueba

androidTestCompile(''com.android.support.test.espresso:espresso-contrib:2.0'') { exclude group: ''com.android.support'', module: ''appcompat'' exclude group: ''com.android.support'', module: ''support-v4'' exclude module: ''recyclerview-v7'' }

* excluye 3 módulos, porque muy probablemente ya lo tengas

2) Luego haz algo como

onView(withId(R.id.recycler_grid)) .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));

O

onView(withId(R.id.recyclerView)) .perform(RecyclerViewActions.actionOnItem( hasDescendant(withText("whatever")), click()));

O

onView(withId(R.id.recycler_linear)) .check(matches(hasDescendant(withText("whatever"))));

¿Cómo puedo usar Espresso para hacer clic en una vista específica dentro de un elemento RecyclerView ? Sé que puedo hacer clic en el elemento en la posición 0 usando:

onView(withId(R.id.recyclerView)) .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));

Pero necesito hacer clic en una vista específica dentro de ese elemento y no en el elemento en sí.

Gracias por adelantado.

- editar -

Para ser más precisos: tengo un RecyclerView ( R.id.recycler_view ) cuyos elementos son CardView ( R.id.card_view ). Dentro de cada CardView tengo cuatro botones (entre otras cosas) y quiero hacer clic en un botón específico ( R.id.bt_deliver ).

Me gustaría usar las nuevas funciones de Espresso 2.0, pero no estoy seguro de que sea posible.

Si no es posible, quiero usar algo como esto (usando el código de Thomas Keller):

onRecyclerItemView(R.id.card_view, ???, withId(R.id.bt_deliver)).perform(click());

pero no sé qué poner en los signos de interrogación.


Aquí está, cómo resolví el problema en kotlin:

fun clickOnViewChild(viewId: Int) = object : ViewAction { override fun getConstraints() = null override fun getDescription() = "Click on a child view with specified id." override fun perform(uiController: UiController, view: View) = click().perform(uiController, view.findViewById<View>(viewId)) }

y entonces

onView(withId(R.id.recyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(position, clickOnViewChild(R.id.viewToClickInTheRow)))


Primero dé a sus botones un contenido único Descripciones, es decir, "fila de botones de entrega 5".

<button android:contentDescription=".." />

Luego desplácese a la fila:

onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.scrollToPosition(5));

Luego, seleccione la vista según el contenido Descripción.

onView(withContentDescription("delivery button row 5")).perform(click());

La Descripción del contenido es una excelente manera de usar onView de Espresso y hacer que su aplicación sea más accesible.


Prueba el siguiente enfoque:

onView(withRecyclerView(R.id.recyclerView) .atPositionOnView(position, R.id.bt_deliver)) .perform(click()); public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) { return new RecyclerViewMatcher(recyclerViewId); } public class RecyclerViewMatcher { final int mRecyclerViewId; public RecyclerViewMatcher(int recyclerViewId) { this.mRecyclerViewId = recyclerViewId; } public Matcher<View> atPosition(final int position) { return atPositionOnView(position, -1); } public Matcher<View> atPositionOnView(final int position, final int targetViewId) { return new TypeSafeMatcher<View>() { Resources resources = null; View childView; public void describeTo(Description description) { int id = targetViewId == -1 ? mRecyclerViewId : targetViewId; String idDescription = Integer.toString(id); if (this.resources != null) { try { idDescription = this.resources.getResourceName(id); } catch (Resources.NotFoundException var4) { idDescription = String.format("%s (resource name not found)", id); } } description.appendText("with id: " + idDescription); } public boolean matchesSafely(View view) { this.resources = view.getResources(); if (childView == null) { RecyclerView recyclerView = (RecyclerView) view.getRootView().findViewById(mRecyclerViewId); if (recyclerView != null) { childView = recyclerView.findViewHolderForAdapterPosition(position).itemView; } else { return false; } } if (targetViewId == -1) { return view == childView; } else { View targetView = childView.findViewById(targetViewId); return view == targetView; } } }; } }


Puede hacer clic en el tercer elemento de recyclerView como este:

onView(withId(R.id.recyclerView)).perform( RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(2,click()))

No olvide proporcionar el tipo ViewHolder para que la inferencia no falle.


Puede hacerlo con la acción de vista personalizada.

public class MyViewAction { public static ViewAction clickChildViewWithId(final int id) { return new ViewAction() { @Override public Matcher<View> getConstraints() { return null; } @Override public String getDescription() { return "Click on a child view with specified id."; } @Override public void perform(UiController uiController, View view) { View v = view.findViewById(id); v.performClick(); } }; } }

Luego puedes hacer clic con

onView(withId(R.id.rv_conference_list)).perform( RecyclerViewActions.actionOnItemAtPosition(0, MyViewAction.clickChildViewWithId(R.id. bt_deliver)));