Question

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());
Was it helpful?

Solution

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);
            }
        };
    }

OTHER TIPS

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")));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top