wake-up-neo.com

Klicken Sie mit Espresso auf Ansicht in RecyclerView

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.

86
Filipe Ramos

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)));
119
blade

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"))));
58
Andrey

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

            }
        };
    }
}
6
Sergey

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)))
4
user2768856

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.

2
erluxman