TimePicker: will display the correct dates when selecting range in calendar with tz. (#35829)

* fixing calendar issue.

* reset yarn.lock.

* added boilerplate for test.

* added tests to verify bugfix.
pull/35891/head
Marcus Andersson 4 years ago committed by GitHub
parent 0fea1cf970
commit b1286ab8d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      packages/grafana-e2e-selectors/src/selectors/components.ts
  2. 9
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx
  3. 99
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeForm.test.tsx
  4. 4
      packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeForm.tsx

@ -4,6 +4,7 @@ export const Components = {
fromField: 'TimePicker from field',
toField: 'TimePicker to field',
applyTimeRange: 'TimePicker submit button',
calendar: 'TimePicker calendar',
},
DataSource: {
TestData: {

@ -8,6 +8,7 @@ import { Button } from '../../Button';
import { Icon } from '../../Icon/Icon';
import { Portal } from '../../Portal/Portal';
import { ClickOutsideWrapper } from '../../ClickOutsideWrapper/ClickOutsideWrapper';
import { selectors } from '@grafana/e2e-selectors';
export const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed = false) => {
return {
@ -208,7 +209,11 @@ export const TimePickerCalendar = memo<Props>((props) => {
if (isFullscreen) {
return (
<ClickOutsideWrapper onClick={props.onClose}>
<div className={styles.container} onClick={stopPropagation}>
<div
className={styles.container}
onClick={stopPropagation}
aria-label={selectors.components.TimePicker.calendar}
>
<Body {...props} />
</div>
</ClickOutsideWrapper>
@ -218,7 +223,7 @@ export const TimePickerCalendar = memo<Props>((props) => {
return (
<Portal>
<div className={styles.modal} onClick={stopPropagation}>
<div className={styles.content}>
<div className={styles.content} aria-label={selectors.components.TimePicker.calendar}>
<Header {...props} />
<Body {...props} />
<Footer {...props} />

@ -0,0 +1,99 @@
import React from 'react';
import { fireEvent, render, RenderResult } from '@testing-library/react';
import { dateTimeParse, TimeRange } from '@grafana/data';
import { TimeRangeForm } from './TimeRangeForm';
import { selectors } from '@grafana/e2e-selectors';
type TimeRangeFormRenderResult = RenderResult & {
getCalendarDayByLabelText(label: string): HTMLButtonElement;
};
const defaultTimeRange: TimeRange = {
from: dateTimeParse('2021-06-17 00:00:00', { timeZone: 'utc' }),
to: dateTimeParse('2021-06-19 23:59:00', { timeZone: 'utc' }),
raw: {
from: '2021-06-17 00:00:00',
to: '2021-06-19 23:59:00',
},
};
function setup(initial: TimeRange = defaultTimeRange, timeZone = 'utc'): TimeRangeFormRenderResult {
const result = render(<TimeRangeForm isFullscreen={true} value={initial} onApply={() => {}} timeZone={timeZone} />);
return {
...result,
getCalendarDayByLabelText: (label: string) => {
const item = result.getByLabelText(label);
return item?.parentElement as HTMLButtonElement;
},
};
}
describe('TimeRangeForm', () => {
it('should render form correcty', () => {
const { getByLabelText } = setup();
const { TimePicker } = selectors.components;
expect(getByLabelText(TimePicker.applyTimeRange)).toBeInTheDocument();
expect(getByLabelText(TimePicker.fromField)).toBeInTheDocument();
expect(getByLabelText(TimePicker.toField)).toBeInTheDocument();
});
it('should display calendar when clicking the from input field', () => {
const { getByLabelText } = setup();
const { TimePicker } = selectors.components;
fireEvent.focus(getByLabelText(TimePicker.fromField));
expect(getByLabelText(TimePicker.calendar)).toBeInTheDocument();
});
it('should have passed time range entered in form', () => {
const { getByLabelText } = setup();
const { TimePicker } = selectors.components;
const fromValue = defaultTimeRange.raw.from as string;
const toValue = defaultTimeRange.raw.to as string;
expect(getByLabelText(TimePicker.fromField)).toHaveValue(fromValue);
expect(getByLabelText(TimePicker.toField)).toHaveValue(toValue);
});
it('should display calendar when clicking the to input field', () => {
const { getByLabelText } = setup();
const { TimePicker } = selectors.components;
fireEvent.focus(getByLabelText(TimePicker.toField));
expect(getByLabelText(TimePicker.calendar)).toBeInTheDocument();
});
it('should not display calendar without clicking any input field', () => {
const { queryByLabelText } = setup();
const { TimePicker } = selectors.components;
expect(queryByLabelText(TimePicker.calendar)).toBeNull();
});
it('should have passed time range selected in calendar', () => {
const { getByLabelText, getCalendarDayByLabelText } = setup();
const { TimePicker } = selectors.components;
fireEvent.focus(getByLabelText(TimePicker.toField));
const from = getCalendarDayByLabelText('June 17, 2021');
const to = getCalendarDayByLabelText('June 19, 2021');
expect(from).toHaveClass('react-calendar__tile--rangeStart');
expect(to).toHaveClass('react-calendar__tile--rangeEnd');
});
it('should select correct time range in calendar when having a custom time zone', () => {
const { getByLabelText, getCalendarDayByLabelText } = setup(defaultTimeRange, 'Asia/Tokyo');
const { TimePicker } = selectors.components;
fireEvent.focus(getByLabelText(TimePicker.toField));
const from = getCalendarDayByLabelText('June 17, 2021');
const to = getCalendarDayByLabelText('June 19, 2021');
expect(from).toHaveClass('react-calendar__tile--rangeStart');
expect(to).toHaveClass('react-calendar__tile--rangeEnd');
});
});

@ -117,8 +117,8 @@ export const TimeRangeForm: React.FC<Props> = (props) => {
<TimePickerCalendar
isFullscreen={isFullscreen}
isOpen={isOpen}
from={dateTimeParse(from.value, { timeZone })}
to={dateTimeParse(to.value, { timeZone })}
from={dateTimeParse(from.value)}
to={dateTimeParse(to.value)}
onApply={onApply}
onClose={() => setOpen(false)}
onChange={onChange}

Loading…
Cancel
Save