Issue
I am new to using espresso. I cannot really get what I wanted to test using this code:
onData(withId(R.id.relativelayout_tag))
.inAdapterView(withId(R.id.recyclerview_tag_list))
.onChildView(withId(R.id.imageview_tag))
.atPosition(1)
.check(matches(isDisplayed()));
Where R.id.imageview_tag
is a child of R.id.relativelayout_tag
. R.id.relativelayout_tag
holds the entire content for my adapter item. R.id.recyclerview_tag_list
is the name of my RecyclerView
on which I assigned a particular RecyclerView
Adapter
.
This is a very very basic test. Here are the user procedures:
- Select, SPECIFICALLY, the first item on the
RecyclerView
(I don't really care what text is on the view). Also do not suggest using view text to identify the first item. I DONT CARE ABOUT THE ADAPTER ITEM'S CONTENT or even putting a unique tag on some view. - On select, the indicator view(An ImageView that shows that the item is selected) should appear.
Very basic and simple. It is so hard to write a test for this basic user story using Espresso. When I run that particular test it always fail stating this:
Caused by: java.lang.RuntimeException: Action will not be performed because the target view does not match one or more of the following constraints:
(is assignable from class: class android.widget.AdapterView and is displayed on the screen to the user)
Target view: "RecyclerView{id=2131624115, res-name=recyclerview_tag_list, visibility=VISIBLE, width=480, height=1032, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=15}"
It doesn't make sense as I have the list already visible. I can even run this test just fine:
onView(withId(R.id.recyclerview_tag_list))
.perform(RecyclerViewActions
.actionOnItemAtPosition(1, click()));
Here is the full test:
@Test
public void shouldTagToggleSelected()
{
onView(withId(R.id.recyclerview_tag_list))
.perform(RecyclerViewActions
.actionOnItemAtPosition(1, click()));
onData(withId(R.id.relativelayout_tag))
.inAdapterView(withId(R.id.recyclerview_tag_list))
.onChildView(withId(R.id.imageview_tag))
.atPosition(1)
.check(matches(isDisplayed()));
//onView(withId(R.id.imageview_tag))
// .check(matches(isDisplayed()));
}
What I wanted to test if the indicator view has a visibility set to visible
ONLY on that particular item (or any item of my choosing).
Any thoughts? Maybe I missed something dearly.
Thanks a lot!
Solution
onData
does not work with RecyclerView
as RecyclerView
does not extend AdapterView
.
You need to use onView
to make your assertions. If it's the first item in the recycler view, then you can use something like this matcher to make your assertion:
public static Matcher<View> withViewAtPosition(final int position, final Matcher<View> itemMatcher) {
return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {
@Override
public void describeTo(Description description) {
itemMatcher.describeTo(description);
}
@Override
protected boolean matchesSafely(RecyclerView recyclerView) {
final RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position);
return viewHolder != null && itemMatcher.matches(viewHolder.itemView);
}
};
}
And the usage is the following:
onView(withId(R.id.recyclerview_tag_list))
.check(matches(withViewAtPosition(1, hasDescendant(allOf(withId(R.id.imageview_tag), isDisplayed())))));
Keep in mind that this matcher will fail if your ViewHolder has not been laid out yet. If that's the case you need to scroll to the ViewHolder with RecyclerViewActions. You don't need to scroll if you are clicking the item in the test prior to using the matcher.
Answered By - Be_Negative
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.