Skip to content

Commit

Permalink
Merge pull request #702 from airbnb/maja-address-issue-700
Browse files Browse the repository at this point in the history
Reset visibleDays/currentMonth state when enableOutsideDays or numberOfMonths has changed
  • Loading branch information
majapw authored Sep 6, 2017
2 parents caaee3d + 0ef7c79 commit 2d56f39
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 179 deletions.
7 changes: 6 additions & 1 deletion src/components/DayPicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,13 @@ export default class DayPicker extends React.Component {
}

componentDidUpdate(prevProps, prevState) {
const { numberOfMonths } = this.props;
const { monthTransition, currentMonth, focusedDate } = this.state;
if (monthTransition || !currentMonth.isSame(prevState.currentMonth)) {
if (
monthTransition ||
!currentMonth.isSame(prevState.currentMonth) ||
numberOfMonths !== prevProps.numberOfMonths
) {
if (this.isHorizontal()) {
this.adjustDayPickerHeight();
}
Expand Down
7 changes: 3 additions & 4 deletions src/components/DayPickerRangeController.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,10 @@ export default class DayPickerRangeController extends React.Component {
const didFocusChange = focusedInput !== this.props.focusedInput;

if (
numberOfMonths !== this.props.numberOfMonths ||
enableOutsideDays !== this.props.enableOutsideDays ||
(
initialVisibleMonth !== this.props.initialVisibleMonth ||
numberOfMonths !== this.props.numberOfMonths ||
enableOutsideDays !== this.props.enableOutsideDays
) && (
initialVisibleMonth !== this.props.initialVisibleMonth &&
!this.props.focusedInput &&
didFocusChange
)
Expand Down
8 changes: 6 additions & 2 deletions src/components/DayPickerSingleDateController.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,13 @@ export default class DayPickerSingleDateController extends React.Component {
recomputeOutsideRange || recomputeDayBlocked || recomputeDayHighlighted;

if (
initialVisibleMonth !== this.props.initialVisibleMonth ||
numberOfMonths !== this.props.numberOfMonths ||
enableOutsideDays !== this.props.enableOutsideDays
enableOutsideDays !== this.props.enableOutsideDays ||
(
initialVisibleMonth !== this.props.initialVisibleMonth &&
!this.props.focused &&
focused
)
) {
const newMonthState = this.getStateForNewMonth(nextProps);
const currentMonth = newMonthState.currentMonth;
Expand Down
234 changes: 62 additions & 172 deletions test/components/DayPickerRangeController_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,198 +143,88 @@ describe('DayPickerRangeController', () => {
});

describe('numberOfMonths changed', () => {
describe('focusedInput has changed and is truthy', () => {
it('calls getStateForNewMonth with nextProps', () => {
const getStateForNewMonthSpy =
sinon.spy(DayPickerRangeController.prototype, 'getStateForNewMonth');
const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
getStateForNewMonthSpy.reset();
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: START_DATE,
numberOfMonths: 5,
});
expect(getStateForNewMonthSpy.callCount).to.equal(1);
});

it('sets state.currentMonth to getStateForNewMonth.currentMonth', () => {
const currentMonth = moment().add(10, 'months');
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays: {} });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: START_DATE,
numberOfMonths: 5,
});
expect(wrapper.instance().state.currentMonth).to.equal(currentMonth);
});

it('sets state.visibleDays to getStateForNewMonth.visibleDays', () => {
const currentMonth = moment().add(10, 'months');
const visibleDays = getVisibleDays(currentMonth, 1);
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: START_DATE,
numberOfMonths: 5,
});
expect(wrapper.instance().state.visibleDays).to.equal(visibleDays);
it('calls getStateForNewMonth with nextProps', () => {
const getStateForNewMonthSpy =
sinon.spy(DayPickerRangeController.prototype, 'getStateForNewMonth');
const wrapper = shallow(<DayPickerRangeController {...props} />);
getStateForNewMonthSpy.reset();
wrapper.instance().componentWillReceiveProps({
...props,
numberOfMonths: 5,
});
expect(getStateForNewMonthSpy.callCount).to.equal(1);
});

describe('focusedInput has not changed', () => {
it('does not call getStateForNewMonth', () => {
const getStateForNewMonthSpy =
sinon.spy(DayPickerRangeController.prototype, 'getStateForNewMonth');
const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
getStateForNewMonthSpy.reset();
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: null,
numberOfMonths: 5,
});
expect(getStateForNewMonthSpy.callCount).to.equal(0);
});

it('does not change state.currentMonth', () => {
const currentMonth = moment().add(10, 'months');
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth: moment(), visibleDays: {} });
it('sets state.currentMonth to getStateForNewMonth.currentMonth', () => {
const currentMonth = moment().add(10, 'months');
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays: {} });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.setState({ currentMonth });
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: null,
numberOfMonths: 5,
});
expect(wrapper.instance().state.currentMonth).to.equal(currentMonth);
const wrapper = shallow(<DayPickerRangeController {...props} />);
wrapper.instance().componentWillReceiveProps({
...props,
numberOfMonths: 5,
});
expect(wrapper.instance().state.currentMonth).to.equal(currentMonth);
});

it('does not change state.visibleDays', () => {
const visibleDays = {};
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({
currentMonth: moment(),
visibleDays: getVisibleDays(moment(), 1),
});
it('sets state.visibleDays to getStateForNewMonth.visibleDays', () => {
const currentMonth = moment().add(10, 'months');
const visibleDays = getVisibleDays(currentMonth, 1);
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.setState({ visibleDays });
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: null,
numberOfMonths: 5,
});
expect(wrapper.instance().state.visibleDays).to.equal(visibleDays);
const wrapper = shallow(<DayPickerRangeController {...props} />);
wrapper.instance().componentWillReceiveProps({
...props,
numberOfMonths: 5,
});
expect(wrapper.instance().state.visibleDays).to.equal(visibleDays);
});
});

