onChildView and hasSiblings with Espresso
Solution 1
Based on your last comment you should use onView()
instead of onData()
.
I think you'll be able to click the button using hasSibling()
- example
onView(allOf(withId(R.id.positive), hasSibling(withDesc(someString))))
.perform(click());
or examples without your custom matcher (sibling view has text):
onView(allOf(withId(R.id.positive), hasSibling(withText(someString))))
.perform(click());
or (sibling view has content description):
onView(allOf(withId(R.id.positive), hasSibling(withContentDescription(someString))))
.perform(click());
EDITED:
OK, I'd try these two variants:
onView(allOf(withId(R.id.increaseGoalButton), isDescendantOfA(withId(R.id.timeGoalWidget))))
.perform(click());
or
onView(allOf(withId(R.id.increaseGoalButton), withParent(withId(R.id.timeGoalWidget))))
.perform(click());
Solution 2
None of your content descriptions match the string "description" that's why it doesn't find anything.
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 July 21, 2022Comments
-
Chad Bingham over 1 year
I am trying to access a button from a specific view. The same view is displayed 6 times. This is the code I am using.
public void testTimeConfig(){ onData(withDesc("description")).onChildView(withId(R.id.positive)).perform(click()); } private static Matcher<Object> withDesc(String desc) { return allOf(is(instanceOf(String.class)), is(desc)); }
When I run, I get an error:
Error performing 'load adapter data' on view 'is assignable from class: class android.widget.AdapterView'.
Is this the best way to access a child view? If so, how?
EDIT
This is the code I am trying to use now.
onView(allOf((withContentDescription("description")), hasSibling(withContentDescription("SettingsLayout")), hasSibling(withId(R.id.positive)))).perform(click());
and
onView(allOf((withContentDescription("description")), hasSibling(withId(R.id.positive)))).perform(click());
With this Error:
No views in hierarchy found matching
The xml
<view android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/setAGoalTitle" android:layout_alignParentLeft="true" class="com.xxx" android:layout_marginTop="30dp" android:id="@+id/timeGoalWidget" app:goalLabel="@string/time_min_upper" app:icon="@drawable/ic_icn_summary_time" app:step="300" app:valueFormat="time" android:gravity="center_horizontal" android:layout_marginBottom="60dp" android:contentDescription="setAGoalTimeConfigurator"/> <view android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignTop="@id/timeGoalWidget" class="com.xxx" android:id="@+id/distanceGoalWidget" app:goalLabel="@string/distance_upper" app:icon="@drawable/ic_icn_summary_track" app:step="0.25" app:valueFormat="decimal_two" android:gravity="center_horizontal" android:contentDescription="setAGoalDistanceConfigurator"/> <view android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/timeGoalWidget" android:layout_alignLeft="@id/timeGoalWidget" class="com.xxx" android:id="@+id/paceGoalWidget" app:goalLabel="@string/pace_upper" app:icon="@drawable/ic_icn_summary_pace" app:valueFormat="time" app:step="10" android:gravity="center_horizontal" android:layout_marginBottom="60dp" android:contentDescription="setAGoalPaceConfigurator"/> <view android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@id/distanceGoalWidget" android:layout_alignTop="@id/paceGoalWidget" class="com.xxx" android:id="@+id/speedGoalWidget" app:goalLabel="@string/speed_upper" app:icon="@drawable/ic_icn_summary_speed" app:step="0.5" app:valueFormat="decimal_two" android:gravity="center_horizontal" android:contentDescription="setAGoalSpeedConfigurator"/> <view android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/paceGoalWidget" android:layout_alignLeft="@id/paceGoalWidget" class="com.xxx" android:id="@+id/inclineGoalWidget" app:goalLabel="@string/incline_percent_upper" app:icon="@drawable/ic_icn_summary_elevation" app:step="0.5" app:valueFormat="decimal_two" android:gravity="center_horizontal" android:contentDescription="setAGoalInclineConfigurator"/> <view android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@id/speedGoalWidget" android:layout_alignTop="@id/inclineGoalWidget" class="com.xxx" android:id="@+id/caloriesGoalWidget" app:goalLabel="@string/calories_upper" app:icon="@drawable/ic_icn_summary_calories" app:step="10" app:valueFormat="decimal_zero" android:gravity="center_horizontal" android:contentDescription="setAGoalCaloriesConfigurator"/> </RelativeLayout>
The view xml that is used 6 times.
<ImageButton android:id="@+id/increaseGoalButton" android:layout_height="@dimen/view_goal_setting_incrementor_button_height_width" android:layout_width="@dimen/view_goal_setting_incrementor_button_height_width" android:background="@drawable/button_goal_widget" android:gravity="center" android:src="@drawable/ic_plus" android:textSize="@dimen/view_goal_setting_incrementor_button_text_size" android:textColor="@color/goal_configuration_widget_button_text_color" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginBottom="1dp" android:contentDescription="@string/increase"/> <ImageButton android:id="@+id/decreaseGoalButton" android:layout_height="@dimen/view_goal_setting_incrementor_button_height_width" android:layout_width="@dimen/view_goal_setting_incrementor_button_height_width" android:background="@drawable/button_goal_widget" android:gravity="center" android:src="@drawable/ic_minus" android:textSize="@dimen/view_goal_setting_incrementor_button_text_size" android:layout_alignParentRight="true" android:textColor="@color/goal_configuration_widget_button_text_color" android:layout_below="@id/increaseGoalButton" android:contentDescription="@string/decrease"/> <LinearLayout android:id="@+id/goalWidgetValueContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_toLeftOf="@id/increaseGoalButton" android:layout_centerVertical="true" android:gravity="center_vertical|right" android:layout_marginRight="@dimen/view_goal_setting_value_margin_right" > <TextView android:id="@+id/goalValueTextView" android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="@color/goal_configuration_widget_value_text_color" android:textSize="@dimen/view_goal_setting_value_text_size" android:lineSpacingExtra="-10sp" app:typeface="proxima_bold" android:text="999:00"/> <TextView android:id="@+id/goalValueLabelTextView" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_gravity="right" android:textSize="@dimen/view_goal_setting_value_label_text_size" android:textColor="@color/goal_configuration_widget_value_text_color" android:includeFontPadding="false" android:lineSpacingExtra="10sp" android:text="@string/incline_percent_upper"/> </LinearLayout>
It is the ImageView with id
increaseGoalButton
that I am trying to click. -
Chad Bingham over 10 yearsThese three examples are all the same
-
denys over 10 yearsThere are 3 cases: 1st with custom matcher, 2nd for a view with text and 3rd for a view with content description. Does any of them work for you?
-
Chad Bingham over 10 yearsSorry, I was looking at them on my phone and all I got was
onView(allOf(withId(R.id.positive)
so they all looked the same. I will play around with this and see if it works -
Chad Bingham over 10 years+1 for mentioning
hasSbiling()
. Do you know if it matters if the view is inside aRelativeLayout
, inside the parentRelativeLayout
? So it is two children deep? -
denys over 10 yearsTake a look at source code for
hasSibling()
matcher - link. Seems that they must be in the same parent. Can you also post your layout xml file, since it's hard to judge without it. -
Chad Bingham over 10 yearsOk I posted the xml. Take a look. Sorry for the delay. I had to edit it so I am not showing sensitive information.
-
Chad Bingham over 10 yearsIs the
com.xxx
needed? -
denys over 10 yearsNo, I just took it from your example. You should replace it with your real package name which you changed to com.xxx in above xml code.
-
Chad Bingham over 10 yearsRight. I am wondering if the com.package is need at all. Right now I am just using
R.id
. without thecom.xx
-
Chad Bingham over 10 years
hasParent
did not work. isDescendantOfA` does. Thanks. -
lacton over 9 years
hasParent
does not exist. There is awithParent
method instead. -
Ruwanka Madhushan almost 7 years+1 for
onView(allOf(withId(R.id.increaseGoalButton), isDescendantOfA(withId(R.id.timeGoalWidget)))) .perform(click());