How to set a specific rating in RatingBar in Espresso?
3 answers
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 to share
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 to share