How to set a specific rating in RatingBar in Espresso?

I am trying to write an Espresso test that checks a RatingBar selection. How can I set a specific rating using Espresso? I only see the one click()

that always sets the average rating.

+3


source to share


3 answers


You need to create your own ViewAction subclass that calls setRating on the view and then pass an instance of your custom view action to the perform () method.



+4


source


The accepted answer helped me write the following custom ViewAction:



public final class SetRating implements ViewAction {

    @Override
    public Matcher<View> getConstraints() {
        Matcher <View> isRatingBarConstraint = ViewMatchers.isAssignableFrom(RatingBar.class);
        return isRatingBarConstraint;
    }

    @Override
    public String getDescription() {
        return "Custom view action to set rating.";
    }

    @Override
    public void perform(UiController uiController, View view) {
        RatingBar ratingBar = (RatingBar) view;
        ratingBar.setRating(3);
    }
}

      

+4


source


Instead of calling setRating

in a custom action the View that installs the software, you can also send the tap event to the correct part of the view.

This means that you can use the parameter boolean fromUser

in your production code, avoiding the need to set the rating sign listener to zero before setting the rating:

ratingBar.setRating(viewModel.rating());
ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
    @Override
    public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
        if (fromUser) {
            viewModel.actions().onRate(rating);
        }
    }
});

      


The following was enough for me, since my rating scale is set to 0.5 steps and has only 5 stars:

RateableMovieViewModel viewModel = viewModel(userActions).build();
rateableMovieViewHolder.bind(viewModel);

onView(withId(R.id.item_rateable_rating)).perform(setRating(4.5f));

verify(userActions).onRate(4.5f);

      


private static ViewAction setRating(final float rating) {
    if (rating % 0.5 != 0) {
        throw new IllegalArgumentException("Rating must be multiple of 0.5f");
    }

    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isAssignableFrom(RatingBar.class);
        }

        @Override
        public String getDescription() {
            return "Set rating on RatingBar in 0.5f increments";
        }

        @Override
        public void perform(UiController uiController, View view) {
            GeneralClickAction viewAction = new GeneralClickAction(
                    Tap.SINGLE,
                    new CoordinatesProvider() {
                        @Override
                        public float[] calculateCoordinates(View view) {
                            int[] locationOnScreen = new int[2];
                            v.getLocationOnScreen(locationOnScreen);
                            int screenX = locationOnScreen[0];
                            int screenY = locationOnScreen[1];
                            int numStars = ((RatingBar) view).getNumStars();
                            float widthPerStar = 1f * view.getWidth() / numStars;
                            float percent = rating / numStars;
                            float x = screenX + view.getWidth() * percent;
                            float y = screenY + view.getHeight() * 0.5f;
                            return new float[]{x - widthPerStar * 0.5f, y};
                        }
                    },
                    Press.FINGER,
                    InputDevice.SOURCE_UNKNOWN,
                    MotionEvent.BUTTON_PRIMARY
            );
            viewAction.perform(uiController, view);
        }
    };
}

      

+1


source







All Articles