Reputation: 147
There is a RecyclerView (R.id.recycler_view). Each item (R.id.movie_card) contains two views: ImageView and TextView (R.id.movie_title_text_view). The goal is to check with the Espresso that all of recyclerview's items contain not empty text view. Please help to write code correctly.
There is using also Idle. So, the moment of start testing RecyclerView is correct (after all data is loaded).
There is not clear how to make assertion that all of the R.id.movie_title_text_view are not empty. Full test method is following:
@Rule
public ActivityTestRule activityTestRule = new ActivityTestRule(MainActivity.class);
@Test
public void GridFragmentRecycleViewTest(){
final int TESTED_VIEWHOLDERS_QUANTITY = 10;
IdlingResource componentIdlingResource = getIdlingResource();
Espresso.registerIdlingResources(componentIdlingResource);
Log.d(TAG, "GridFragmentRecycleViewTest()");
onView(withId(R.id.action_search)).perform(click());
onView(isAssignableFrom(SearchView.class)).perform(typeSearchViewText("lord")).perform(pressKey(KeyEvent.KEYCODE_ENTER));
EspressoIdlingResource.increment();
onView(withId(R.id.recycler_view)).check(new RecyclerViewItemCountAssertion(TESTED_VIEWHOLDERS_QUANTITY));
//up to here all works good
onView(allOf(withId(R.id.movie_title_text_view))).check(matches(withText(not(isEmptyString()))));
}
public static ViewAction typeSearchViewText(final String text){
return new ViewAction(){
@Override
public Matcher<View> getConstraints() {
//Ensure that only apply if it is a SearchView and if it is visible.
return allOf(isDisplayed(), isAssignableFrom(SearchView.class));
}
@Override
public String getDescription() {
return "Change view text";
}
@Override
public void perform(UiController uiController, View view) {
((SearchView) view).setQuery(text,false);
}
};
}
The line:
onView(allOf(withId(R.id.movie_title_text_view))).check(matches(withText(not(isEmptyString()))));
makes the following exception: androidx.test.espresso.AmbiguousViewMatcherException: '(with id: com.example.myapplication3:id/movie_title_text_view)' matches multiple views in the hierarchy. Problem views are marked with '****MATCHES****' below.
View Hierarchy: +>DecorView{id=-1, visibility=VISIBLE, width=1440, height=2560, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) ty=BASE_APPLICATION wanim=0x10302f8 fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3} ...
Upvotes: 1
Views: 1672
Reputation: 3500
This is not ready to use answer, but if you get no other answers it will hopefully help drive you into right direction.
RecyclerView.ViewHolder holder = recyclerViewInstance.findViewHolderForAdapterPosition(index);
)holder.itemView.findViewsWithText(listOfViews, text, FIND_VIEWS_WITH_TEXT);
or for example holder.itemView.findViewById(yourViewId);
You may want to build some view assertion for the purpose:
public static ViewAssertion hasViewWithXyzAtPosition(final int index, final CharSequence text) {
return new ViewAssertion() {
@Override
public void check(View view, NoMatchingViewException e) {
if (!(view instanceof RecyclerView)) {
throw e;
}
RecyclerView rv = (RecyclerView) view;
RecyclerView.ViewHolder holder = rv.findViewHolderForAdapterPosition(index);
//...
Assert.assertTrue(
"There's no view at index " + index + ",
...
);
}
};
}
Upvotes: 1