How to perform an action on MaterialDatePicker in an Espresso test? - android

I have a MaterialDatePicker dialog, and I want to write an Espresso test that selects a date. Unfortunately, I can't use PickerActions for this. I'm looking for something similar to this:
onView(withClassName(Matchers.equalTo(DatePicker.class.getName()))).perform(PickerActions.setDate(year, monthOfYear, dayOfMonth));
Does anyone have any ideas on how to go about this?
Thanks in advance!

I found this answer buried in the question linked above, which you may find useful for setting the date when the InputMode is INPUT_MODE_TEXT.
public static void setDate(LocalDate date){
onView(withTagValue((Matchers.is((Object) ("TOGGLE_BUTTON_TAG"))))).perform(click());
onView(withId(com.google.android.material.R.id.mtrl_picker_text_input_date)).perform(replaceText(date.format(DateTimeFormatter.ofPattern("M/d/yy"))));
}
public static void setTime(LocalTime time){
onView(withId(com.google.android.material.R.id.material_timepicker_mode_button)).perform(click());
onView(withId(com.google.android.material.R.id.material_hour_text_input)).perform(click());
onView(allOf(isDisplayed(), withClassName(is(AppCompatEditText.class.getName())))).perform(replaceText(time.format(DateTimeFormatter.ofPattern("hh"))));
onView(withId(com.google.android.material.R.id.material_minute_text_input)).perform(click());
onView(allOf(isDisplayed(), withClassName(is(AppCompatEditText.class.getName())))).perform(replaceText(time.format(DateTimeFormatter.ofPattern("mm"))));
}
It's definitely janky in terms of relying very closely on the ids to not change, but it is effective.
If you want to select a date when the InputMode is INPUT_MODE_CALENDAR, then this worked for me:
onView(
// the date you are selecting must be visible for this to work
withContentDescription("Mon, Jan 1, 1990")
).inRoot(RootMatchers.isDialog())
.perform(click())
onView(withId(com.google.android.material.R.id.confirm_button))
.perform(click())
You could expand this answer further to select a different month/day/year by clicking on the appropriate buttons in the Material Date Picker layout. You can go spelunking for the ids in the source code.

Related

Android DatePicker: How to reset DatePicker to current date automatically after the user selects the date?

Hello StackOverFlow Community,
I have created an app with two DatePickers in one activity. I need for the DatePicker to reset to the current date after the user chooses the date with it. Next, I have a clear button in the activity. I need that to also reset the DatePicker to the current date onClick of that button. Can anyone help me to accomplish this?
I really appreciate your time. Please, if you are going to give me a minus point for this question, can you explain why? I am trying to get better and that is why I am here. Thanks again.
public void onResetClick(){
resetDateToToday();
}
public void onDateSelected(){
resetDateToToday();
}
public void resetDateToToday(){
Calendar cal = Calendar.getInstance();
datePicker.updateDate(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH) - 1,cal.get(Calendar.DAY_OF_MONTH));
}

Recording an Espresso test with a DatePicker

The test recorder produces code that promptly fails on being run after recording.
The reason is that while recording, I tap the year, the year spinner pops up, I scroll back and then select one of the years. The recorder does not capture the scrolling.
In Xcode, they added a method to scroll to the item. I could not find something akin in Espresso.
(Using Android Studio 2.3.)
I have not used the recorder in a long time and instead wrote my tests by hand.
I use the following line to set the date in a DatePicker:
onView(withClassName(Matchers.equalTo(DatePicker.class.getName()))).perform(PickerActions.setDate(year, monthOfYear, dayOfMonth));
The PickerActions class is defined in the espresso-contrib library. Add it as follows to your gradle file:
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0'
I then use this in a helper method which clicks the button that opens a DatePickerDialog, sets the date and confirms it by clicking the OK button:
public static void setDate(int datePickerLaunchViewId, int year, int monthOfYear, int dayOfMonth) {
onView(withParent(withId(buttonContainer)), withId(datePickerLaunchViewId)).perform(click());
onView(withClassName(Matchers.equalTo(DatePicker.class.getName()))).perform(PickerActions.setDate(year, monthOfYear, dayOfMonth));
onView(withId(android.R.id.button1)).perform(click());
}
And then use it in my tests as follows:
TestHelper.setDate(R.id.date_button, 2017, 1, 1);
//TestHelper is my helper class that contains the helper method above
Note: This answer is intended to supplement #stamanuel's answer.
To see an example in the Android source code of an Android instrumentation test which opens a DatePickerDialog and selects a date, refer to the PickerActionsTest.java file.
The two key lines of code in that file are the following:
// Sets a date on the date picker widget
onView(isAssignableFrom(DatePicker.class)).perform(setDate(1980, 10, 30));
// Confirm the selected date. This example uses a standard DatePickerDialog
// which uses
// android.R.id.button1 for the positive button id.
onView(withId(android.R.id.button1)).perform(click());
As #stamanuel has mentioned in his answer, the PickerActions.setDate(year:monthOfYear:dayOfMonth:) method is defined in the androidx.test.espresso:espresso-contrib library.

