Wie kann ich mit Espresso auf eine bestimmte Ansicht in einem RecyclerView Element klicken? Ich weiß, dass ich den Artikel an Position 0 mit folgendem Befehl anklicken kann:
onView(withId(R.id.recyclerView)) .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
Ich muss jedoch auf eine bestimmte Ansicht in diesem Artikel klicken und nicht auf den Artikel selbst.
Danke im Voraus.
- bearbeiten -
Genauer gesagt: Ich habe ein RecyclerView (R.id.recycler_view
) welche Elemente sind CardView (R.id.card_view
). In jedem CardView Ich habe (unter anderem) vier Schaltflächen und möchte auf eine bestimmte Schaltfläche klicken (R.id.bt_deliver
).
Ich möchte die neuen Funktionen von Espresso 2.0 nutzen, bin mir aber nicht sicher, ob dies möglich ist.
Wenn nicht möglich, möchte ich so etwas benutzen (mit Thomas Keller Code):
onRecyclerItemView(R.id.card_view, ???, withId(R.id.bt_deliver)).perform(click());
aber ich weiß nicht, was ich auf die Fragezeichen setzen soll.
Sie können dies mit der Aktion "Ansicht anpassen" tun.
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();
}
};
}
}
Dann können Sie mit darauf klicken
onView(withId(R.id.rv_conference_list)).perform(
RecyclerViewActions.actionOnItemAtPosition(0, MyViewAction.clickChildViewWithId(R.id. bt_deliver)));
Jetzt mit Android.support.test.espresso.contrib ist es einfacher geworden:
1) Testabhängigkeit hinzufügen
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'
}
* 3 Module ausschließen, da Sie es höchstwahrscheinlich bereits haben
2) Dann mach sowas
onView(withId(R.id.recycler_grid))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
Oder
onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.actionOnItem(
hasDescendant(withText("whatever")), click()));
Oder
onView(withId(R.id.recycler_linear))
.check(matches(hasDescendant(withText("whatever"))));
Versuchen Sie den nächsten Ansatz:
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;
}
}
};
}
}
Hier ist, wie ich das Problem in Kotlin gelöst habe:
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))
}
und dann
onView(withId(R.id.recyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(position, clickOnViewChild(R.id.viewToClickInTheRow)))
Sie können klicken auf . Element von recyclerView
wie folgt:
onView(withId(R.id.recyclerView)).perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(2,click()))
Verwenden Sie nicht vergessen, um den Typ ViewHolder
anzugeben, damit die Inferenz nicht fehlschlägt.