Skip to content

Commit

Permalink
fix(calendar): stop extra call to validation when choosing from picker
Browse files Browse the repository at this point in the history
  • Loading branch information
kabaros committed Oct 25, 2024
1 parent cc5b4dd commit f875d6e
Show file tree
Hide file tree
Showing 2 changed files with 329 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { Button } from '@dhis2-ui/button'
import { fireEvent, render, waitFor, within } from '@testing-library/react'
import React from 'react'
import userEvent from '@testing-library/user-event'
import React, { useState } from 'react'
import { Field, Form } from 'react-final-form'
import { CalendarInput } from '../calendar-input.js'

describe('Calendar Input', () => {
beforeEach(() => {
jest.useFakeTimers()
jest.setSystemTime(new Date('2024-10-22T09:05:00.000Z'))
})
afterEach(jest.useRealTimers)

it('allow selection of a date through the calendar widget', async () => {
const onDateSelectMock = jest.fn()
const screen = render(
Expand All @@ -16,7 +25,7 @@ describe('Calendar Input', () => {
const calendar = await screen.findByTestId('calendar')
expect(calendar).toBeInTheDocument()

const todayString = new Date().toISOString().slice(0, -14)
const todayString = '2024-10-22'
const today = within(calendar).getByTestId(todayString)

fireEvent.click(today)
Expand Down Expand Up @@ -51,4 +60,284 @@ describe('Calendar Input', () => {
})
)
})

describe('validation', () => {
it('should validate minimum date', async () => {
const onDateSelectMock = jest.fn()
const screen = render(
<CalendarWithValidation
calendar="gregory"
minDate="2024-01-01"
onDateSelect={onDateSelectMock}
/>
)

const dateInputString = '2023-10-12'
const dateInput = within(
screen.getByTestId('dhis2-uicore-input')
).getByRole('textbox')

userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
await screen.findByText(
'Date 2023-10-12 is less than the minimum allowed date 2024-01-01.'
)
)
expect(onDateSelectMock).toHaveBeenCalledTimes(1)
})
it('should validate maximum date', async () => {
const { getByTestId, findByText } = render(
<CalendarWithValidation
calendar="gregory"
maxDate="2024-01-01"
/>
)

const dateInputString = '2024-10-12'
const dateInput = within(
getByTestId('dhis2-uicore-input')
).getByRole('textbox')

userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
await findByText(
'Date 2024-10-12 is greater than the maximum allowed date 2024-01-01.'
)
)
})
it('should validate date in ethiopic calendar', async () => {
const onDateSelectMock = jest.fn()
const { getByTestId, findByText, queryByText } = render(
<CalendarWithValidation
calendar="ethiopian"
minDate="2018-13-04"
onDateSelect={onDateSelectMock}
/>
)

let dateInputString = '2018-13-02'
const dateInput = within(
getByTestId('dhis2-uicore-input')
).getByRole('textbox')

userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
await findByText(
'Date 2018-13-02 is less than the minimum allowed date 2018-13-04.'
)
)

dateInputString = '2018-13-05'
userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
queryByText(
'Date 2018-13-04 is less than the minimum allowed date 2018-13-05.'
)
).not.toBeInTheDocument()

dateInputString = '2018-13-07'
userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
await findByText('Invalid date in specified calendar')
).toBeInTheDocument()
})
it('should validate date in nepali calendar', async () => {
const onDateSelectMock = jest.fn()
const { getByTestId, findByText, queryByText } = render(
<CalendarWithValidation
calendar="nepali"
maxDate="2080-05-30"
onDateSelect={onDateSelectMock}
/>
)

let dateInputString = '2080-06-01'
const dateInput = within(
getByTestId('dhis2-uicore-input')
).getByRole('textbox')

userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
await findByText(
'Date 2080-06-01 is greater than the maximum allowed date 2080-05-30.'
)
)

dateInputString = '2080-04-32'
userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
queryByText(/greater than the maximum allowed date/)
).not.toBeInTheDocument()

dateInputString = '2080-01-32'
userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
await findByText('Invalid date in specified calendar')
).toBeInTheDocument()
})
it('should validate from date picker', async () => {
const onDateSelectMock = jest.fn()
const { queryByText, getByText, getByTestId } = render(
<CalendarWithValidation
calendar="gregory"
minDate="2024-02-16"
onDateSelect={onDateSelectMock}
/>
)

const dateInput = within(
getByTestId('dhis2-uicore-input')
).getByRole('textbox')

await userEvent.click(dateInput)
await userEvent.click(getByText('17'))
expect(queryByText('17')).not.toBeInTheDocument()

// Bug where callback used to be called first with undefined
expect(onDateSelectMock).toHaveBeenCalledTimes(1)
expect(onDateSelectMock).toHaveBeenCalledWith({
calendarDateString: '2024-10-17',
validation: { error: false, valid: true, warning: false },
})
})

it('should validate with Clear', async () => {
const onDateSelectMock = jest.fn()
const { queryByText, getByText, getByTestId } = render(
<CalendarWithValidation
calendar="gregory"
minDate="2024-02-16"
onDateSelect={onDateSelectMock}
clearable
/>
)

const dateInputString = '2023-10-12'
const dateInput = within(
getByTestId('dhis2-uicore-input')
).getByRole('textbox')

userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
getByTestId('dhis2-uiwidgets-calendar-inputfield-validation')
).toBeInTheDocument()

await userEvent.click(getByText('Clear'))
expect(queryByText('17')).not.toBeInTheDocument()

expect(onDateSelectMock).toHaveBeenLastCalledWith({
calendarDateString: null,
validation: { valid: true },
})
})

it('should validate when Clearing manually (i.e. deleting text not using clear button)', async () => {
const onDateSelectMock = jest.fn()
const { getByTestId } = render(
<CalendarWithValidation
calendar="gregory"
minDate="2024-02-16"
onDateSelect={onDateSelectMock}
clearable
/>
)

const dateInputString = '2023-10-12'
const dateInput = within(
getByTestId('dhis2-uicore-input')
).getByRole('textbox')

userEvent.clear(dateInput)
userEvent.type(dateInput, dateInputString)
userEvent.tab()

expect(
getByTestId('dhis2-uiwidgets-calendar-inputfield-validation')
).toBeInTheDocument()

userEvent.clear(dateInput)
userEvent.tab()

expect(onDateSelectMock).toHaveBeenCalledWith({
calendarDateString: null,
validation: { valid: true },
})
})
})
})

const CalendarWithValidation = (propsFromParent) => {
const [date, setDate] = useState()

const [validation, setValidation] = useState({})

const errored = () => {
if (validation?.error) {
return { calendar: validation.validationText }
}
}

return (
<Form onSubmit={() => {}} validate={errored}>
{({ handleSubmit, invalid }) => {
return (
<form>
<Field name="calendar">
{(props) => (
<CalendarInput
{...props}
date={date}
label="Enter a date"
editable
calendar="gregory"
{...validation}
{...propsFromParent}
onDateSelect={(date) => {
setDate(date?.calendarDateString)
setValidation(date?.validation)
propsFromParent.onDateSelect?.(date)
}}
/>
)}
</Field>

<Button
type="submit"
disabled={invalid}
onClick={handleSubmit}
>
Submit
</Button>
</form>
)
}}
</Form>
)
}
Loading

0 comments on commit f875d6e

Please sign in to comment.