Skip to content

Commit ccb0c22

Browse files
authored
fix: improve validation when creating input (#26)
* Update validation to restrict input to only digits that create a valid date * Remove guesstimation functionality around selecting from an invalid date
1 parent 64e7586 commit ccb0c22

File tree

2 files changed

+92
-32
lines changed

2 files changed

+92
-32
lines changed

src/__tests__/datepicker.test.js

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -558,64 +558,118 @@ describe('Date picker', () => {
558558
expect(previousYearButton.tabIndex).toEqual(0);
559559
});
560560

561-
it('should set focus on nearest date when day input is incorrectly formatted', () => {
561+
it('should set focus on today when day input is not a number', () => {
562562
datePicker(document.querySelector('.date-picker'), {});
563563
const revealButton = document.querySelector('.date-picker__reveal');
564564
const dayInput = document.querySelector('.date-picker-day');
565565
const monthInput = document.querySelector('.date-picker-month');
566566
const yearInput = document.querySelector('.date-picker-year');
567567

568-
$(dayInput).val('40');
568+
$(dayInput).val('3 12');
569569
$(monthInput).val('11');
570570
$(yearInput).val('2021');
571571

572572
$(revealButton).trigger('click');
573573

574-
const nearestDate = DateTime.fromObject({ year: 2021, month: 11, day: 30 });
575-
const nearestDateButton = document.querySelector(`[data-test-id="${nearestDate.toLocaleString()}"]`);
574+
const focusedDate = document.querySelector(`[data-test-id="${now.toLocaleString()}"]`);
576575

577-
expect(nearestDateButton === document.activeElement).toBeTruthy();
578-
expect(nearestDateButton.tabIndex).toEqual(0);
576+
expect(focusedDate === document.activeElement).toBeTruthy();
577+
expect(focusedDate.tabIndex).toEqual(0);
579578
});
580579

581-
it('should set focus on nearest date when month input is incorrectly formatted', () => {
580+
it('should set focus on today when month input is not a number', () => {
582581
datePicker(document.querySelector('.date-picker'), {});
583582
const revealButton = document.querySelector('.date-picker__reveal');
584583
const dayInput = document.querySelector('.date-picker-day');
585584
const monthInput = document.querySelector('.date-picker-month');
586585
const yearInput = document.querySelector('.date-picker-year');
587586

588587
$(dayInput).val('15');
589-
$(monthInput).val('13');
588+
$(monthInput).val('11 20');
590589
$(yearInput).val('2021');
591590

592591
$(revealButton).trigger('click');
593592

594-
const nearestDate = DateTime.fromObject({ year: 2021, month: 12, day: 15 });
595-
const nearestDateButton = document.querySelector(`[data-test-id="${nearestDate.toLocaleString()}"]`);
593+
const focusedDate = document.querySelector(`[data-test-id="${now.toLocaleString()}"]`);
596594

597-
expect(nearestDateButton === document.activeElement).toBeTruthy();
598-
expect(nearestDateButton.tabIndex).toEqual(0);
595+
expect(focusedDate === document.activeElement).toBeTruthy();
596+
expect(focusedDate.tabIndex).toEqual(0);
599597
});
600598

601-
it('should set focus on 31st December when day and month input is incorrectly formatted', () => {
599+
it('should set focus on today when year input is not a number', () => {
602600
datePicker(document.querySelector('.date-picker'), {});
603601
const revealButton = document.querySelector('.date-picker__reveal');
604602
const dayInput = document.querySelector('.date-picker-day');
605603
const monthInput = document.querySelector('.date-picker-month');
606604
const yearInput = document.querySelector('.date-picker-year');
607605

608-
$(dayInput).val('32');
606+
$(dayInput).val('15');
607+
$(monthInput).val('11');
608+
$(yearInput).val('20 22');
609+
610+
$(revealButton).trigger('click');
611+
612+
const focusedDate = document.querySelector(`[data-test-id="${now.toLocaleString()}"]`);
613+
614+
expect(focusedDate === document.activeElement).toBeTruthy();
615+
expect(focusedDate.tabIndex).toEqual(0);
616+
});
617+
618+
it('should set focus on today when day input is an invalid number', () => {
619+
datePicker(document.querySelector('.date-picker'), {});
620+
const revealButton = document.querySelector('.date-picker__reveal');
621+
const dayInput = document.querySelector('.date-picker-day');
622+
const monthInput = document.querySelector('.date-picker-month');
623+
const yearInput = document.querySelector('.date-picker-year');
624+
625+
$(dayInput).val('1125');
626+
$(monthInput).val('11');
627+
$(yearInput).val('2022');
628+
629+
$(revealButton).trigger('click');
630+
631+
const focusedDate = document.querySelector(`[data-test-id="${now.toLocaleString()}"]`);
632+
633+
expect(focusedDate === document.activeElement).toBeTruthy();
634+
expect(focusedDate.tabIndex).toEqual(0);
635+
});
636+
637+
it('should set focus on today when month input is an invalid number', () => {
638+
datePicker(document.querySelector('.date-picker'), {});
639+
const revealButton = document.querySelector('.date-picker__reveal');
640+
const dayInput = document.querySelector('.date-picker-day');
641+
const monthInput = document.querySelector('.date-picker-month');
642+
const yearInput = document.querySelector('.date-picker-year');
643+
644+
$(dayInput).val('11');
609645
$(monthInput).val('13');
610646
$(yearInput).val('2022');
611647

612648
$(revealButton).trigger('click');
613649

614-
const nearestDate = DateTime.fromObject({ year: 2022, month: 12, day: 31 });
615-
const nearestDateButton = document.querySelector(`[data-test-id="${nearestDate.toLocaleString()}"]`);
650+
const focusedDate = document.querySelector(`[data-test-id="${now.toLocaleString()}"]`);
616651

617-
expect(nearestDateButton === document.activeElement).toBeTruthy();
618-
expect(nearestDateButton.tabIndex).toEqual(0);
652+
expect(focusedDate === document.activeElement).toBeTruthy();
653+
expect(focusedDate.tabIndex).toEqual(0);
654+
});
655+
656+
it('should set focus on today when year input is an invalid number', () => {
657+
datePicker(document.querySelector('.date-picker'), {});
658+
const revealButton = document.querySelector('.date-picker__reveal');
659+
const dayInput = document.querySelector('.date-picker-day');
660+
const monthInput = document.querySelector('.date-picker-month');
661+
const yearInput = document.querySelector('.date-picker-year');
662+
663+
$(dayInput).val('11');
664+
$(monthInput).val('11');
665+
$(yearInput).val('202220222022202220222022');
666+
667+
$(revealButton).trigger('click');
668+
669+
const focusedDate = document.querySelector(`[data-test-id="${now.toLocaleString()}"]`);
670+
671+
expect(focusedDate === document.activeElement).toBeTruthy();
672+
expect(focusedDate.tabIndex).toEqual(0);
619673
});
620674
});
621675

src/js/datepicker.js

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,26 +122,32 @@ function datePicker(datePickerElement, options = {}) {
122122
}
123123

124124
function getDateFromInputs() {
125-
var tempDate;
126-
var inputDates = {
125+
const inputDates = {
127126
day: elements.inputs.day.value,
128127
month: elements.inputs.month.value,
129128
year: elements.inputs.year.value,
130129
};
131130

132-
if (parseInt(inputDates.day, 10) && parseInt(inputDates.month, 10)
133-
&& parseInt(inputDates.year, 10)) {
134-
tempDate = new Date(inputDates.year, inputDates.month, 0);
135-
if (inputDates.month > 12 && inputDates.day > tempDate.getDate()) {
136-
return new Date(inputDates.year, 11, 31);
137-
} else if (inputDates.month > 12) {
138-
return new Date(inputDates.year, 11, inputDates.day);
139-
} else if (inputDates.day > tempDate.getDate()) {
140-
return tempDate;
141-
}
142-
return new Date(inputDates.year, inputDates.month - 1, inputDates.day);
131+
function isValidInput(input) {
132+
const expression = /^\d+$/;
133+
return expression.test(input);
134+
}
135+
136+
function isValidDate(input) {
137+
const date = new Date(input.year, input.month - 1, input.day);
138+
return date.getFullYear() === Number(input.year)
139+
&& date.getMonth() + 1 === Number(input.month)
140+
&& date.getDate() === Number(input.day);
143141
}
144-
return new Date();
142+
143+
if (!(isValidInput(inputDates.day)
144+
&& isValidInput(inputDates.month)
145+
&& isValidInput(inputDates.year)
146+
&& isValidDate(inputDates))) {
147+
return new Date();
148+
}
149+
150+
return new Date(inputDates.year, inputDates.month - 1, inputDates.day);
145151
}
146152

147153
function setInputDate(date) {

0 commit comments

Comments
 (0)