Skip to content

Commit

Permalink
Merge 0535640 into 9acb2a5
Browse files Browse the repository at this point in the history
  • Loading branch information
mmarkelov committed Feb 5, 2020
2 parents 9acb2a5 + 0535640 commit b657898
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/components/DateRangePicker.jsx
Expand Up @@ -590,6 +590,7 @@ class DateRangePicker extends React.PureComponent {
openDirection,
phrases,
isOutsideRange,
isDayBlocked,
minimumNights,
withPortal,
withFullScreenPortal,
Expand Down Expand Up @@ -640,6 +641,7 @@ class DateRangePicker extends React.PureComponent {
reopenPickerOnClearDates={reopenPickerOnClearDates}
keepOpenOnDateSelect={keepOpenOnDateSelect}
isOutsideRange={isOutsideRange}
isDayBlocked={isDayBlocked}
minimumNights={minimumNights}
withFullScreenPortal={withFullScreenPortal}
onDatesChange={onDatesChange}
Expand Down
8 changes: 6 additions & 2 deletions src/components/DateRangePickerInputController.jsx
Expand Up @@ -62,6 +62,7 @@ const propTypes = forbidExtraProps({
withFullScreenPortal: PropTypes.bool,
minimumNights: nonNegativeInteger,
isOutsideRange: PropTypes.func,
isDayBlocked: PropTypes.func,
displayFormat: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

onFocusChange: PropTypes.func,
Expand Down Expand Up @@ -118,6 +119,7 @@ const defaultProps = {
withFullScreenPortal: false,
minimumNights: 1,
isOutsideRange: (day) => !isInclusivelyAfterDay(day, moment()),
isDayBlocked: () => false,
displayFormat: () => moment.localeData().longDateFormat('L'),

onFocusChange() {},
Expand Down Expand Up @@ -167,6 +169,7 @@ export default class DateRangePickerInputController extends React.PureComponent
const {
startDate,
isOutsideRange,
isDayBlocked,
minimumNights,
keepOpenOnDateSelect,
onDatesChange,
Expand All @@ -175,7 +178,7 @@ export default class DateRangePickerInputController extends React.PureComponent
const endDate = toMomentObject(endDateString, this.getDisplayFormat());

const isEndDateValid = endDate
&& !isOutsideRange(endDate)
&& !isOutsideRange(endDate) && !isDayBlocked(endDate)
&& !(startDate && isBeforeDay(endDate, startDate.clone().add(minimumNights, 'days')));
if (isEndDateValid) {
onDatesChange({ startDate, endDate });
Expand Down Expand Up @@ -210,6 +213,7 @@ export default class DateRangePickerInputController extends React.PureComponent
let { endDate } = this.props;
const {
isOutsideRange,
isDayBlocked,
minimumNights,
onDatesChange,
onFocusChange,
Expand All @@ -220,7 +224,7 @@ export default class DateRangePickerInputController extends React.PureComponent
const isEndDateBeforeStartDate = startDate
&& isBeforeDay(endDate, startDate.clone().add(minimumNights, 'days'));
const isStartDateValid = startDate
&& !isOutsideRange(startDate)
&& !isOutsideRange(startDate) && !isDayBlocked(startDate)
&& !(disabled === END_DATE && isEndDateBeforeStartDate);

if (isStartDateValid) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/DayPickerKeyboardShortcuts.jsx
Expand Up @@ -214,7 +214,7 @@ class DayPickerKeyboardShortcuts extends React.PureComponent {
topLeft && styles.DayPickerKeyboardShortcuts_showSpan__topLeft,
)}
>
?
?
</span>
</button>
)}
Expand Down
2 changes: 2 additions & 0 deletions src/components/SingleDatePicker.jsx
Expand Up @@ -569,6 +569,7 @@ class SingleDatePicker extends React.PureComponent {
keepOpenOnDateSelect,
styles,
isOutsideRange,
isDayBlocked,
} = this.props;

const { isInputFocused } = this.state;
Expand All @@ -593,6 +594,7 @@ class SingleDatePicker extends React.PureComponent {
showDefaultInputIcon={showDefaultInputIcon}
inputIconPosition={inputIconPosition}
isOutsideRange={isOutsideRange}
isDayBlocked={isDayBlocked}
customCloseIcon={customCloseIcon}
customInputIcon={customInputIcon}
date={date}
Expand Down
5 changes: 4 additions & 1 deletion src/components/SingleDatePickerInputController.jsx
Expand Up @@ -54,6 +54,7 @@ const propTypes = forbidExtraProps({
keepOpenOnDateSelect: PropTypes.bool,
reopenPickerOnClearDate: PropTypes.bool,
isOutsideRange: PropTypes.func,
isDayBlocked: PropTypes.func,
displayFormat: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),

onClose: PropTypes.func,
Expand Down Expand Up @@ -98,6 +99,7 @@ const defaultProps = {
keepOpenOnDateSelect: false,
reopenPickerOnClearDate: false,
isOutsideRange: (day) => !isInclusivelyAfterDay(day, moment()),
isDayBlocked: () => false,
displayFormat: () => moment.localeData().longDateFormat('L'),

onClose() {},
Expand Down Expand Up @@ -129,14 +131,15 @@ export default class SingleDatePickerInputController extends React.PureComponent
onChange(dateString) {
const {
isOutsideRange,
isDayBlocked,
keepOpenOnDateSelect,
onDateChange,
onFocusChange,
onClose,
} = this.props;
const newDate = toMomentObject(dateString, this.getDisplayFormat());

const isValid = newDate && !isOutsideRange(newDate);
const isValid = newDate && !isOutsideRange(newDate) && !isDayBlocked(newDate);
if (isValid) {
onDateChange(newDate);
if (!keepOpenOnDateSelect) {
Expand Down
64 changes: 63 additions & 1 deletion test/components/DateRangePickerInputController_spec.jsx
Expand Up @@ -432,6 +432,37 @@ describe('DateRangePickerInputController', () => {
});
});

describe('is blocked', () => {
const futureDate = moment().add(7, 'days').format('DD/MM/YYYY');
const isDayBlocked = sinon.stub().returns(true);

it('calls props.onDatesChange', () => {
const onDatesChangeStub = sinon.stub();
const wrapper = shallow((
<DateRangePickerInputController
onDatesChange={onDatesChangeStub}
isDayBlocked={isDayBlocked}
/>
));
wrapper.instance().onEndDateChange(futureDate);
expect(onDatesChangeStub.callCount).to.equal(1);
});

it('calls props.onDatesChange with endDate === null', () => {
const onDatesChangeStub = sinon.stub();
const wrapper = shallow((
<DateRangePickerInputController
onDatesChange={onDatesChangeStub}
startDate={today}
isDayBlocked={isDayBlocked}
/>
));
wrapper.instance().onEndDateChange(futureDate);
const args = onDatesChangeStub.getCall(0).args[0];
expect(args.endDate).to.equal(null);
});
});

describe('is inclusively before state.startDate', () => {
const startDate = moment(today).add(10, 'days');
const beforeStartDateString = today.toISOString();
Expand Down Expand Up @@ -720,7 +751,7 @@ describe('DateRangePickerInputController', () => {
});

describe('is outside range', () => {
const futureDate = moment().add(7, 'days').toISOString();
const futureDate = moment().add(7, 'days').format('DD/MM/YYYY');
const isOutsideRange = (day) => day > moment().add(5, 'days');

it('calls props.onDatesChange', () => {
Expand Down Expand Up @@ -763,6 +794,37 @@ describe('DateRangePickerInputController', () => {
expect(args.endDate).to.equal(today);
});
});

describe('is blocked', () => {
const futureDate = moment().add(7, 'days').format('DD/MM/YYYY');
const isDayBlocked = sinon.stub().returns(true);

it('calls props.onDatesChange', () => {
const onDatesChangeStub = sinon.stub();
const wrapper = shallow((
<DateRangePickerInputController
onDatesChange={onDatesChangeStub}
isDayBlocked={isDayBlocked}
/>
));
wrapper.instance().onStartDateChange(futureDate);
expect(onDatesChangeStub.callCount).to.equal(1);
});

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

describe('#onStartDateFocus', () => {
Expand Down
10 changes: 10 additions & 0 deletions test/components/DateRangePicker_spec.jsx
Expand Up @@ -110,6 +110,16 @@ describe('DateRangePicker', () => {
});
});

describe('props.isDayBlocked is defined', () => {
it('should pass props.isDayBlocked to <DateRangePickerInputController>', () => {
const isDayBlocked = sinon.stub();
const wrapper = shallow((
<DateRangePicker {...requiredProps} isDayBlocked={isDayBlocked} />
)).dive();
expect(wrapper.find(DateRangePickerInputController).prop('isDayBlocked')).to.equal(isDayBlocked);
});
});

describe('props.appendToBody', () => {
it('renders <DayPickerRangeController> inside <Portal>', () => {
const wrapper = shallow((
Expand Down
35 changes: 34 additions & 1 deletion test/components/SingleDatePickerInputController_spec.jsx
Expand Up @@ -203,7 +203,7 @@ describe('SingleDatePickerInputController', () => {

describe('date string outside range', () => {
const isOutsideRangeStub = sinon.stub().returns(true);
const todayDateString = today.toISOString();
const todayDateString = today.format('DD/MM/YYYY');

it('calls props.onDateChange once', () => {
const onDateChangeStub = sinon.stub();
Expand Down Expand Up @@ -247,6 +247,39 @@ describe('SingleDatePickerInputController', () => {
expect(onFocusChangeStub.callCount).to.equal(0);
});
});

describe('date string is blocked', () => {
const isDayBlocked = sinon.stub().returns(true);
const todayDateString = today.format('DD/MM/YYYY');

it('calls props.onDateChange once', () => {
const onDateChangeStub = sinon.stub();
const wrapper = shallow((
<SingleDatePickerInputController
id="date"
onDateChange={onDateChangeStub}
onFocusChange={() => {}}
isDayBlocked={isDayBlocked}
/>
));
wrapper.instance().onChange(todayDateString);
expect(onDateChangeStub.callCount).to.equal(1);
});

it('calls props.onDateChange with null as 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[0]).to.equal(null);
});
});
});

describe('#onFocus', () => {
Expand Down
15 changes: 15 additions & 0 deletions test/components/SingleDatePicker_spec.jsx
Expand Up @@ -56,6 +56,21 @@ describe('SingleDatePicker', () => {
expect(wrapper.find(SingleDatePickerInputController).prop('isOutsideRange')).to.equal(isOutsideRange);
});
});

describe('props.isDayBlocked is defined', () => {
it('should pass props.isDayBlocked to <SingleDatePickerInputController>', () => {
const isDayBlocked = sinon.stub();
const wrapper = shallow((
<SingleDatePicker
id="date"
onDateChange={() => {}}
onFocusChange={() => {}}
isDayBlocked={isDayBlocked}
/>
)).dive();
expect(wrapper.find(SingleDatePickerInputController).prop('isDayBlocked')).to.equal(isDayBlocked);
});
});
});

describe('DayPickerSingleDateController', () => {
Expand Down

0 comments on commit b657898

Please sign in to comment.