a_chubenko
a_chubenko

Reputation: 147

Check TextView in each item of RecyclerView with Espresso

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

Answers (1)

ror
ror

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.

  1. You need to rely on RecyclerView finding view holder capabilities, and build assertion around it (RecyclerView.ViewHolder holder = recyclerViewInstance.findViewHolderForAdapterPosition(index);)
  2. Find relevant view holder view using holder.itemView.findViewsWithText(listOfViews, text, FIND_VIEWS_WITH_TEXT); or for example holder.itemView.findViewById(yourViewId);
  3. Iterate through the items you have and execute the above for each item

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

Related Questions