Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(datetimepicker): new DateTimePicker component #1072

Merged
merged 17 commits into from
Apr 22, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
702 changes: 702 additions & 0 deletions src/components/DateTimePicker/DateTimePicker.jsx

Large diffs are not rendered by default.

91 changes: 91 additions & 0 deletions src/components/DateTimePicker/DateTimePicker.story.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { select } from '@storybook/addon-knobs';

import { CARD_SIZES } from '../../constants/LayoutConstants';
import { getCardMinSize } from '../../utils/componentUtilityFunctions';

import DateTimePicker, { INTERVAL_VALUES, RELATIVE_VALUES } from './DateTimePicker';

const customPresets = [
{
label: 'Last 30 minutes',
offset: 30,
},
{
label: 'Last 1 hour',
offset: 60,
},
{
label: 'Last 6 hours',
offset: 360,
},
{
label: 'Last 12 hours',
offset: 720,
},
];

const defaultRelativeValue = {
lastNumber: 20,
lastInterval: INTERVAL_VALUES.MINUTES,
relativeToWhen: RELATIVE_VALUES.TODAY,
relativeToTime: '13:30',
};

const defaultAbsoluteValue = {
startDate: '04/01/2020',
startTime: '12:34',
endDate: '04/06/2020',
endTime: '10:49',
};

const onApply = value => {
console.log('VAL', value);
};

storiesOf('Watson IoT Experimental/DateTime Picker', module)
.add('Default', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUMWIDE);
return (
<div style={{ width: `${getCardMinSize('lg', size).x}px`, margin: 20 }}>
<DateTimePicker />
</div>
);
})
.add('Selected preset', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUMWIDE);
return (
<div style={{ width: `${getCardMinSize('lg', size).x}px`, margin: 20 }}>
<DateTimePicker defaultValue={customPresets[3]} onApply={onApply} />
</div>
);
})
.add('Selected relative', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUMWIDE);
return (
<div style={{ width: `${getCardMinSize('lg', size).x}px`, margin: 20 }}>
<DateTimePicker defaultValue={defaultRelativeValue} onApply={onApply} />
</div>
);
})
.add('Selected absolute', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUMWIDE);
return (
<div style={{ width: `${getCardMinSize('lg', size).x}px`, margin: 20 }}>
<DateTimePicker defaultValue={defaultAbsoluteValue} onApply={onApply} />
</div>
);
})
.add('Without a relative option', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUMWIDE);
return (
<div style={{ width: `${getCardMinSize('lg', size).x}px`, margin: 20 }}>
<DateTimePicker
defaultValue={defaultAbsoluteValue}
showRelativeOption={false}
onApply={onApply}
/>
</div>
);
});
184 changes: 184 additions & 0 deletions src/components/DateTimePicker/DateTimePicker.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import React from 'react';
import { mount } from 'enzyme';
import moment from 'moment';

import DateTimePicker, {
INTERVAL_VALUES,
RELATIVE_VALUES,
PRESETS_VALUES,
PICKER_KINDS,
} from './DateTimePicker';

const dateTimePickerProps = {
id: 'datetimepicker',
onCancel: jest.fn(),
onApply: jest.fn(),
};

const defaultRelativeValue = {
lastNumber: 20,
lastInterval: INTERVAL_VALUES.MINUTES,
relativeToWhen: RELATIVE_VALUES.TODAY,
relativeToTime: '13:30',
};

const defaultAbsoluteValue = {
startDate: '04/01/2020',
startTime: '12:34',
endDate: '04/06/2020',
endTime: '10:49',
};