describe('enableOutsideDays changed', () => {
describe('focusedInput has changed and is truthy', () => {
it('calls getStateForNewMonth with nextProps', () => {
const getStateForNewMonthSpy =
sinon.spy(DayPickerRangeController.prototype, 'getStateForNewMonth');
const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
getStateForNewMonthSpy.reset();
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: START_DATE,
enableOutsideDays: true,
});
expect(getStateForNewMonthSpy.callCount).to.equal(1);
});

it('sets state.currentMonth to getStateForNewMonth.currentMonth', () => {
const currentMonth = moment().add(10, 'months');
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays: {} });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: START_DATE,
enableOutsideDays: true,
});
expect(wrapper.instance().state.currentMonth).to.equal(currentMonth);
});

it('sets state.visibleDays to getStateForNewMonth.visibleDays', () => {
const currentMonth = moment().add(10, 'months');
const visibleDays = getVisibleDays(currentMonth, 1);
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: START_DATE,
enableOutsideDays: true,
});
expect(wrapper.instance().state.visibleDays).to.equal(visibleDays);
it('calls getStateForNewMonth with nextProps', () => {
const getStateForNewMonthSpy =
sinon.spy(DayPickerRangeController.prototype, 'getStateForNewMonth');
const wrapper = shallow(<DayPickerRangeController {...props} />);
getStateForNewMonthSpy.reset();
wrapper.instance().componentWillReceiveProps({
...props,
enableOutsideDays: true,
});
expect(getStateForNewMonthSpy.callCount).to.equal(1);
});

describe('focusedInput has not changed', () => {
it('does not call getStateForNewMonth', () => {
const getStateForNewMonthSpy =
sinon.spy(DayPickerRangeController.prototype, 'getStateForNewMonth');
const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
getStateForNewMonthSpy.reset();
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: null,
enableOutsideDays: true,
});
expect(getStateForNewMonthSpy.callCount).to.equal(0);
});

it('does not change state.currentMonth', () => {
const currentMonth = moment().add(10, 'months');
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth: moment(), visibleDays: {} });
it('sets state.currentMonth to getStateForNewMonth.currentMonth', () => {
const currentMonth = moment().add(10, 'months');
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays: {} });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.setState({ currentMonth });
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: null,
enableOutsideDays: true,
});
expect(wrapper.instance().state.currentMonth).to.equal(currentMonth);
const wrapper = shallow(<DayPickerRangeController {...props} />);
wrapper.instance().componentWillReceiveProps({
...props,
enableOutsideDays: true,
});
expect(wrapper.instance().state.currentMonth).to.equal(currentMonth);
});

it('does not change state.visibleDays', () => {
const visibleDays = {};
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({
currentMonth: moment(),
visibleDays: getVisibleDays(moment(), 1),
});
it('sets state.visibleDays to getStateForNewMonth.visibleDays', () => {
const currentMonth = moment().add(10, 'months');
const visibleDays = getVisibleDays(currentMonth, 1);
const getStateForNewMonthStub =
sinon.stub(DayPickerRangeController.prototype, 'getStateForNewMonth');
getStateForNewMonthStub.returns({ currentMonth, visibleDays });

const wrapper = shallow(<DayPickerRangeController {...props} focusedInput={null} />);
wrapper.setState({ visibleDays });
wrapper.instance().componentWillReceiveProps({
...props,
focusedInput: null,
enableOutsideDays: true,
});
expect(wrapper.instance().state.visibleDays).to.equal(visibleDays);
const wrapper = shallow(<DayPickerRangeController {...props} />);
wrapper.instance().componentWillReceiveProps({
...props,
enableOutsideDays: true,
});
expect(wrapper.instance().state.visibleDays).to.equal(visibleDays);
});
});
});
Expand Down

0 comments on commit 2d56f39

Please sign in to comment.