Espresso - Click by text in List view
Solution 1
The problem is, that you try to match the list view itself with the instanceOf(ListView.class)
as argument for onData()
. onData()
requires a data matcher that matches the adapted data of the ListView
, not the ListView
itself, and also not the View
that Adapter.getView()
returns, but the actual data.
If you have something like this in your production code:
ListView listView = (ListView)findViewById(R.id.myListView);
ArrayAdapter<MyDataClass> adapter = getAdapterFromSomewhere();
listView.setAdapter(adapter);
Then the Matcher argument of Espresso.onData()
should match the desired instance of MyDataClass
.
So, something like this should work:
onData(hasToString(startsWith("ASDF"))).perform(click());
(You can use another Matcher using a method of org.hamcrest.Matchers
)
In case you have multiple adapter views in your activity, you can call ViewMatchers.inAdapterView()
with a view matcher that specifies the AdapterView like this:
onData(hasToString(startsWith("ASDF")))
.inAdapterView(withId(R.id.myListView))
.perform(click());
Solution 2
If adapter have custom model class for example Item
:
public static Matcher<Object> withItemValue(final String value) {
return new BoundedMatcher<Object, Item>(Item.class) {
@Override
public void describeTo(Description description) {
description.appendText("has value " + value);
}
@Override
public boolean matchesSafely(Item item) {
return item.getName().toUpperCase().equals(String.valueOf(value));
}
};
}
Then call following:
onData(withItemValue("DRINK1")).inAdapterView(withId(R.id.menu_item_grid)).perform(click());
Chad Bingham
Arguing with a software engineer is like wrestling with a pig in the mud; after a while you realize the pig likes it. -Unknown
Updated on June 17, 2020Comments
-
Chad Bingham almost 4 years
I am trying to click on a text in a list view using Espresso. I know they have this guide, but I can't see how to make this work by looking for text. This is what I have tried
Espresso.onData(Matchers.allOf(Matchers.is(Matchers.instanceOf(ListView.class)), Matchers.hasToString(Matchers.startsWith("ASDF")))).perform(ViewActions.click());
As expected, this didn't work. The error said no view in hierarchy. Does anyone know how to select a String? (
"ASDF"
in this case) Thanks in advance.Update due to @haffax
I received error:
com.google.android.apps.common.testing.ui.espresso.AmbiguousViewMatcherException: 'is assignable from class: class android.widget.AdapterView' matches multiple views in the hierarchy.
Second error
With this code
onData(hasToString(startsWith("ASDF"))).inAdapterView(withContentDescription("MapList")).perform(click());
I get this error
com.google.android.apps.common.testing.ui.espresso.PerformException: Error performing 'load adapter data' on view 'with content description: is "MapList"'.
Caused by: java.lang.RuntimeException: No data found matching: asString(a string starting with "ASDF")
Solution
onData(anything()).inAdapterView(withContentDescription("desc")).atPosition(x).perform(click())
-
haffax about 10 yearsAnswer extended to include solution for multiple AdapterViews in hierarchy.
-
Chad Bingham about 10 yearsI am getting the same error, but with less
**MATCHES**
-
Chad Bingham about 10 yearsThe two that match, seem to be the same though. The only difference I can see is one
is=focused=false
-
haffax about 10 yearsWell, you'll have to sort the matching out yourself. Seems weird to have so many different list views with the same id. Can't you give your list views different IDs? Or is this because the are used in ListFragments? Other ways to further distinguish: Assign a tag to the view and use the hasTag() matcher or use isDescendantOfA() to distinguish via hierarchy.
-
Chad Bingham about 10 yearsYeah I think it is odd too. i didn't write the app, I just test it. But yes, you're right, I can't give them different id's cause they are in ListFragments. I will look in to adding a tag.
-
Chad Bingham about 10 yearsIf I look in the uiautomatorviewer, I only see one ListView. I don't get how its finding two??
-
Chad Bingham about 10 yearsAlright, so I have given one list a content description. How could i click by text within content description?
-
Tomask about 8 yearsBe aware that if you have e.g. nav drawer with list view, it can be a second adapter view! so as it was already said,
inAdapterView()
must be used in that case to differentiate between them -
mbob almost 6 yearsthis works for me on one screen, but on another screen, Espresso seems to scroll to that item, but the item is not clicked even if perform(click()) is called (tested this with breakpoints)....this is very weird