From 8588b3b0891ba938b6ed66b06b87e9b41c5f8373 Mon Sep 17 00:00:00 2001 From: Dimitri Mitropoulos Date: Thu, 5 Mar 2020 20:49:39 -0500 Subject: [PATCH] ensure all tests pass --- ...test.js.snap => date_picker.test.tsx.snap} | 1 - ...s.snap => date_picker_range.test.tsx.snap} | 0 .../date_picker/date_picker.test.tsx | 8 +++--- src/components/date_picker/date_picker.tsx | 15 +++++------ .../date_picker/react-datepicker.d.ts | 1 + ...s.snap => super_date_picker.test.tsx.snap} | 1 - ...snap => super_update_button.test.tsx.snap} | 0 .../super_date_picker/async_interval.test.ts | 8 +++--- .../date_popover/absolute_tab.tsx | 11 +++++--- .../date_popover/date_popover_content.tsx | 14 +++++++--- .../date_popover/relative_tab.tsx | 8 ++++-- ...est.js.snap => quick_select.test.tsx.snap} | 8 ++---- ...nap => quick_select_popover.test.tsx.snap} | 8 +++++- .../quick_select_popover/quick_select.tsx | 20 +++++++++----- .../quick_select_popover/refresh_interval.tsx | 2 +- .../super_date_picker/relative_options.ts | 4 +-- .../super_date_picker.test.tsx | 26 +++++++++++-------- src/components/date_picker/types.ts | 4 ++- 18 files changed, 85 insertions(+), 54 deletions(-) rename src/components/date_picker/__snapshots__/{date_picker.test.js.snap => date_picker.test.tsx.snap} (99%) rename src/components/date_picker/__snapshots__/{date_picker_range.test.js.snap => date_picker_range.test.tsx.snap} (100%) rename src/components/date_picker/super_date_picker/__snapshots__/{super_date_picker.test.js.snap => super_date_picker.test.tsx.snap} (98%) rename src/components/date_picker/super_date_picker/__snapshots__/{super_update_button.test.js.snap => super_update_button.test.tsx.snap} (100%) rename src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/{quick_select.test.js.snap => quick_select.test.tsx.snap} (98%) rename src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/{quick_select_popover.test.js.snap => quick_select_popover.test.tsx.snap} (95%) diff --git a/src/components/date_picker/__snapshots__/date_picker.test.js.snap b/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap similarity index 99% rename from src/components/date_picker/__snapshots__/date_picker.test.js.snap rename to src/components/date_picker/__snapshots__/date_picker.test.tsx.snap index 0d50659bbed0..473823bf096c 100644 --- a/src/components/date_picker/__snapshots__/date_picker.test.js.snap +++ b/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap @@ -6,7 +6,6 @@ exports[`EuiDatePicker is rendered 1`] = ` className="euiDatePicker euiDatePicker--shadow" > { test('is rendered', () => { - const component = shallow(); + const component = shallow( + + ); expect(component).toMatchSnapshot(); // snapshot of wrapping dom expect(component.find('ContextConsumer').shallow()).toMatchSnapshot(); // snapshot of DatePicker usage }); describe('localization', () => { - const selectedDate = new Moment('2019-07-01T00:00:00-0700').locale('fr'); + const selectedDate = moment('2019-07-01T00:00:00-0700').locale('fr'); test('accepts the locale prop', () => { const component = mount( diff --git a/src/components/date_picker/date_picker.tsx b/src/components/date_picker/date_picker.tsx index 92d4f831eb03..66940a1b21e3 100644 --- a/src/components/date_picker/date_picker.tsx +++ b/src/components/date_picker/date_picker.tsx @@ -1,19 +1,19 @@ -import React, { Component, MouseEventHandler, Ref } from 'react'; +import React, { Component, MouseEventHandler, RefCallback } from 'react'; import classNames from 'classnames'; import { Moment } from 'moment'; // eslint-disable-line import/named -// @ts-ignore the type is provided by -import { ReactDatePicker as _ReactDatePicker } from '../../../packages'; import { EuiFormControlLayout, EuiValidatableControl } from '../form'; +import { EuiFormControlLayoutIconsProps } from '../form/form_control_layout/form_control_layout_icons'; import { EuiErrorBoundary } from '../error_boundary'; import { EuiI18nConsumer } from '../context'; import { CommonProps } from '../common'; +// @ts-ignore the type is provided by react-datepicker.d.ts +import { ReactDatePicker as _ReactDatePicker } from '../../../packages'; import ReactDatePicker, { ReactDatePickerProps } from './react-datepicker'; // eslint-disable-line import/no-unresolved -import { EuiFormControlLayoutIconsProps } from '../form/form_control_layout/form_control_layout_icons'; export const euiDatePickerDefaultDateFormat = 'MM/DD/YYYY'; export const euiDatePickerDefaultTimeFormat = 'hh:mm A'; @@ -34,7 +34,7 @@ interface EuiExtendedDatePickerProps extends ReactDatePickerProps { /** * Applies ref to the input */ - inputRef: Ref; + inputRef: RefCallback>; /** * Provides styling to the input when invalid @@ -75,7 +75,7 @@ interface EuiExtendedDatePickerProps extends ReactDatePickerProps { export type EuiDatePickerProps = CommonProps & EuiExtendedDatePickerProps; export class EuiDatePicker extends Component { - defaultProps = { + static defaultProps = { adjustDateOnChange: true, dateFormat: euiDatePickerDefaultDateFormat, fullWidth: false, @@ -228,7 +228,6 @@ export class EuiDatePicker extends Component { openToDate={openToDate} placeholderText={placeholder} popperClassName={popperClassName} - // @ts-ignore this is due to `react-datepicker` (i.e. `ReactDatePicker`, this component) being a `React.ClassicComponentClass` rather than a `React.Component`. ref={inputRef} selected={selected} shouldCloseOnSelect={shouldCloseOnSelect} @@ -239,7 +238,7 @@ export class EuiDatePicker extends Component { timeFormat={timeFormat} utcOffset={utcOffset} yearDropdownItemNumber={7} - accessibleMode={true} + accessibleMode {...rest} /> ); diff --git a/src/components/date_picker/react-datepicker.d.ts b/src/components/date_picker/react-datepicker.d.ts index 27db4eff6553..2b37e531cdd0 100644 --- a/src/components/date_picker/react-datepicker.d.ts +++ b/src/components/date_picker/react-datepicker.d.ts @@ -19,6 +19,7 @@ export interface ReactDatePickerProps { * Whether changes to Year and Month (via dropdowns) should trigger `onChange` */ adjustDateOnChange?: boolean; + accessibleMode?: boolean; allowSameDay?: boolean; autoComplete?: string; autoFocus?: boolean; diff --git a/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap b/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap similarity index 98% rename from src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap rename to src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap index 391b56377898..99ba70ad3396 100644 --- a/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap +++ b/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap @@ -12,7 +12,6 @@ exports[`EuiSuperDatePicker is rendered 1`] = ` isDisabled={false} prepend={ { ) { const iterations = times(Math.floor(milliseconds / 100)); const remainder = milliseconds % 100; - // eslint-disable-next-line @typescript-eslint/no-unused-vars + /* eslint-disable @typescript-eslint/no-unused-vars */ + // @ts-ignore for (const item of iterations) { + /* eslint-enable @typescript-eslint/no-unused-vars */ await instance.__pendingFn; jest.advanceTimersByTime(100); await instance.__pendingFn; @@ -32,7 +34,7 @@ describe('AsyncInterval', () => { describe('when creating a 1000ms interval', async () => { let instance: AsyncInterval; - let spy; + let spy: jest.Mock; beforeEach(() => { spy = jest.fn(); instance = new AsyncInterval(spy, 1000); @@ -69,7 +71,7 @@ describe('AsyncInterval', () => { describe('when creating a 1000ms interval that calls a fn that takes 2000ms to complete', async () => { let instance: AsyncInterval; - let spy; + let spy: jest.Mock; beforeEach(() => { spy = jest.fn(async () => await sleep(2000)); instance = new AsyncInterval(spy, 1000); diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx index e7d3b9530d65..5bcf4f002fbd 100644 --- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx +++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx @@ -54,11 +54,15 @@ export class EuiAbsoluteTab extends Component< } handleChange: ReactDatePickerProps['onChange'] = (date, event) => { + const { onChange } = this.props; if (date === null) { return; } + if (!onChange) { + return; + } const dateMoment = moment(date); - this.props.onChange(date, event); + onChange(date, event); this.setState({ valueAsMoment: dateMoment, textInputValue: dateMoment.format(this.props.dateFormat), @@ -67,14 +71,15 @@ export class EuiAbsoluteTab extends Component< }; handleTextChange: ChangeEventHandler = event => { + const { onChange } = this.props; const valueAsMoment = moment( event.target.value, this.props.dateFormat, true ); const dateIsValid = valueAsMoment.isValid(); - if (dateIsValid) { - this.props.onChange(valueAsMoment, event); + if (dateIsValid && onChange) { + onChange(valueAsMoment, event); } this.setState({ textInputValue: event.target.value as string, diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx index 9c8640fd03de..b56894da0bd3 100644 --- a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx +++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx @@ -14,7 +14,7 @@ import { toRelativeString, } from '../date_modes'; import { LocaleSpecifier } from 'moment'; // eslint-disable-line import/named -import { ReactDatePickerProps } from '../../react-datepicker'; +import { ReactDatePickerProps } from '../../react-datepicker'; // eslint-disable-line import/no-unresolved export interface EuiDatePopoverContentProps { value: string; @@ -38,6 +38,10 @@ export const EuiDatePopoverContent: FunctionComponent< position, }) => { const onTabClick: EuiTabbedContentProps['onTabClick'] = selectedTab => { + if (!onChange) { + return; + } + switch (selectedTab.id) { case DATE_MODES.ABSOLUTE: onChange(toAbsoluteString(value, roundUp)); @@ -99,7 +103,11 @@ export const EuiDatePopoverContent: FunctionComponent<

onChange('now')} + onClick={() => { + if (onChange) { + onChange('now'); + } + }} fullWidth size="s" fill> @@ -119,10 +127,8 @@ export const EuiDatePopoverContent: FunctionComponent< tabs={renderTabs()} autoFocus="selected" initialSelectedTab={{ - // NOTE_TO_SELF(dimitri): behavior change? content: , id: getDateMode(value), - // NOTE_TO_SELF(dimitri): behavior change? name: '', }} onTabClick={onTabClick} diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx b/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx index 7308dba3cbb3..319703c07a46 100644 --- a/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx +++ b/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx @@ -83,16 +83,20 @@ export class EuiRelativeTab extends Component< handleChange = () => { const { count, round, roundUnit, unit } = this.state; + const { onChange } = this.props; if (count === null || count < 0) { return; } + if (!onChange) { + return; + } const date = toRelativeStringFromParts({ count, round, roundUnit, unit, }); - this.props.onChange(date); + onChange(date); }; render() { @@ -184,7 +188,7 @@ export class EuiRelativeTab extends Component< } /> - +

- +

- +

{ return { value: key, text: `${timeUnits[key]}s` }; }); +const defaultQuickSelect: QuickSelect = { + timeTense: LAST, + timeValue: 15, + timeUnits: 'm', +}; + type EuiQuickSelectState = QuickSelect; export interface EuiQuickSelectProps { applyTime: ApplyTime; start: string; end: string; - prevQuickSelect?: EuiQuickSelectState; + prevQuickSelect: EuiQuickSelectState; } export class EuiQuickSelect extends Component< EuiQuickSelectProps, EuiQuickSelectState > { - defaultProps = { - prevQuickSelect: {}, + static defaultProps = { + prevQuickSelect: defaultQuickSelect, }; state: EuiQuickSelectState = { timeTense: this.props.prevQuickSelect && this.props.prevQuickSelect.timeTense ? this.props.prevQuickSelect.timeTense - : LAST, + : defaultQuickSelect.timeTense, timeValue: this.props.prevQuickSelect && this.props.prevQuickSelect.timeValue ? this.props.prevQuickSelect.timeValue - : 15, + : defaultQuickSelect.timeValue, timeUnits: this.props.prevQuickSelect && this.props.prevQuickSelect.timeUnits ? this.props.prevQuickSelect.timeUnits - : 'm', + : defaultQuickSelect.timeUnits, }; generateId = htmlIdGenerator(); @@ -267,7 +273,7 @@ export class EuiQuickSelect extends Component< - +

- +

value) - .filter(value => value.includes('+')) as TimeUnitId[]; + .filter(value => !value.includes('+')) as TimeUnitId[]; export const isTimeUnitId = (value: string): value is TimeUnitId => timeUnitIds.includes(value as TimeUnitId); const timeUnitFromNowIds = relativeOptions .map(({ value }) => value) - .filter(value => !value.includes('+')) as TimeUnitFromNowId[]; + .filter(value => value.includes('+')) as TimeUnitFromNowId[]; export const isTimeUnitFromNowId = ( value: string diff --git a/src/components/date_picker/super_date_picker/super_date_picker.test.tsx b/src/components/date_picker/super_date_picker/super_date_picker.test.tsx index b21e3857a2d3..949e7309c31a 100644 --- a/src/components/date_picker/super_date_picker/super_date_picker.test.tsx +++ b/src/components/date_picker/super_date_picker/super_date_picker.test.tsx @@ -14,7 +14,9 @@ describe('EuiSuperDatePicker', () => { test('refresh is disabled by default', () => { // By default we expect `asyncInterval` to be not set. - const componentPaused = mount(); + const componentPaused = mount( + + ); const instancePaused = componentPaused.instance(); expect(instancePaused.asyncInterval).toBe(undefined); expect(componentPaused.prop('isPaused')).toBe(true); @@ -24,7 +26,7 @@ describe('EuiSuperDatePicker', () => { // If refresh is enabled via `isPaused/onRefresh` we expect // `asyncInterval` to be present and `asyncInterval.isStopped` to be `false`. const onRefresh = jest.fn(); - const componentRefresh = mount( + const componentRefresh = mount( { ); const instanceRefresh = componentRefresh.instance(); expect(typeof instanceRefresh.asyncInterval).toBe('object'); - expect(instanceRefresh.asyncInterval.isStopped).toBe(false); + expect(instanceRefresh.asyncInterval!.isStopped).toBe(false); expect(componentRefresh.prop('isPaused')).toBe(false); // If we update the prop `isPaused` we expect the interval to be stopped too. componentRefresh.setProps({ isPaused: true }); const instanceUpdatedPaused = componentRefresh.instance(); expect(typeof instanceUpdatedPaused.asyncInterval).toBe('object'); - expect(instanceUpdatedPaused.asyncInterval.isStopped).toBe(true); + expect(instanceUpdatedPaused.asyncInterval!.isStopped).toBe(true); expect(componentRefresh.prop('isPaused')).toBe(true); // Let's start refresh again for a final sanity check. componentRefresh.setProps({ isPaused: false }); const instanceUpdatedRefresh = componentRefresh.instance(); expect(typeof instanceUpdatedRefresh.asyncInterval).toBe('object'); - expect(instanceUpdatedRefresh.asyncInterval.isStopped).toBe(false); + expect(instanceUpdatedRefresh.asyncInterval!.isStopped).toBe(false); expect(componentRefresh.prop('isPaused')).toBe(false); }); @@ -56,7 +58,7 @@ describe('EuiSuperDatePicker', () => { const onRefresh = jest.fn(); - const componentRefresh = mount( + const componentRefresh = mount( { ); const instanceRefresh = componentRefresh.instance(); + expect(typeof instanceRefresh.asyncInterval).toBe('object'); jest.advanceTimersByTime(10); - await instanceRefresh.asyncInterval.__pendingFn; + await instanceRefresh.asyncInterval!.__pendingFn; jest.advanceTimersByTime(10); - await instanceRefresh.asyncInterval.__pendingFn; + await instanceRefresh.asyncInterval!.__pendingFn; expect(onRefresh).toBeCalledTimes(2); @@ -82,7 +85,7 @@ describe('EuiSuperDatePicker', () => { const onRefresh = jest.fn(); - const componentRefresh = mount( + const componentRefresh = mount( { const instanceRefresh = componentRefresh.instance(); jest.advanceTimersByTime(10); - await instanceRefresh.asyncInterval.__pendingFn; + expect(typeof instanceRefresh.asyncInterval).toBe('object'); + await instanceRefresh.asyncInterval!.__pendingFn; componentRefresh.setProps({ isPaused: true, refreshInterval: 0 }); jest.advanceTimersByTime(10); - await instanceRefresh.asyncInterval.__pendingFn; + await instanceRefresh.asyncInterval!.__pendingFn; expect(onRefresh).toBeCalledTimes(1); diff --git a/src/components/date_picker/types.ts b/src/components/date_picker/types.ts index 816c32fece12..627f97d98d49 100644 --- a/src/components/date_picker/types.ts +++ b/src/components/date_picker/types.ts @@ -1,3 +1,5 @@ +import { ReactElement } from 'react'; + export interface DurationRange { end: ShortDate; label?: string; @@ -66,5 +68,5 @@ export type ApplyTime = (args: ApplyTimeArgs) => void; export interface QuickSelectPanel { title: string; - content: React.ReactNode; + content: ReactElement; }