Skip to content

Commit

Permalink
(Calendar) Respect disabled dates when selection date range #75
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkeppeler committed Jan 1, 2024
1 parent 5b0d0bb commit 5637c2c
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package com.maxkeppeler.sheets.calendar.functional

import android.util.Range
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createComposeRule
Expand Down Expand Up @@ -145,6 +146,121 @@ class CalendarViewTests {
assert(endDate == testEndDate)
}

@Test
fun calendarViewDateSelectionStyleMonthConfigDatesDisabled() {
val testDate = LocalDate.now().withDayOfMonth(15)
val newDates = listOf(
testDate.plusDays(2),
testDate,
testDate.minusDays(3)
)
val disabledDates = listOf(
testDate.minusDays(3),
)
var selectedDate: LocalDate? = null
rule.setContentAndWaitForIdle {
CalendarView(
useCaseState = UseCaseState(visible = true),
selection = CalendarSelection.Date(
onSelectDate = { dates -> selectedDate = dates }
),
config = CalendarConfig(
style = CalendarStyle.MONTH,
disabledDates = disabledDates
)
)
}

newDates.forEach { date ->
rule.onNodeWithTags(
TestTags.CALENDAR_DATE_SELECTION,
date.format(DateTimeFormatter.ISO_DATE)
).performClick()
}

rule.onPositiveButton().performClick()
assert(selectedDate == testDate)
}

@Test
fun calendarViewDatesSelectionStyleMonthConfigDatesDisabled() {
val testDate = LocalDate.now().withDayOfMonth(15)
val defaultDates = listOf(
testDate.minusDays(10),
testDate.minusDays(5)
)
val newDates = listOf(
testDate,
testDate.minusDays(3)
)
val disabledDates = listOf(
testDate.minusDays(3),
)
var selectedDates: List<LocalDate>? = null
rule.setContentAndWaitForIdle {
CalendarView(
useCaseState = UseCaseState(visible = true),
selection = CalendarSelection.Dates(
selectedDates = defaultDates,
onSelectDates = { dates -> selectedDates = dates }
),
config = CalendarConfig(
style = CalendarStyle.MONTH,
disabledDates = disabledDates
)
)
}

newDates.forEach { date ->
rule.onNodeWithTags(
TestTags.CALENDAR_DATE_SELECTION,
date.format(DateTimeFormatter.ISO_DATE)
).performClick()
}

rule.onPositiveButton().performClick()
assert(selectedDates?.sorted() == (defaultDates + testDate).sorted())
}


@Test
fun calendarViewPeriodSelectionStyleMonthConfigDatesDisabled() {
val testDate = LocalDate.now().withDayOfMonth(15)
val disabledDates = listOf(
testDate.minusDays(1),
testDate.minusDays(2),
testDate.minusDays(3),
)
val testStartDate = testDate.minusDays(4)
val testEndDate = testDate.plusDays(2)
var selectedDate: Range<LocalDate>? = null
rule.setContentAndWaitForIdle {
CalendarView(
useCaseState = UseCaseState(visible = true),
selection = CalendarSelection.Period { startDate, endDate ->
selectedDate = Range(startDate, endDate)
},
config = CalendarConfig(
style = CalendarStyle.MONTH,
disabledDates = disabledDates
)
)
}

rule.onNodeWithTags(
TestTags.CALENDAR_DATE_SELECTION,
testStartDate.format(DateTimeFormatter.ISO_DATE)
).performClick()

rule.onNodeWithTags(
TestTags.CALENDAR_DATE_SELECTION,
testEndDate.format(DateTimeFormatter.ISO_DATE)
).performClick()

rule.onPositiveButton().assertIsNotEnabled()
assert(selectedDate == null)
}

@Test
fun calendarViewPeriodSelectionInvalid() {
rule.setContentAndWaitForIdle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,16 +245,29 @@ internal class CalendarState(
}

is CalendarSelection.Period -> {
val beforeStart =
range.startValue?.let { newDate.isBefore(it) } ?: false
val containsDisabledDate = range.endValue?.let { startDate ->
config.disabledDates?.any { it.isAfter(startDate) && it.isBefore(newDate) }
// Check if the selected range includes any disabled dates
val includesDisabledDate = range.startValue?.let { startDate ->
config.disabledDates?.any { disabledDate ->
disabledDate.isAfter(startDate) && disabledDate.isBefore(newDate) || disabledDate == newDate
}
} ?: false
if (isRangeSelectionStart || beforeStart || containsDisabledDate) {

// Reset the range if the selection includes a disabled date
if (includesDisabledDate) {
range[Constants.RANGE_START] = newDate
range[Constants.RANGE_END] = null
return
}

// Check if the selection is the start or the date is before the start
val beforeStart = range.startValue?.let { newDate.isBefore(it) } ?: false
if (isRangeSelectionStart || beforeStart) {
// Reset the range if the selection includes a disabled date
range[Constants.RANGE_START] = newDate
range[Constants.RANGE_END] = null
isRangeSelectionStart = false
} else {
// Check if the selection is the end or the date is after the end
range[Constants.RANGE_END] = newDate
isRangeSelectionStart = true
}
Expand Down

0 comments on commit 5637c2c

Please sign in to comment.