Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Espresso - Click by text in List view

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())

like image 353
Chad Bingham Avatar asked Apr 09 '14 14:04

Chad Bingham


People also ask

How to test a textview with espresso?

Here’s how to test this with Espresso: The first step is to look for a property that helps to find the button. The button in the SimpleActivity has a unique R.id, as expected. Now to perform the click: The TextView with the text to verify has a unique R.id too: Now to verify the content text:

What is a view action in espresso?

As learned earlier, view actions automate all the possible actions performable by users in an android application. Espresso onView and “onData” provides the perform method, which accepts view actions and invokes/automates the corresponding user actions in the test environment.

Why can't I see getview () and getcurrentactivity () in espresso API?

At the same time, the framework prevents direct access to activities and views of the application because holding on to these objects and operating on them off the UI thread is a major source of test flakiness. Thus, you will not see methods like getView () and getCurrentActivity () in the Espresso API.

How to use expected text pattern in espresso viewmatchers?

For simplicity following String XXYYZZ will be used as a expected text pattern. Espresso ViewMatchers class implements two String matcher methods withText () and withContentDescription () which will match a view which text is equal to specified expectedText or specified expectedContentDescriptionText parameter passed into it.


2 Answers

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()); 
like image 82
haffax Avatar answered Sep 28 '22 23:09

haffax


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()); 
like image 42
Veer Avatar answered Sep 28 '22 21:09

Veer