From 3da196e4e54c9c74abb1eccc20444de2aa0f6ca8 Mon Sep 17 00:00:00 2001 From: Francois Malinowski Date: Tue, 15 Nov 2022 16:42:09 -0800 Subject: [PATCH] fix: dateInput onClose not called with last picked date DateInput onClose callback is not called with last picked date when value property is present --- src/components/Input/DateInput.js | 2 +- src/components/Input/DateInput.spec.js | 121 ++++++++++++++++++++++--- 2 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/components/Input/DateInput.js b/src/components/Input/DateInput.js index 1af1d2971..5b54c2f5f 100644 --- a/src/components/Input/DateInput.js +++ b/src/components/Input/DateInput.js @@ -274,7 +274,7 @@ export default class DateInput extends React.Component { componentDidUpdate(prevProps, prevState) { this.setInputValue(); if (this.props.onClose && this.state.open !== prevState.open && !this.state.open) { - const value = this.props.value !== undefined ? this.props.value : this.state.value; + const value = this.state.value; const date = this.props.parse(value, this.props.dateFormat); if (date) { diff --git a/src/components/Input/DateInput.spec.js b/src/components/Input/DateInput.spec.js index df6c5da94..6bed0eca9 100644 --- a/src/components/Input/DateInput.spec.js +++ b/src/components/Input/DateInput.spec.js @@ -8,7 +8,7 @@ import isToday from 'date-fns/is_today'; import frLocale from 'date-fns/locale/fr'; import startOfToday from 'date-fns/start_of_today'; import { mount } from 'enzyme'; -import React from 'react'; +import React, { useState } from 'react'; import sinon from 'sinon'; import Button from '../Button/Button'; import Icon from '../Icon/Icon'; @@ -159,11 +159,15 @@ describe('', () => { }); describe('date picker', () => { - const callback = sinon.spy(); - const component = mount(); + let callback, onCloseCallback, component; + + beforeEach(() => { + callback = sinon.spy(); + onCloseCallback = sinon.spy(); + component = mount(); + }); it('should set date after clicking a date', () => { - callback.resetHistory(); const firstDate = component.find('Day').first(); const expectedDate = firstDate.props().day.date; firstDate.simulate('click'); @@ -172,7 +176,6 @@ describe('', () => { }); it('should call onChange after clicking a date', () => { - callback.resetHistory(); const lastDate = component.find('Day').first(); const expectedDate = lastDate.props().day.date; lastDate.simulate('click'); @@ -180,7 +183,6 @@ describe('', () => { }); it('should set date after clicking prev year', () => { - callback.resetHistory(); const expectedDate = addYears(component.instance().getCurrentDate(), -1); const prevYear = component.find('Button.js-prev-year'); @@ -191,7 +193,6 @@ describe('', () => { }); it('should set date after clicking next year', () => { - callback.resetHistory(); const expectedDate = addYears(component.instance().getCurrentDate(), 1); const nextYear = component.find('Button.js-next-year'); @@ -202,7 +203,6 @@ describe('', () => { }); it('should set date after clicking prev month', () => { - callback.resetHistory(); const expectedDate = addMonths(component.instance().getCurrentDate(), -1); const prevMonth = component.find('Button.js-prev-month'); @@ -213,7 +213,6 @@ describe('', () => { }); it('should set date after clicking next month', () => { - callback.resetHistory(); const expectedDate = addMonths(component.instance().getCurrentDate(), 1); const nextMonth = component.find('Button.js-next-month'); @@ -230,7 +229,6 @@ describe('', () => { }); it('should call onChange after clicking today', () => { - callback.resetHistory(); const today = component.find('footer Button').at(0); today.simulate('click'); assert(callback.called); @@ -246,7 +244,6 @@ describe('', () => { }); it('should call onChange after clicking clear', () => { - callback.resetHistory(); const clear = component.find('footer Button').at(1); clear.simulate('click'); assert(callback.calledWith('', false)); @@ -272,6 +269,108 @@ describe('', () => { input.simulate('keydown', { key: 'ArrowRight', keyCode: 39, which: 39 }); assert(isSameDay(component.instance().getCurrentDate(), expectedDate)); }); + + it('should call onClose when closing the date picker with the latest selected date in the current month', () => { + const toggle = component.find('InputGroup').find('Button'); + toggle.simulate('click'); + + const initialDate = component.instance().getCurrentDate(); + const isFirstOfMonth = initialDate.getDate() === 1; + const dayToPick = isFirstOfMonth ? component.find('Day').at(1) : component.find('Day').at(0); + + const expectedDate = dayToPick.props().day.date; + + dayToPick.simulate('click'); + assert(onCloseCallback.calledOnce); + assert(onCloseCallback.calledWith(expectedDate, true)); + }); + + it('should call onClose with the last selected date when we change the month', () => { + const toggle = component.find('InputGroup').find('Button'); + toggle.simulate('click'); + + const nextMonth = component.find('Button.js-next-month'); + nextMonth.simulate('click'); + + const tentativeIndexDayToPick = 15; + const tentativeDayToPick = component.find('Day').at(tentativeIndexDayToPick); + const dayToPick = + tentativeDayToPick.props().day.date.getDate() === component.instance().getCurrentDate().getDate() + ? component.find('Day').at(tentativeIndexDayToPick + 1) + : tentativeDayToPick; + + const expectedDate = dayToPick.props().day.date; + + dayToPick.simulate('click'); + assert(onCloseCallback.calledOnce); + assert(onCloseCallback.calledWith(expectedDate, true)); + }); + }); + + describe('date picker with value property', () => { + let onChangeCallback, onCloseCallback, wrapper; + + beforeEach(() => { + onChangeCallback = sinon.spy(); + onCloseCallback = sinon.spy(); + + const WrappingComponent = () => { + const [ dateValue, setDateValue ] = useState(new Date()); + + const onChange = (date, valid) => { + onChangeCallback(date, valid); + setDateValue(date); + }; + + return ( + + ); + }; + + wrapper = mount(); + }); + + it('should call onClose when closing the date picker with the latest selected date in the current month', () => { + const toggle = wrapper.find('DateInput').find('InputGroup').find('Button'); + toggle.simulate('click'); + + const initialDate = wrapper.find('DateInput').instance().getCurrentDate(); + const isFirstOfMonth = initialDate.getDate() === 1; + const dayToPick = isFirstOfMonth + ? wrapper.find('DateInput').find('Day').at(1) + : wrapper.find('DateInput').find('Day').at(0); + + const expectedDate = dayToPick.props().day.date; + + dayToPick.simulate('click'); + assert(onCloseCallback.calledOnce); + assert(onCloseCallback.calledWith(expectedDate, true)); + }); + + it('should call onClose with the last selected date when we change the month', () => { + const toggle = wrapper.find('DateInput').find('InputGroup').find('Button'); + toggle.simulate('click'); + + const nextMonth = wrapper.find('DateInput').find('Button.js-next-month'); + nextMonth.simulate('click'); + + const tentativeIndexDayToPick = 15; + const tentativeDayToPick = wrapper.find('DateInput').find('Day').at(tentativeIndexDayToPick); + const dayToPick = + tentativeDayToPick.props().day.date.getDate() === + wrapper.find('DateInput').instance().getCurrentDate().getDate() + ? wrapper + .find('DateInput') + .find('Day') + .at(tentativeIndexDayToPick + 1) + : tentativeDayToPick; + + const expectedDate = dayToPick.props().day.date; + + dayToPick.simulate('click'); + assert(onCloseCallback.calledOnce); + assert(onCloseCallback.calledWith(expectedDate, true)); + }); }); describe('date picker with controlled visible dates', () => {