Skip to content

Commit

Permalink
[EuiDatePicker] Handle invalid selected moment formats (#7784)
Browse files Browse the repository at this point in the history
  • Loading branch information
cee-chen authored May 23, 2024
1 parent 50247a5 commit 7140a4e
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 5 deletions.
3 changes: 3 additions & 0 deletions packages/eui/changelogs/upcoming/7784.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**Bug fixes**

- Fixed `EuiDatePicker` to more gracefully handle incorrectly formatted `selected` Moment dates, instead of simply crashing
27 changes: 25 additions & 2 deletions packages/eui/src/components/date_picker/date_picker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
*/

import React from 'react';
import { render } from '../../test/rtl';
import { requiredProps } from '../../test';
import moment from 'moment';
import { fireEvent } from '@testing-library/react';
import { render, waitForEuiPopoverOpen } from '../../test/rtl';
import { requiredProps } from '../../test';

import { EuiDatePicker } from './date_picker';
import { EuiContext } from '../context';
Expand All @@ -21,6 +22,28 @@ describe('EuiDatePicker', () => {
expect(container.firstChild).toMatchSnapshot();
});

it('handles invalid `selected` dates', async () => {
// Silence the console warning from the invalid moment date
jest.spyOn(console, 'warn').mockImplementation(() => {});
const { container } = render(
<EuiDatePicker selected={moment('invalid')} />
);
const datepickerInput = container.querySelector('input.euiDatePicker');

expect(datepickerInput).toHaveValue('Invalid date');
expect(datepickerInput).toBeInvalid();

// The calendar date picker should load in a popover, but no date should be selected
fireEvent.focus(datepickerInput!);
await waitForEuiPopoverOpen();
const calendar = document.querySelector('.react-datepicker__month');
expect(calendar).toBeInTheDocument();
const selected = document.querySelector('.react-datepicker__day--selected');
expect(selected).not.toBeInTheDocument();

jest.restoreAllMocks();
});

test('compressed', () => {
const { container } = render(<EuiDatePicker compressed />);
// TODO: Should probably be a visual snapshot test
Expand Down
6 changes: 5 additions & 1 deletion packages/eui/src/components/date_picker/date_picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export const EuiDatePicker: FunctionComponent<EuiDatePickerProps> = ({
injectTimes,
inline,
inputRef,
isInvalid,
isInvalid: _isInvalid,
isLoading,
locale,
maxDate,
Expand Down Expand Up @@ -193,6 +193,10 @@ export const EuiDatePicker: FunctionComponent<EuiDatePickerProps> = ({
'euiDatePicker--shadow': inline && shadow,
});

// Check for whether the passed `selected` moment date is valid
const isInvalid =
_isInvalid || (selected?.isValid() === false ? true : undefined);

const numIconsClass = controlOnly
? false
: getFormControlClassNameForIconCount({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ function hasPreSelectionChanged(date1, date2) {

function hasSelectionChanged(date1, date2) {
if (date1 && date2) {
if (date1._isValid === false && date2._isValid === false) {
return false;
}
return !equals(date1, date2);
}

Expand Down Expand Up @@ -288,7 +291,7 @@ export default class DatePicker extends React.Component {
return {
open: this.props.startOpen || false,
preventFocus: false,
preSelection: this.props.selected
preSelection: this.props.selected?._isValid
? newDate(this.props.selected)
: boundedPreSelection,
// transforming highlighted days (perhaps nested array)
Expand Down Expand Up @@ -693,7 +696,7 @@ export default class DatePicker extends React.Component {
useWeekdaysShort={this.props.useWeekdaysShort}
formatWeekDay={this.props.formatWeekDay}
dropdownMode={this.props.dropdownMode}
selected={this.props.selected}
selected={this.props.selected?._isValid ? this.props.selected : undefined}
preSelection={this.state.preSelection}
onSelect={this.handleSelect}
onWeekSelect={this.props.onWeekSelect}
Expand Down

0 comments on commit 7140a4e

Please sign in to comment.