如何在 Espresso 测试中对 MaterialDatePicker 执行操作?

问题描述 投票:0回答:2

我有一个

MaterialDatePicker
对话框,我想编写一个选择日期的 Espresso 测试。不幸的是,我不能使用
PickerActions
来实现这一点。我正在寻找类似的东西:

onView(withClassName(Matchers.equalTo(DatePicker.class.getName()))).perform(PickerActions.setDate(year, monthOfYear, dayOfMonth));

有人对如何解决这个问题有任何想法吗?

提前致谢!

android android-espresso
2个回答
1
投票

我发现这个答案隐藏在上面链接的问题中,您可能会发现它对于在InputMode为

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

就非常紧密地依赖 ids 而不改变而言,这绝对是很糟糕的,但它是有效的。

如果您想选择输入模式为

INPUT_MODE_CALENDAR
的日期,那么这对我有用:

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())

您可以通过单击“材料日期选择器”布局中的相应按钮来进一步扩展此答案以选择不同的月/日/年。您可以在源代码中寻找 ids。


0
投票

我只想添加@Chantell Osejo 的评论。有些日期会有不同的内容描述,如下所示:

"Mon, Jan 1, 2024"
"Fri, Dec 29"
"Today Thu, Dec 28"

如果您使用

MaterialDatePicker.dateRangePicker()
,当您选择开始日期时,所选开始日期的内容描述将是例如
"Start date Mon, Jan 1, 2024"

这是我根据@Chantell Osejo 的评论制作的匹配器。仍然需要改进,请随时发表评论。

fun withDate(date: Date): Matcher<View> {
    fun areDatesEqual(calendar1: Calendar, calendar2: Calendar): Boolean {
        return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR) &&
                calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH) &&
                calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH)
    }

    fun areYearsEqual(calendar1: Calendar, calendar2: Calendar): Boolean {
        return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR)
    }
    val now = Calendar.getInstance()
    val selectedDate = Calendar.getInstance().apply {
        time = date
    }

    val isToday = areDatesEqual(now, selectedDate)
    val areYearsEqual = areYearsEqual(now, selectedDate)

    val dateFormat = if (areYearsEqual) {
        SimpleDateFormat("EEE, MMM d")
    } else {
        SimpleDateFormat("EEE, MMM d, yyyy")
    }

    val finalDate = if (isToday) {
        "Today ${dateFormat.format(date)}"
    } else {
        dateFormat.format(date)
    }

    return withContentDescription(finalDate)
}

用途:

val tomorrowCalendar = Calendar.getInstance().apply {
    add(Calendar.DAY_OF_MONTH, 1)
}
onView(withDate(tomorrowCalendar.time))
      .inRoot(RootMatchers.isDialog())
      .perform(click())
© www.soinside.com 2019 - 2024. All rights reserved.