describe('DateTimePicker tests', () => {
jest.useFakeTimers();

test('it should have the first preset as value', () => {
const wrapper = mount(<DateTimePicker {...dateTimePickerProps} />);
expect(wrapper.find('.iot--date-time-picker__field')).toHaveLength(1);
expect(wrapper.find('.bx--tooltip__trigger').text()).toEqual(PRESETS_VALUES[0].label);
});

test('onApply should be called', () => {
const wrapper = mount(<DateTimePicker {...dateTimePickerProps} />);
wrapper
.find('.iot--date-time-picker__menu-btn-apply')
.first()
.simulate('click');
expect(dateTimePickerProps.onApply).toHaveBeenCalled();
});

test('onCancel should be called', () => {
const wrapper = mount(<DateTimePicker {...dateTimePickerProps} />);
wrapper
.find('.iot--date-time-picker__menu-btn-cancel')
.first()
.simulate('click');
expect(dateTimePickerProps.onCancel).toHaveBeenCalled();
});

test('it should render with a predefined preset', () => {
const wrapper = mount(
<DateTimePicker {...dateTimePickerProps} defaultValue={PRESETS_VALUES[1]} />
);
expect(wrapper.find('.iot--date-time-picker__field')).toHaveLength(1);
expect(wrapper.find('.bx--tooltip__trigger').text()).toEqual(PRESETS_VALUES[1].label);
});

test('it should render with a predefined relative range', () => {
const wrapper = mount(
<DateTimePicker {...dateTimePickerProps} defaultValue={defaultRelativeValue} />
);
expect(wrapper.find('.iot--date-time-picker__field')).toHaveLength(1);

wrapper
.find('.bx--select-input')
.first()
.simulate('change', { target: { value: INTERVAL_VALUES.DAYS } });

wrapper
.find('.bx--select-input')
.at(1)
.simulate('change', { target: { value: RELATIVE_VALUES.YESTERDAY } });

const today = moment();
expect(
wrapper
.find('.iot--date-time-picker__field')
.first()
.text()
).toEqual(`${today.format('YYYY-MM-DD')} 13:10 to ${today.format('YYYY-MM-DD')} 13:30`);

wrapper
.find('.bx--number__control-btn.up-icon')
.first()
.simulate('click');

expect(
wrapper
.find('.iot--date-time-picker__field')
.first()
.text()
).toEqual(`${today.format('YYYY-MM-DD')} 13:09 to ${today.format('YYYY-MM-DD')} 13:30`);

wrapper
.find('.iot--time-picker__controls--btn.up-icon')
.first()
.simulate('click');

expect(
wrapper
.find('.iot--date-time-picker__field')
.first()
.text()
).toEqual(`${today.format('YYYY-MM-DD')} 14:09 to ${today.format('YYYY-MM-DD')} 14:30`);
});

test('it should render with a predefined absolute range', () => {
const wrapper = mount(
<DateTimePicker {...dateTimePickerProps} defaultValue={defaultAbsoluteValue} />
);
expect(wrapper.find('.iot--date-time-picker__field')).toHaveLength(1);
expect(
wrapper
.find('.iot--date-time-picker__field')
.first()
.text()
).toEqual('2020-04-01 12:34 to 2020-04-06 10:49');

wrapper
.find('.iot--time-picker__controls--btn.up-icon')
.first()
.simulate('click');

expect(
wrapper
.find('.iot--date-time-picker__field')
.first()
.text()
).toEqual('2020-04-01 13:34 to 2020-04-06 10:49');

wrapper
.find('.iot--time-picker__controls--btn.up-icon')
.at(1)
.simulate('click');

expect(
wrapper
.find('.iot--date-time-picker__field')
.first()
.text()
).toEqual('2020-04-01 13:34 to 2020-04-06 11:49');
});

test('it should switch from relative to absolute', () => {
const wrapper = mount(
<DateTimePicker {...dateTimePickerProps} defaultValue={defaultRelativeValue} />
);
expect(wrapper.find('.iot--date-time-picker__field')).toHaveLength(1);

wrapper
.find('.bx--radio-button')
.at(1)
.simulate('change', { target: { value: PICKER_KINDS.ABSOLUTE } });

expect(wrapper.find('.iot--time-picker__controls--btn')).toHaveLength(4);
});

test('it should switch from relative to presets', () => {
const wrapper = mount(
<DateTimePicker {...dateTimePickerProps} defaultValue={defaultRelativeValue} />
);
expect(wrapper.find('.iot--date-time-picker__field')).toHaveLength(1);
wrapper
.find('.iot--date-time-picker__field')
.first()
.simulate('click');

wrapper
.find('.iot--date-time-picker__menu-btn-back')
.first()
.simulate('click');

expect(wrapper.find('.iot--time-picker__controls--btn')).toHaveLength(0);
});
});
Loading