Skip to content

Commit

Permalink
chore(DatePicker): document correct_invalid_date prop, and make sure …
Browse files Browse the repository at this point in the history
…functionality fires when min_date or max_date is set (#3240)
  • Loading branch information
joakbjerk authored Jan 22, 2024
1 parent a9223c3 commit 0912bb7
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
| `status_state` | _(optional)_ defines the state of the status. Currently, there are two statuses `[error, info]`. Defaults to `error`. |
| `status_props` | _(optional)_ use an object to define additional FormStatus properties. |
| `disable_autofocus` | _(optional)_ once the date picker gets opened, there is a focus handling to ensure good accessibility. This can be disabled with this property. Defaults to `false`. |
| `correct_invalid_date` | _(optional)_ corrects the input date value to be the same as either `min_date` or `max_date`, when the user types in a date that is either before or after one of these. Defaults to `false`. |
| `globalStatus` | _(optional)_ the [configuration](/uilib/components/global-status/properties/#configuration-object) used for the target [GlobalStatus](/uilib/components/global-status). |
| `skeleton` | _(optional)_ if set to `true`, an overlaying skeleton with animation will be shown. |
| `size` | _(optional)_ the sizes you can choose is `small` (1.5rem), `default` (2rem), `medium` (2.5rem) and `large` (3rem) are supported component sizes. Defaults to `default` / `null`. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export interface DatePickerProps
* To limit a date range to a maximum `end_date`. Defaults to `null`.
*/
max_date?: DatePickerMaxDate;
/**
* Corrects the date input value if the user tries to set a date that is before or after `min_date` or `max_date`.
* Defaults to `false`.
*/
correct_invalid_date?: boolean;
/**
* To define the order of the masked placeholder input fields. Defaults to `dd/mm/yyyy`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,23 @@ export default class DatePickerProvider extends React.PureComponent {
* Because now we do not any more relay on auto "correction",
* but rather return "is_valid_start_date=false"
*/
if (isTrue(props.correct_invalid_date)) {
if (
isTrue(props.correct_invalid_date) ||
((typeof props.min_date !== 'undefined' ||
typeof props.max_date !== 'undefined') &&
props.correct_invalid_date !== false)
) {
if (isDisabled(state.startDate, state.minDate, state.maxDate)) {
state.startDate = state.minDate
}
if (isDisabled(state.endDate, state.minDate, state.maxDate)) {
state.endDate = state.maxDate
// state.endDate is only used by the input if range is set to true.
// this is done to make max_date correction work if the input is not a range and only max_date is defined.
if (!props.range && !props.min_date) {
state.startDate = state.maxDate
} else {
state.endDate = state.maxDate
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,143 @@ describe('DatePicker component', () => {
expect(on_change.mock.calls[1][0].is_valid_start_date).toBe(true)
})

it('has to auto-correct invalid min dates when min_date is given', async () => {
render(<DatePicker date="2024-02-02" min_date="2024-02-02" />)
const day = document.querySelectorAll(
'input.dnb-date-picker__input--day'
)[0] as HTMLInputElement
const month = document.querySelectorAll(
'input.dnb-date-picker__input--month'
)[0] as HTMLInputElement
const year = document.querySelectorAll(
'input.dnb-date-picker__input--year'
)[0] as HTMLInputElement

// by default we have the corrected start day
expect(day).toHaveValue('02')

// try to type invalid day
await userEvent.type(day, '01')
expect(day).toHaveValue('02')

// then type valid day
await userEvent.type(day, '{Backspace>2}03')
expect(day).toHaveValue('03')

// expect default month to be 02
expect(month).toHaveValue('02')

// try to type invalid month
await userEvent.type(month, '01')
expect(month).toHaveValue('02')

// then type valid month
await userEvent.type(month, '{Backspace>2}03')
expect(month).toHaveValue('03')

// expect default year to be 2024
expect(year).toHaveValue('2024')

// try to type invalid year
await userEvent.type(year, '2023')
expect(year).toHaveValue('2024')

// then type valid year
await userEvent.type(year, '{Backspace>4}2025')
expect(year).toHaveValue('2025')
})

it('has to auto-correct invalid max dates when max_date is given', async () => {
render(<DatePicker date="2024-02-02" max_date="2024-02-02" />)
const day = document.querySelectorAll(
'input.dnb-date-picker__input--day'
)[0] as HTMLInputElement
const month = document.querySelectorAll(
'input.dnb-date-picker__input--month'
)[0] as HTMLInputElement
const year = document.querySelectorAll(
'input.dnb-date-picker__input--year'
)[0] as HTMLInputElement

// by default we have the corrected start day
expect(day).toHaveValue('02')

// try to type invalid day
await userEvent.type(day, '03')
expect(day).toHaveValue('02')

// then type valid day
await userEvent.type(day, '{Backspace>2}01')
expect(day).toHaveValue('01')

// expect default month to be 02
expect(month).toHaveValue('02')

// try to type invalid month
await userEvent.type(month, '03')
expect(month).toHaveValue('02')

// then type valid month
await userEvent.type(month, '{Backspace>2}01')
expect(month).toHaveValue('01')

// expect default year to be 2024
expect(year).toHaveValue('2024')

// try to type invalid year
await userEvent.type(year, '2025')
expect(year).toHaveValue('2024')

// then type valid year
await userEvent.type(year, '{Backspace>4}2023')
expect(year).toHaveValue('2023')
})

it('should not auto-correct invalid min/max dates if correct_invalid_date is set to false', async () => {
render(
<DatePicker
date="2024-02-02"
min_date="2024-02-02"
max_date="2024-02-16"
correct_invalid_date={false}
/>
)
const day = document.querySelectorAll(
'input.dnb-date-picker__input--day'
)[0] as HTMLInputElement
const month = document.querySelectorAll(
'input.dnb-date-picker__input--month'
)[0] as HTMLInputElement
const year = document.querySelectorAll(
'input.dnb-date-picker__input--year'
)[0] as HTMLInputElement

// by default we have the corrected start day
expect(day).toHaveValue('02')

await userEvent.type(day, '01')
expect(day).toHaveValue('01')

await userEvent.type(day, '{Backspace>2}18')
expect(day).toHaveValue('18')

expect(month).toHaveValue('02')

await userEvent.type(month, '05')
expect(month).toHaveValue('05')

await userEvent.type(month, '{Backspace>2}01')
expect(month).toHaveValue('01')

expect(year).toHaveValue('2024')

await userEvent.type(year, '2026')
expect(year).toHaveValue('2026')

await userEvent.type(year, '{Backspace>4}2023')
expect(year).toHaveValue('2023')
})

it('has a working min and max date limitation', () => {
const on_type = jest.fn()
const on_change = jest.fn()
Expand Down

0 comments on commit 0912bb7

Please sign in to comment.