Home » Android » Automating number picker in android using espresso

Automating number picker in android using espresso

Posted by: admin June 15, 2020 Leave a comment

Questions:

How to automate number picker using espresso. I want to set specific time in the timePicker using espresso.

How to&Answers:

To match a View by its class name you can simply use:

 onView(withClassName(Matchers.equalTo(TimePicker.class.getName())));

Once you have the ViewInteraction object you can set a value on it defining and using a ViewAction as following:

public static ViewAction setTime(final int hour, final int minute) {
        return new ViewAction() {
            @Override
            public void perform(UiController uiController, View view) {
                TimePicker tp = (TimePicker) view;
                tp.setCurrentHour(hour);
                tp.setCurrentMinute(minute)
            }
            @Override
            public String getDescription() {
                return "Set the passed time into the TimePicker";
            }
            @Override
            public Matcher<View> getConstraints() {
                return ViewMatchers.isAssignableFrom(TimePicker.class);
            }
        };
    }

Answer:

Match the view and then perform the action:

ViewInteraction numPicker = onView(withClassName(Matchers.equalTo(NumberPicker.class.getName())));
numPicker.perform(setNumber(1));

Create a ViewAction to set the number:

public static ViewAction setNumber(final int num) {
    return new ViewAction() {
        @Override
        public void perform(UiController uiController, View view) {
            NumberPicker np = (NumberPicker) view;
            np.setValue(num);

        }

        @Override
        public String getDescription() {
            return "Set the passed number into the NumberPicker";
        }

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

Answer:

There is a problem with accepted answer : it does not fire on change event. So (if you need it) you can’t test if your view react to this on change event.

The following code (kotlin) is not cool anyway but i think it’s the only way.

fun setValue(value: Int): ViewAction {
    return object : ViewAction {
        override fun getDescription(): String {
            return "set the value of a " + NumberPicker::class.java.name
        }

        override fun getConstraints(): Matcher<View> {
            return ViewMatchers.isAssignableFrom(NumberPicker::class.java)
        }

        // the only way to fire onChange event is to call this private method
        override fun perform(uiController: UiController?, view: View?) {
            val numberPicker = view as NumberPicker

            val setValueMethod = NumberPicker::class.java.getDeclaredMethod(
                "setValueInternal",
                Int::class.java,
                Boolean::class.java
            )

            setValueMethod.isAccessible = true

            setValueMethod.invoke(numberPicker, value, true)
        }
    }
}

Answer:

For those looking at this question later (like me) this might be helpful: DateTimePickerTest makes use of PickerActions. PickerActions allows code for date pickers like this (Java):

onView(withClassName(Matchers.equalTo(DatePicker.class.getName()))).perform(PickerActions.setDate(year, month + 1, day));

Or for time pickers (Kotlin):

onView(withClassName(Matchers.equalTo(TimePicker::class.java.name))).perform(PickerActions.setTime(0, 10))

Answer:

I have found a solution to the problem, that Luigi Massa Gallerano’s solution does not trigger the change listener.

Additionally to his method you need to add a wrapping method, that swipes up and down one time each. This triggers the changeListener, though the former value of course, is lost.

fun setNumberPickerValue(viewInteraction: ViewInteraction, value: Int) {
    viewInteraction.perform(setValue(value))

    viewInteraction.perform(GeneralSwipeAction(Swipe.SLOW, GeneralLocation.TOP_CENTER, GeneralLocation.BOTTOM_CENTER, Press.FINGER))
    SystemClock.sleep(50)
    viewInteraction.perform(GeneralSwipeAction(Swipe.SLOW, GeneralLocation.BOTTOM_CENTER, GeneralLocation.TOP_CENTER, Press.FINGER))
    SystemClock.sleep(50)

}

The example given is using NumberPicker and Kotlin, but in principle, it’s the same.

Answer:

I used the built-in TimePickerDialog.

![Looks like this

(Kotlin)

fun setAlarmTime(){

    val calendar = Calendar.getInstance()

    onView(isAssignableFrom(TimePicker::class.java)).perform(
        PickerActions.setTime(
            calendar.get(Calendar.HOUR_OF_DAY),
            calendar.get(Calendar.MINUTE) + 2
        )
    )
    onView(withText("OK")).perform(click())
}

Firstly, you should open the TimePickerDialog, then use this code. The time will be the current time + 2 minute. After the setup, it clicks on the OK button.