Skip to content

Commit c1fdd25

Browse files
authored
test(react): increase coverage for DatePicker (#21833)
1 parent c51ee16 commit c1fdd25

2 files changed

Lines changed: 172 additions & 19 deletions

File tree

packages/react/src/components/DatePicker/DatePicker-test.js

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,44 @@ describe('DatePicker', () => {
146146
expect(ref).toHaveBeenCalledWith(container.firstChild);
147147
});
148148

149+
it('should update the flatpickr instance when `disable`, `enable`, and `inline` props change', () => {
150+
const ref = createRef();
151+
const disable = ['01/20/2025'];
152+
const enable = ['01/21/2025'];
153+
const { rerender } = render(
154+
<DatePicker ref={ref} datePickerType="single">
155+
<DatePickerInput
156+
id="date-picker-input-id-start"
157+
placeholder="mm/dd/yyyy"
158+
labelText="Date Picker label"
159+
/>
160+
</DatePicker>
161+
);
162+
163+
const setSpy = jest.spyOn(ref.current.calendar, 'set');
164+
165+
setSpy.mockClear();
166+
167+
rerender(
168+
<DatePicker
169+
ref={ref}
170+
datePickerType="single"
171+
disable={disable}
172+
enable={enable}
173+
inline>
174+
<DatePickerInput
175+
id="date-picker-input-id-start"
176+
placeholder="mm/dd/yyyy"
177+
labelText="Date Picker label"
178+
/>
179+
</DatePicker>
180+
);
181+
182+
expect(setSpy).toHaveBeenCalledWith('disable', disable);
183+
expect(setSpy).toHaveBeenCalledWith('enable', enable);
184+
expect(setSpy).toHaveBeenCalledWith('inline', true);
185+
});
186+
149187
it('should respect decorator prop', () => {
150188
render(
151189
<DatePickerInput
@@ -492,6 +530,30 @@ describe('Simple date picker', () => {
492530
expect(screen.queryByRole('application')).not.toBeInTheDocument();
493531
});
494532

533+
it('should update the input value when a controlled simple date value changes', () => {
534+
const { rerender } = render(
535+
<DatePicker datePickerType="simple" value="01/14/2025">
536+
<DatePickerInput
537+
id="date-picker-input-id-start"
538+
labelText="Start date"
539+
/>
540+
</DatePicker>
541+
);
542+
543+
expect(screen.getByLabelText('Start date')).toHaveValue('01/14/2025');
544+
545+
rerender(
546+
<DatePicker datePickerType="simple" value="02/14/2025">
547+
<DatePickerInput
548+
id="date-picker-input-id-start"
549+
labelText="Start date"
550+
/>
551+
</DatePicker>
552+
);
553+
554+
expect(screen.getByLabelText('Start date')).toHaveValue('02/14/2025');
555+
});
556+
495557
it('should remove the calendar if changed from another type to simple', () => {
496558
const { rerender } = render(
497559
<DatePicker datePickerType="single">
@@ -569,6 +631,12 @@ describe('Simple date picker', () => {
569631
});
570632

571633
describe('Single date picker', () => {
634+
it('should not initialize a calendar without an input', () => {
635+
render(<DatePicker datePickerType="single" />);
636+
637+
expect(screen.queryByRole('application')).not.toBeInTheDocument();
638+
});
639+
572640
it('should initialize a calendar', () => {
573641
render(
574642
<DatePicker
@@ -805,6 +873,28 @@ describe('Single date picker', () => {
805873
expect(nextFocusTarget).toHaveFocus();
806874
expect(calendar).not.toHaveClass('open');
807875
});
876+
877+
it('should remove the calendar keydown listener on unmount', () => {
878+
const ref = createRef();
879+
const { unmount } = render(
880+
<DatePicker ref={ref} datePickerType="single">
881+
<DatePickerInput id="input-id" labelText="Date input" />
882+
</DatePicker>
883+
);
884+
885+
const removeEventListenerSpy = jest.spyOn(
886+
ref.current.calendar.calendarContainer,
887+
'removeEventListener'
888+
);
889+
890+
unmount();
891+
892+
expect(removeEventListenerSpy).toHaveBeenCalledWith(
893+
'keydown',
894+
expect.any(Function),
895+
undefined
896+
);
897+
});
808898
});
809899

810900
describe('Range date picker', () => {
@@ -1466,6 +1556,23 @@ describe('Date picker with locale', () => {
14661556
expect(screen.getByText('Enero')).toBeInTheDocument();
14671557
});
14681558

1559+
it('should support locale objects with a `locale` key', () => {
1560+
render(
1561+
<DatePicker
1562+
onChange={() => {}}
1563+
datePickerType="single"
1564+
locale={{ locale: 'es' }}
1565+
value="01/01/2022">
1566+
<DatePickerInput
1567+
id="date-picker-input-id"
1568+
placeholder="mm/dd/yyyy"
1569+
labelText="Date picker label"
1570+
/>
1571+
</DatePicker>
1572+
);
1573+
expect(screen.getByText('Enero')).toBeInTheDocument();
1574+
});
1575+
14691576
it('should use default locale if one is not passed as a prop', () => {
14701577
render(
14711578
<DatePicker
@@ -1563,6 +1670,62 @@ describe('Date picker with locale', () => {
15631670
});
15641671

15651672
describe('Date picker with minDate and maxDate', () => {
1673+
it('should respect `disable` prop', async () => {
1674+
render(
1675+
<DatePicker
1676+
onChange={() => {}}
1677+
datePickerType="single"
1678+
disable={['01/02/2018']}
1679+
value="01/01/2018">
1680+
<DatePickerInput
1681+
id="date-picker-input-id"
1682+
placeholder="mm/dd/yyyy"
1683+
labelText="Date picker label"
1684+
data-testid="input"
1685+
/>
1686+
</DatePicker>
1687+
);
1688+
1689+
await userEvent.click(screen.getByTestId('input'));
1690+
1691+
const disabledDate = document.querySelector(
1692+
'[aria-label="January 2, 2018"]'
1693+
);
1694+
1695+
expect(disabledDate).toHaveClass('flatpickr-disabled');
1696+
});
1697+
1698+
it('should respect `enable` prop', async () => {
1699+
const ref = createRef();
1700+
const enable = ['01/02/2018'];
1701+
1702+
render(
1703+
<DatePicker
1704+
ref={ref}
1705+
onChange={() => {}}
1706+
datePickerType="single"
1707+
enable={enable}
1708+
value="01/01/2018">
1709+
<DatePickerInput
1710+
id="date-picker-input-id"
1711+
placeholder="mm/dd/yyyy"
1712+
labelText="Date picker label"
1713+
data-testid="input"
1714+
/>
1715+
</DatePicker>
1716+
);
1717+
1718+
await userEvent.click(screen.getByTestId('input'));
1719+
1720+
expect(ref.current.calendar.config.enable).toHaveLength(1);
1721+
expect(
1722+
ref.current.calendar.formatDate(
1723+
ref.current.calendar.config.enable[0],
1724+
'm/d/Y'
1725+
)
1726+
).toBe('01/02/2018');
1727+
});
1728+
15661729
it('should respect minDate', async () => {
15671730
render(
15681731
<DatePicker

packages/react/src/components/DatePicker/DatePicker.tsx

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((props, ref) => {
482482
warn: mergedWarn,
483483
});
484484
}
485+
// TODO: The docs say this component expects `DatePickerInput` children.
486+
// Can these non-`DatePickerInput` fallbacks be deleted?
487+
// https://github.com/carbon-design-system/carbon/blob/b4297c52b50edf2fbc6c439c38edc8ee860c77fc/packages/react/src/components/DatePicker/DatePicker.mdx?plain=1#L49-L50
485488
if (index === 0) {
486489
return React.cloneElement(child, {
487490
ref: startInputField,
@@ -746,10 +749,6 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((props, ref) => {
746749
return;
747750
}
748751

749-
if (!calendar.selectedDates) {
750-
return;
751-
}
752-
753752
if (calendar.selectedDates.length === 0) {
754753
return;
755754
}
@@ -921,21 +920,12 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((props, ref) => {
921920

922921
useEffect(() => {
923922
if (calendarRef.current?.set) {
924-
if (value !== undefined) {
925-
// To make up for calendarRef.current.setDate not making provision for an empty string or array
926-
if (
927-
value === '' ||
928-
value === null ||
929-
(Array.isArray(value) &&
930-
(value.length === 0 || value.every(isEmptyDateValue)))
931-
) {
932-
// only clear if there are selected dates to avoid unnecessary operations
933-
if (calendarRef.current.selectedDates.length > 0) {
934-
calendarRef.current.clear();
935-
}
936-
} else {
937-
calendarRef.current.setDate(value);
938-
}
923+
if (
924+
!isEmptyDateValue(value) &&
925+
(!Array.isArray(value) ||
926+
(value.length > 0 && !value.every(isEmptyDateValue)))
927+
) {
928+
calendarRef.current.setDate(value);
939929
}
940930
updateClassNames(calendarRef.current, prefix);
941931
//for simple date picker w/o calendar; initial mount may not have value

0 commit comments

Comments
 (0)