I am trying to access the children in my custom expandablelist. The list looks like this :
Custom ExpandableList
I can successfully access the groups with :
Espresso.onView(allOf(withId(R.id.groupRowTextView1), withText(startsWith("Candida")))).perform(click());
When I try to access the child EditText like :
Espresso.onData(is(instanceOf(CustomExpandableListAdapter.class)))
.inAdapterView(withId(R.id.aversionsListView))
.onChildView(allOf(withId(R.id.childEditText), isDisplayed()))
.atPosition(1)
.perform(click());
I get this error :
11-30 16:47:45.733 2479-2492/com.foodaversions.people I/TestRunner﹕ ----- begin exception -----
11-30 16:47:45.733 2479-2492/com.foodaversions.people I/TestRunner﹕ com.google.android.apps.common.testing.ui.espresso.PerformException: Error performing 'load adapter data' on view 'with id: is <2131099682>'.
at com.google.android.apps.common.testing.ui.espresso.PerformException$Builder.build(PerformException.java:67)
at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:57)
at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:40)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:159)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.doPerform(ViewInteraction.java:90)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.perform(ViewInteraction.java:73)
at com.google.android.apps.common.testing.ui.espresso.DataInteraction.load(DataInteraction.java:135)
at com.google.android.apps.common.testing.ui.espresso.DataInteraction.perform(DataInteraction.java:112)
at com.foodaversions.people.ModifyAversionsTest.selectGlutenIntolerance(ModifyAversionsTest.java:49)
at com.foodaversions.people.ModifyAversionsTest.test(ModifyAversionsTest.java:20)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:115)
at junit.framework.TestResult.runProtected(TestResult.java:133)
at junit.framework.TestResult.run(TestResult.java:118)
at junit.framework.TestCase.run(TestCase.java:124)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:167)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1584)
Caused by: java.lang.RuntimeException: No data found matching: is an instance of com.foodaversions.people.adapters.CustomExpandableListAdapter contained values: <[Data: GroupStruct{id=6, name='Alcohol Intolerance', sourceTable=AVERSION_NAME, modifierEnum=EDITABLE, childData=
ChildStruct{id=-1, name='<Add Ingredient>', sourceTable=null, joinTable=null, modifierEnum=ADD_TEXT_VIEW}
}
(class: class com.foodaversions.people.data.ExpandableGroupData$GroupStruct) token: 0, Data: GroupStruct{id=8, name='Candida', sourceTable=AVERSION_NAME, modifierEnum=EDITABLE, childData=
ChildStruct{id=13, name='Sugar', sourceTable=AVERSION, joinTable=null, modifierEnum=DELETE}
ChildStruct{id=-1, name='<Add Ingredient>', sourceTable=null, joinTable=null, modifierEnum=ADD_TEXT_VIEW}
}
(class: class com.foodaversions.people.data.ExpandableGroupData$GroupStruct) token: 1, Data: ChildStruct{id=13, name='Sugar', sourceTable=AVERSION, joinTable=null, modifierEnum=DELETE} (class: class com.foodaversions.people.data.ChildStruct) token: 2, Data: ChildStruct{id=-1, name='<Add Ingredient>', sourceTable=null, joinTable=null, modifierEnum=ADD_TEXT_VIEW} (class: class com.foodaversions.people.data.ChildStruct) token: 3, Data: GroupStruct{id=3, name='Dairy Intolerance', sourceTable=AVERSION_NAME, modifierEnum=EDITABLE, childData=
ChildStruct{id=-1, name='<Add Ingredient>', sourceTable=null, joinTable=null, modifierEnum=ADD_TEXT_VIEW}
}
(class: class com.foodaversions.people.data.ExpandableGroupData$GroupStruct) token: 4, Data: GroupStruct{id=10, name='Egg Allergy', sourceTable=AVERSION_NAME, modifierEnum=EDITABLE, childData=
ChildStruct{id=-1, name='<Add Ingredient>', sourceTable=null, joinTable=null, modifierEnum
11-30 16:47:45.733 2479-2492/com.foodaversions.people I/TestRunner﹕ ----- end exception -----
I had trouble getting the child click to work, I found it easier to work out how to expand the list first :
Espresso.onData(allOf(is(instanceOf(ExpandableGroupData.GroupStruct.class)), withGroupName("Candida")))
.inAdapterView(withId(R.id.aversionsListView))
.perform(click());
I thought it might help towards the solution for clicking the child view.
Thanks to @Anna for providing the direction I needed to solve this:
// aversionsListView is the id of the ExpandableListView containing the expandable list
Espresso.onData(allOf(is(instanceOf(ChildStruct.class)), withChildName("<Add Ingredient>")))
.inAdapterView(withId(R.id.aversionsListView))
.check(matches(isDisplayed()))
.perform(click());
matcher :
public static Matcher<Object> withChildName(String name) {
checkNotNull(name);
return withChildName(equalTo(name));
}
public static Matcher<Object> withChildName(final Matcher<String> name) {
checkNotNull(name);
// ChildStruct is the Class returned by BaseExpandableListAdapter.getChild()
return new BoundedMatcher<Object, ChildStruct>(ChildStruct.class){
@Override
public boolean matchesSafely (final ChildStruct childStruct){
return name.matches(childStruct.name);
}
@Override
public void describeTo (Description description){
name.describeTo(description);
}
} ;
}
There are several points of using adapter views. If it is loading data from adapter you could not use simple view as if Espresso would not wait until data is loaded. If you are going to use
Espresso.onData(is(instanceOf(CustomExpandableListAdapter.class))) .inAdapterView(withId(R.id.aversionsListView))
then it its will return AdapterListView
. If you want to click on the second item of list then .atPosition(1)
is fine to use. If R.id.childEditText
is the type of your list element you have to match it with custom matcher. You could not use .onChildView(allOf(withId(R.id.childEditText), isDisplayed())).atPosition(1)
together.
I am suggesting to write a custom matcher. Please look into this. Custom matchers are helping to get the list item with matching it at the beginning.You can try to write something like this.
onData(allOf(is(instanceOf(<List item class for adapter>.class)), withListItemCheck(check_value))).check(matches(isDisplayed()));
Your matcher can be like this one:
public static Matcher<Object> withListItemCheck(final <Type> check_value) {
checkNotNull(check_value);
return new BoundedMatcher<Object, <List_Item_class>>(<List_Item_class>.class) {
private String m_message = "";
@Override
public void describeTo(Description d) {
d.appendText(m_message);
}
@Override
public boolean matchesSafely(<List_Item_class> listItem) {
m_message = "Expected " + listItem+ " and got ";
if (listItem== null) {
m_message += "empty";
return false;
}
return <assertion to check `check_value` is corresponding to `listItem` or not>;
}
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With