does anybody know, how to set a seekBar to a specific value or just a click on that view on Espresso UI Testing ?
I just get an exception: Error performing 'single click' on view with id...
onView(withId(R.id.FilterPriceMax)).perform(click());
does anybody know, how to set a seekBar to a specific value or just a click on that view on Espresso UI Testing ?
I just get an exception: Error performing 'single click' on view with id...
onView(withId(R.id.FilterPriceMax)).perform(click());
You might want to give the following code a try:
First you could match the SeekBar with its class name:
onView(withClassName(Matchers.equalTo(SeekBar.class.getName()))).perform(setProgress(progress));
where setProgress(final int progress) is a ViewAction you defined as:
public static ViewAction setProgress(final int progress) {
return new ViewAction() {
@Override
public void perform(UiController uiController, View view) {
SeekBar seekBar = (SeekBar) view;
seekBar.setProgress(progress);
}
@Override
public String getDescription() {
return "Set a progress on a SeekBar";
}
@Override
public Matcher<View> getConstraints() {
return ViewMatchers.isAssignableFrom(SeekBar.class);
}
};
}
I have a custom Seekbar, and also I have multiple Seekbars in my View. I managed do my test with this code below:
onView(withId(R.id.my_seek_bar)).perform(setProgress(10));
and
public static ViewAction setProgress(final int progress) {
return new ViewAction() {
@Override
public void perform(UiController uiController, View view) {
((MyCustomSeekBar) view).setSelectedProgress(progress);
//or ((SeekBar) view).setProgress(progress);
}
@Override
public String getDescription() {
return "Set a progress";
}
@Override
public Matcher<View> getConstraints() {
return ViewMatchers.isAssignableFrom(RangeSeekBar.class);
}
};
}
I use a swipe-action to perform an actual swipe on the SeekBar. This makes sure the callback method (SeekBar.OnSeekBarChangeListener. onProgressChanged) is called with fromUser set to true. It is also more in the line of click testing.
public static ViewAction scrubSeekBarAction(int progress) {
return actionWithAssertions(new GeneralSwipeAction(
Swipe.SLOW,
new SeekBarThumbCoordinatesProvider(0),
new SeekBarThumbCoordinatesProvider(progress),
Press.PINPOINT));
}
private static class SeekBarThumbCoordinatesProvider implements CoordinatesProvider {
int mProgress;
public SeekBarThumbCoordinatesProvider(int progress) {
mProgress = progress;
}
private static float[] getVisibleLeftTop(View view) {
final int[] xy = new int[2];
view.getLocationOnScreen(xy);
return new float[]{ (float) xy[0], (float) xy[1] };
}
@Override
public float[] calculateCoordinates(View view) {
if (!(view instanceof SeekBar)) {
throw new PerformException.Builder()
.withViewDescription(HumanReadables.describe(view))
.withCause(new RuntimeException(String.format("SeekBar expected"))).build();
}
SeekBar seekBar = (SeekBar) view;
int width = seekBar.getWidth() - seekBar.getPaddingLeft() - seekBar.getPaddingRight();
double progress = mProgress == 0 ? seekBar.getProgress() : mProgress;
int xPosition = (int) (seekBar.getPaddingLeft() + width * progress / seekBar.getMax());
float[] xy = getVisibleLeftTop(seekBar);
return new float[]{ xy[0] + xPosition, xy[1] + 10 };
}
}
In case you want to check the progress value
public static Matcher<View> withProgress(final int expectedProgress) {
return new BoundedMatcher<View, SeekBar>(SeekBar.class) {
@Override
public void describeTo(Description description) {
description.appendText("expected: ");
description.appendText(""+expectedProgress);
}
@Override
public boolean matchesSafely(SeekBar seekBar) {
return seekBar.getProgress() == expectedProgress;
}
};
}
I have used this to do some basic testing on seekbar UI components if you don't require specific values. It assumes the 'check()' is based on a 0-100 percentage.
onView(withId(R.id.yourSeekBar)).perform(new GeneralClickAction(Tap.SINGLE, GeneralLocation.CENTER_LEFT, Press.FINGER));
onView(withId(R.id.yourSeekBarUserFeedback)).check(matches(withText("0")));
onView(withId(R.id.yourSeekBar)).perform(new GeneralClickAction(Tap.SINGLE, GeneralLocation.CENTER, Press.FINGER));
onView(withId(R.id.yourSeekBarUserFeedback)).check(matches(withText("50")));
onView(withId(R.id.yourSeekBar)).perform(new GeneralClickAction(Tap.SINGLE, GeneralLocation.CENTER_RIGHT, Press.FINGER));
onView(withId(R.id.yourSeekBarUserFeedback)).check(matches(withText("100")));