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

Issue 1937 | Pass invalid date string to date change handlers #1941

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
14 changes: 10 additions & 4 deletions examples/DateRangePickerWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const propTypes = {
stateDateWrapper: PropTypes.func,
initialStartDate: momentPropTypes.momentObj,
initialEndDate: momentPropTypes.momentObj,
onInvalidInput: PropTypes.func,

...omit(DateRangePickerShape, [
'startDate',
Expand All @@ -40,6 +41,7 @@ const defaultProps = {
autoFocusEndDate: false,
initialStartDate: null,
initialEndDate: null,
onInvalidInput: () => null,

// input related props
startDateId: START_DATE,
Expand Down Expand Up @@ -85,15 +87,15 @@ const defaultProps = {
minimumNights: 1,
enableOutsideDays: false,
isDayBlocked: () => false,
isOutsideRange: day => !isInclusivelyAfterDay(day, moment()),
isOutsideRange: (day) => !isInclusivelyAfterDay(day, moment()),
isDayHighlighted: () => false,

// internationalization
displayFormat: () => moment.localeData().longDateFormat('L'),
monthFormat: 'MMMM YYYY',
phrases: DateRangePickerPhrases,

stateDateWrapper: date => date,
stateDateWrapper: (date) => date,
};

class DateRangePickerWrapper extends React.Component {
Expand All @@ -117,12 +119,15 @@ class DateRangePickerWrapper extends React.Component {
this.onFocusChange = this.onFocusChange.bind(this);
}

onDatesChange({ startDate, endDate }) {
const { stateDateWrapper } = this.props;
onDatesChange({ startDate, endDate, invalidDateString }) {
const { onInvalidInput, stateDateWrapper } = this.props;
this.setState({
startDate: startDate && stateDateWrapper(startDate),
endDate: endDate && stateDateWrapper(endDate),
});
if (invalidDateString) {
onInvalidInput(invalidDateString);
}
}

onFocusChange(focusedInput) {
Expand All @@ -141,6 +146,7 @@ class DateRangePickerWrapper extends React.Component {
'initialStartDate',
'initialEndDate',
'stateDateWrapper',
'onInvalidInput',
]);

return (
Expand Down
11 changes: 9 additions & 2 deletions examples/SingleDatePickerWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const propTypes = {
// example props for the demo
autoFocus: PropTypes.bool,
initialDate: momentPropTypes.momentObj,
onInvalidInput: PropTypes.func,

...omit(SingleDatePickerShape, [
'date',
Expand All @@ -28,6 +29,7 @@ const defaultProps = {
// example props for the demo
autoFocus: false,
initialDate: null,
onInvalidInput: () => null,

// input related props
id: 'date',
Expand Down Expand Up @@ -69,7 +71,7 @@ const defaultProps = {
renderDayContents: null,
enableOutsideDays: false,
isDayBlocked: () => false,
isOutsideRange: day => !isInclusivelyAfterDay(day, moment()),
isOutsideRange: (day) => !isInclusivelyAfterDay(day, moment()),
isDayHighlighted: () => {},

// internationalization props
Expand All @@ -90,8 +92,12 @@ class SingleDatePickerWrapper extends React.Component {
this.onFocusChange = this.onFocusChange.bind(this);
}

onDateChange(date) {
onDateChange(date, invalidDateString) {
const { onInvalidInput } = this.props;
this.setState({ date });
if (invalidDateString) {
onInvalidInput(invalidDateString);
}
}

onFocusChange({ focused }) {
Expand All @@ -106,6 +112,7 @@ class SingleDatePickerWrapper extends React.Component {
const props = omit(this.props, [
'autoFocus',
'initialDate',
'onInvalidInput',
]);

return (
Expand Down
2 changes: 2 additions & 0 deletions src/components/DateRangePickerInputController.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export default class DateRangePickerInputController extends React.PureComponent
onDatesChange({
startDate,
endDate: null,
invalidDateString: endDateString,
});
}
}
Expand Down Expand Up @@ -238,6 +239,7 @@ export default class DateRangePickerInputController extends React.PureComponent
onDatesChange({
startDate: null,
endDate,
invalidDateString: startDateString,
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/SingleDatePickerInputController.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default class SingleDatePickerInputController extends React.PureComponent
onClose({ date: newDate });
}
} else {
onDateChange(null);
onDateChange(null, dateString);
}
}

Expand Down
17 changes: 13 additions & 4 deletions stories/DateRangePicker_input.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ const TestCustomCloseIcon = () => (
color: '#484848',
padding: '3px',
}}
>'X'</span>
>
'X'
</span>
);

storiesOf('DRP - Input Props', module)
Expand All @@ -64,16 +66,16 @@ storiesOf('DRP - Input Props', module)
initialStartDate={moment().add(3, 'months')}
initialEndDate={moment().add(3, 'months').add(10, 'days')}
disabled="startDate"
isOutsideRange={day => !isInclusivelyAfterDay(day, moment().add(3, 'months'))}
isOutsideRange={(day) => !isInclusivelyAfterDay(day, moment().add(3, 'months'))}
/>
)))
.add('disabled end date', withInfo()(() => (
<DateRangePickerWrapper
initialStartDate={moment().add(3, 'months')}
initialEndDate={moment().add(3, 'months').add(10, 'days')}
disabled="endDate"
isOutsideRange={day => !isInclusivelyAfterDay(day, moment()) ||
!isInclusivelyBeforeDay(day, moment().add(3, 'months').add(10, 'days'))}
isOutsideRange={(day) => !isInclusivelyAfterDay(day, moment())
|| !isInclusivelyBeforeDay(day, moment().add(3, 'months').add(10, 'days'))}
/>
)))
.add('readOnly', withInfo()(() => (
Expand Down Expand Up @@ -179,4 +181,11 @@ storiesOf('DRP - Input Props', module)
showClearDates
regular
/>
)))
.add('handle invalid input', withInfo()(() => (
<DateRangePickerWrapper
initialStartDate={moment().add(3, 'months')}
initialEndDate={moment().add(3, 'months').add(10, 'days')}
onInvalidInput={(input) => alert(`invalid date string: ${input}`)}
/>
)));
6 changes: 6 additions & 0 deletions stories/SingleDatePicker_input.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,10 @@ storiesOf('SDP - Input Props', module)
showClearDate
regular
/>
)))
.add('handle invalid input', withInfo()(() => (
<SingleDatePickerWrapper
initialDate={moment().add(3, 'days')}
onInvalidInput={(input) => alert(`invalid date string: ${input}`)}
/>
)));
23 changes: 23 additions & 0 deletions test/components/DateRangePickerInputController_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,16 @@ describe('DateRangePickerInputController', () => {
const args = onDatesChangeStub.getCall(0).args[0];
expect(args.endDate).to.equal(null);
});

it('calls props.onDatesChange with invalidDateString in arg object', () => {
const onDatesChangeStub = sinon.stub();
const wrapper = shallow((
<DateRangePickerInputController onDatesChange={onDatesChangeStub} />
));
wrapper.instance().onEndDateChange(invalidDateString);
const args = onDatesChangeStub.getCall(0).args[0];
expect(args.invalidDateString).to.equal(invalidDateString);
});
});

describe('is outside range', () => {
Expand Down Expand Up @@ -739,6 +749,19 @@ describe('DateRangePickerInputController', () => {
expect(args.startDate).to.equal(null);
});

it('calls props.onDatesChange with invalidDateString in arg object', () => {
const onDatesChangeStub = sinon.stub();
const wrapper = shallow((
<DateRangePickerInputController
onDatesChange={onDatesChangeStub}
startDate={today}
/>
));
wrapper.instance().onStartDateChange(invalidDateString);
const args = onDatesChangeStub.getCall(0).args[0];
expect(args.invalidDateString).to.equal(invalidDateString);
});

it('calls props.onDatesChange with endDate === props.endDate', () => {
const onDatesChangeStub = sinon.stub();
const wrapper = shallow((
Expand Down
43 changes: 40 additions & 3 deletions test/components/SingleDatePickerInputController_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ describe('SingleDatePickerInputController', () => {
expect(onDateChangeStub.callCount).to.equal(1);
});

it('calls props.onDateChange with null as arg', () => {
it('calls props.onDateChange with null as first arg', () => {
const onDateChangeStub = sinon.stub();
const wrapper = shallow((
<SingleDatePickerInputController id="date" onDateChange={onDateChangeStub} onFocusChange={() => {}} />
Expand All @@ -191,6 +191,15 @@ describe('SingleDatePickerInputController', () => {
expect(onDateChangeStub.getCall(0).args[0]).to.equal(null);
});

it('calls props.onDateChange with invalid string as second arg', () => {
const onDateChangeStub = sinon.stub();
const wrapper = shallow((
<SingleDatePickerInputController id="date" onDateChange={onDateChangeStub} onFocusChange={() => {}} />
));
wrapper.instance().onChange(invalidDateString);
expect(onDateChangeStub.getCall(0).args[1]).to.equal(invalidDateString);
});

it('does not call props.onFocusChange', () => {
const onFocusChangeStub = sinon.stub();
const wrapper = shallow((
Expand Down Expand Up @@ -219,7 +228,7 @@ describe('SingleDatePickerInputController', () => {
expect(onDateChangeStub.callCount).to.equal(1);
});

it('calls props.onDateChange with null as arg', () => {
it('calls props.onDateChange with null as first arg', () => {
const onDateChangeStub = sinon.stub();
const wrapper = shallow((
<SingleDatePickerInputController
Expand All @@ -233,6 +242,20 @@ describe('SingleDatePickerInputController', () => {
expect(onDateChangeStub.getCall(0).args[0]).to.equal(null);
});

it('calls props.onDateChange with date string as second arg', () => {
const onDateChangeStub = sinon.stub();
const wrapper = shallow((
<SingleDatePickerInputController
id="date"
onDateChange={onDateChangeStub}
onFocusChange={() => {}}
isOutsideRange={isOutsideRangeStub}
/>
));
wrapper.instance().onChange(todayDateString);
expect(onDateChangeStub.getCall(0).args[1]).to.equal(todayDateString);
});

it('does not call props.onFocusChange', () => {
const onFocusChangeStub = sinon.stub();
const wrapper = shallow((
Expand Down Expand Up @@ -266,7 +289,7 @@ describe('SingleDatePickerInputController', () => {
expect(onDateChangeStub.callCount).to.equal(1);
});

it('calls props.onDateChange with null as arg', () => {
it('calls props.onDateChange with null as first arg', () => {
const onDateChangeStub = sinon.stub();
const wrapper = shallow((
<SingleDatePickerInputController
Expand All @@ -279,6 +302,20 @@ describe('SingleDatePickerInputController', () => {
wrapper.instance().onChange(todayDateString);
expect(onDateChangeStub.getCall(0).args[0]).to.equal(null);
});

it('calls props.onDateChange with date string as second arg', () => {
const onDateChangeStub = sinon.stub();
const wrapper = shallow((
<SingleDatePickerInputController
id="date"
onDateChange={onDateChangeStub}
onFocusChange={() => {}}
isDayBlocked={isDayBlocked}
/>
));
wrapper.instance().onChange(todayDateString);
expect(onDateChangeStub.getCall(0).args[1]).to.equal(todayDateString);
});
});
});

Expand Down