Custom DatePicker buttons

I would like to highlight that I am looking for a Xamarin solution. I have found Java solutions, but I can't seem to convert them to Xamarin. I want to have the user set their birthday and then have the app calculate their age, and display it as text. I have everything functioning. All I am looking to do is change the text on the "ok" button to "Calculate age." I am able to change the text, but the button doesn't grab the date from the picker then. This is how I create my datepicker:
DatePickerDialog setDate = new DatePickerDialog(this, onDateSet, date.Year, date.Month-1, date.Day);
then I use this method to change the text
setDate.SetButton("calculate age", EventHandler<DialogClickEventArgs>)
I have created an EventHandler called Age use for the second argument. What code do I put in the EventHandler to make the button function like the "ok" button? if I set handler:null the method works, I can also get the method to do other things, change text in textbox for a example. Any solution is welcomed.
Wow. No love for Xamarin? I discovered the solution was much simpler. Following from what I learned here: Change DatePickerDialog's button texts. I began throwing darts into the code and this is what stuck. Where I set handler to null I simply set listener to the dialog object like so. setDate.SetButton ("calculate age", listener:setDate);

Hours, Minutes selector widget

I am porting one of my iOS apps over to android, and one of the layouts uses the UIDatePicker with the mode UIDatePickerModeCountDownTimer. I have searched and searched and searched for something even close in android, and the only thing I have come across is the TimePicker widget which only seems to do time of day.
Does something like UIDatePickerModeCountDownTimer exist in android, or do I have to fenagle my own solution for entering this type of time.
There is no one stop shop that includes a date picker and a time picker, both are seperate
so basically you need a date field that shows a DatePickerDialog and a time field that show a TimePickerDialog when clicked
As far as I am aware you will either need a 3rd party library or you will need to create a custom version of the TimePicker.
EDIT :
Basically i've done something similar like your requirement, i have a time picker dialog in dialog fragment, without am/pm indicator. You only have to set the DateFormat to 24 hour format in onCreateDialog method. Something similar like this :
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the current time as the default values for the picker
int hour = 0;
int minute = 0;
// Create a new instance of TimePickerDialog without am/pm and return it
return new TimePickerDialog(getActivity(), this, hour, minute,
DateFormat.is24HourFormat(getActivity()));
}
I hope this answer help you :)

Changing the title on a TimePicker?

I'm trying to look for a solution to change the title on a TimePicker dialog. Right now it says whatever the system time is (ex. "12:23 AM") but I want to change this to something a little more descriptive. Does anyone have any suggestions?
By request. :)
By TimePicker dialog do you mean the
actual TimePickerDialog? Because that
has a setTitle(CharSequence text)
method. The TimePickerDialog is what
is used in the official tutorial.
http://developer.android.com/reference/android/app/AlertDialog.html#setTitle(java.lang.CharSequence)
This question is rather old, but it shows up on Google results if you search this question. So, I thought I'll post my solution.
DatePicker has setCustomTitle(View view), where you can define your own view (e.g. TextView with your custom text) to be used as a title. This one does not update when changing values.
I dont know how to reply to the comments below question, so I use "Answer".
By looking into source code: SourceCode
You may realize that OnTimeChangedListener is implemented by TimePickerDialog.
To avoid title changed while adjusting time, you may derived from TimePickerDialog and override public void onTimeChanged(TimePicker view, int hourOfDay, int minute);
Notice, dont call super version, or it will setTitle again...

Categories

Resources