Comment utiliser Espresso pour cliquer sur une vue spécifique dans un élément RecyclerView? Je sais que je peux cliquer sur l'élément en position 0 en utilisant:
onView(withId(R.id.recyclerView)) .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
Mais je dois cliquer sur une vue spécifique à l'intérieur de cet élément et non sur l'élément lui-même.
Merci d'avance.
-- modifier --
Pour être plus précis: j'ai un RecyclerView (R.id.recycler_view
) quels éléments sont CardView (R.id.card_view
). Dans chaque CardView J'ai quatre boutons (entre autres) et je veux cliquer sur un bouton spécifique (R.id.bt_deliver
).
J'aimerais utiliser les nouvelles fonctionnalités d'Espresso 2.0, mais je ne suis pas sûr que ce soit possible.
Si ce n’est pas possible, je voudrais utiliser quelque chose comme ceci (en utilisant le code Thomas Keller):
onRecyclerItemView(R.id.card_view, ???, withId(R.id.bt_deliver)).perform(click());
mais je ne sais pas quoi mettre sur les points d'interrogation.
Vous pouvez le faire avec une action d'affichage personnalisée.
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();
}
};
}
}
Ensuite, vous pouvez cliquer dessus avec
onView(withId(R.id.rv_conference_list)).perform(
RecyclerViewActions.actionOnItemAtPosition(0, MyViewAction.clickChildViewWithId(R.id. bt_deliver)));
Maintenant, avec Android.support.test.espresso.contrib, c'est devenu plus simple:
1) Ajouter une dépendance de test
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'
}
* exclure 3 modules, car très probablement vous l'avez déjà
2) Ensuite, fais quelque chose comme
onView(withId(R.id.recycler_grid))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
Ou
onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.actionOnItem(
hasDescendant(withText("whatever")), click()));
Ou
onView(withId(R.id.recycler_linear))
.check(matches(hasDescendant(withText("whatever"))));
Essayez l'approche suivante:
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;
}
}
};
}
}
Voici comment j'ai résolu le problème dans 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))
}
et alors
onView(withId(R.id.recyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(position, clickOnViewChild(R.id.viewToClickInTheRow)))
Vous pouvez cliquer sur ème élément de recyclerView
comme ceci:
onView(withId(R.id.recyclerView)).perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(2,click()))
Faites n'oubliez pas pour fournir le type ViewHolder
afin que l'inférence n'échoue pas.