Skip to content

Commit

Permalink
Merge pull request #548 from open-formulieren/fix/3443-date-validation
Browse files Browse the repository at this point in the history
[OF#3443] Date validation
  • Loading branch information
sergei-maertens authored Sep 20, 2023
2 parents 1f47894 + 01cf715 commit 95da438
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/formio/components/DateField.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {Formio} from 'react-formio';

import MinMaxDateValidator from 'formio/validators/minMaxDateValidator';

const DateTimeField = Formio.Components.components.datetime;

const extractDate = value => {
Expand All @@ -11,6 +13,17 @@ const extractDate = value => {
};

class DateField extends DateTimeField {
constructor(component, options, data) {
super(component, options, data);

if (component.datePicker.minDate || component.datePicker.maxDate) {
component.validate.dateMinMax = true;
}

this.validators.push('dateMinMax');
this.validator.validators['dateMinMax'] = MinMaxDateValidator;
}

get suffix() {
// Don't show an icon
return null;
Expand Down
59 changes: 59 additions & 0 deletions src/formio/components/DateField.stories.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import {expect} from '@storybook/jest';
import {userEvent, within} from '@storybook/testing-library';

import {withUtrechtDocument} from 'story-utils/decorators';

import {SingleFormioComponent} from './story-util';
Expand Down Expand Up @@ -38,5 +41,61 @@ export const DateField = {
args: {
key: 'date',
label: 'Datum',
extraComponentProperties: {
format: 'dd-MM-yyyy',
placeholder: 'dd-mm-yyyy',
enableTime: false,
datePicker: {
minDate: null,
maxDate: null,
},
},
},
play: async ({canvasElement}) => {
const canvas = within(canvasElement);

const dateInput = canvas.getByRole('textbox');

userEvent.type(dateInput, '06-06-2006');
await expect(dateInput).toHaveDisplayValue('06-06-2006');

const error = canvas.queryByText('minDate');
await expect(error).toBeNull();
// This test succeeds, but the value is not displayed in storybook... Mystery
},
};

export const DateWithMinField = {
render: SingleFormioComponent,
args: {
key: 'date',
label: 'Datum > 08-09-2023',
extraComponentProperties: {
format: 'dd-MM-yyyy',
placeholder: 'dd-mm-yyyy',
enableTime: false,
datePicker: {
minDate: '2023-09-08',
maxDate: null,
},
customOptions: {
allowInvalidPreload: true,
},
validate: {
dateMinMax: true,
},
},
},
play: async ({canvasElement}) => {
const canvas = within(canvasElement);

const dateInput = canvas.getByRole('textbox');

userEvent.type(dateInput, '06-06-2006');
await expect(dateInput).toHaveDisplayValue('06-06-2006');

// TODO: I cannot get this to work. If you do it manually in storybook, it works... (it shows the error).
// const error = canvas.queryByText('minDate');
// await expect(error).not.toBeNull();
},
};
47 changes: 47 additions & 0 deletions src/formio/validators/minMaxDateValidator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import set from 'lodash/set';

const validateDateBoundaries = (minBoundary, maxBoundary, value) => {
const minDate = minBoundary ? new Date(minBoundary) : null;
const maxDate = maxBoundary ? new Date(maxBoundary) : null;

if (!minDate && !maxDate) {
return {isValid: true};
}

const parsedValue = new Date(value);

if (minDate) return {isValid: parsedValue >= minDate, errorKeys: ['minDate']};
if (maxDate) return {isValid: parsedValue < maxDate, errorKeys: ['maxDate']};
};

const MinMaxDateValidator = {
key: 'validate.dateMinMax',
message(component) {
const minDate = new Date(component.component.minDate);
const maxDate = new Date(component.component.maxDate);

const errorKeys = component?.openForms?.validationErrorContext?.minMaxDateValidatorErrorKeys;
const errorMessage = errorKeys ? errorKeys[0] : 'invalidDate';

return component.t(errorMessage, {
minDate: minDate,
maxDate: maxDate,
});
},
check(component, setting, value) {
if (!value) return true;

const {isValid, errorKeys} = validateDateBoundaries(
component.component.datePicker.minDate,
component.component.datePicker.maxDate,
value
);

if (!isValid) {
set(component, 'openForms.validationErrorContext.minMaxDateValidatorErrorKeys', errorKeys);
}
return isValid;
},
};

export default MinMaxDateValidator;

0 comments on commit 95da438

Please sign in to comment.