-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #636 from open-formulieren/fix/3755-datetime-valid…
…ation [OF#3755] Datetime validation
- Loading branch information
Showing
5 changed files
with
312 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import set from 'lodash/set'; | ||
|
||
import {validateBoundaries} from './utils'; | ||
|
||
const MinMaxDatetimeValidator = { | ||
key: 'validate.datetimeMinMax', | ||
message(component) { | ||
// In the form builder, this property is called 'minDate'/'maxDate' also in the datetime component | ||
const minDatetime = new Date(component.component.minDate); | ||
const maxDatetime = new Date(component.component.maxDate); | ||
|
||
const errorKeys = | ||
component?.openForms?.validationErrorContext?.minMaxDatetimeValidatorErrorKeys; | ||
const errorMessage = errorKeys ? errorKeys[0] : 'invalidDatetime'; | ||
|
||
return component.t(errorMessage, { | ||
minDatetime: minDatetime, | ||
maxDatetime: maxDatetime, | ||
}); | ||
}, | ||
check(component, setting, value) { | ||
if (!value) return true; | ||
|
||
const {isValid, errorKeys} = validateBoundaries( | ||
component.type, | ||
component.component.datePicker.minDate, | ||
component.component.datePicker.maxDate, | ||
value | ||
); | ||
|
||
if (!isValid) { | ||
set( | ||
component, | ||
'openForms.validationErrorContext.minMaxDatetimeValidatorErrorKeys', | ||
errorKeys | ||
); | ||
} | ||
return isValid; | ||
}, | ||
}; | ||
|
||
export default MinMaxDatetimeValidator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import {parseISO} from 'date-fns'; | ||
|
||
export const validateBoundaries = (componentType, minBoundary, maxBoundary, value) => { | ||
const parsedMinBoundary = minBoundary ? new Date(minBoundary) : null; | ||
const parsedMaxBoundary = maxBoundary ? new Date(maxBoundary) : null; | ||
|
||
if (!parsedMinBoundary && !parsedMaxBoundary) { | ||
return {isValid: true}; | ||
} | ||
|
||
const parsedValue = parseISO(value); | ||
|
||
let errorKeyMinValue, errorKeyMaxValue; | ||
if (componentType === 'date') { | ||
errorKeyMinValue = 'minDate'; | ||
errorKeyMaxValue = 'maxDate'; | ||
} else if (componentType === 'datetime') { | ||
errorKeyMinValue = 'minDatetime'; | ||
errorKeyMaxValue = 'maxDatetime'; | ||
} | ||
|
||
if (parsedMinBoundary && parsedMaxBoundary) { | ||
const isValid = parsedValue >= parsedMinBoundary && parsedValue <= parsedMaxBoundary; | ||
let errorKeys = []; | ||
if (!isValid) { | ||
if (parsedValue < parsedMinBoundary) { | ||
errorKeys.push(errorKeyMinValue); | ||
} else { | ||
errorKeys.push(errorKeyMaxValue); | ||
} | ||
} | ||
return {isValid, errorKeys}; | ||
} | ||
|
||
if (parsedMinBoundary) | ||
return {isValid: parsedValue >= parsedMinBoundary, errorKeys: [errorKeyMinValue]}; | ||
if (parsedMaxBoundary) | ||
return {isValid: parsedValue <= parsedMaxBoundary, errorKeys: [errorKeyMaxValue]}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
import set from 'lodash/set'; | ||
import {Formio} from 'react-formio'; | ||
|
||
import MinMaxDatetimeValidator from 'formio/validators/minMaxDatetimeValidator'; | ||
|
||
const FormioComponent = Formio.Components.components.component; | ||
|
||
describe('Datetime Component', () => { | ||
test('Datetime validator: no min/max datetime', () => { | ||
const component = { | ||
label: 'datetime', | ||
key: 'datetime', | ||
type: 'datetime', | ||
datePicker: { | ||
minDate: null, | ||
maxDate: null, | ||
}, | ||
customOptions: { | ||
allowInvalidPreload: true, | ||
}, | ||
validate: {datetimeMinMax: true}, | ||
}; | ||
|
||
const componentInstance = new FormioComponent(component, {}, {}); | ||
|
||
const isValid = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2020-01-01T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid).toBeTruthy(); | ||
}); | ||
|
||
test('Datetime validator: check min datetime', () => { | ||
const component = { | ||
label: 'datetime', | ||
key: 'datetime', | ||
type: 'datetime', | ||
datePicker: { | ||
minDate: '2023-01-01T10:00:00+01:00', | ||
maxDate: null, | ||
}, | ||
customOptions: { | ||
allowInvalidPreload: true, | ||
}, | ||
validate: {datetimeMinMax: true}, | ||
}; | ||
|
||
const componentInstance = new FormioComponent(component, {}, {}); | ||
|
||
const isValid1 = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2020-01-01T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid1).toBeFalsy(); | ||
expect( | ||
componentInstance.openForms.validationErrorContext.minMaxDatetimeValidatorErrorKeys | ||
).toContain('minDatetime'); | ||
|
||
const isValid2 = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2024-01-01T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid2).toBeTruthy(); | ||
}); | ||
|
||
test('Datetime validator: check max datetime', () => { | ||
const component = { | ||
label: 'datetime', | ||
key: 'datetime', | ||
type: 'datetime', | ||
datePicker: { | ||
minDate: null, | ||
maxDate: '2023-01-01T10:00:00+01:00', | ||
}, | ||
customOptions: { | ||
allowInvalidPreload: true, | ||
}, | ||
validate: {datetimeMinMax: true}, | ||
}; | ||
|
||
const componentInstance = new FormioComponent(component, {}, {}); | ||
|
||
const isValid1 = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2024-01-01T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid1).toBeFalsy(); | ||
expect( | ||
componentInstance.openForms.validationErrorContext.minMaxDatetimeValidatorErrorKeys | ||
).toContain('maxDatetime'); | ||
|
||
const isValid2 = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2020-01-01T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid2).toBeTruthy(); | ||
}); | ||
|
||
test('Datetime validator: check max datetime including the current one', () => { | ||
const component = { | ||
label: 'datetime', | ||
key: 'datetime', | ||
type: 'datetime', | ||
datePicker: { | ||
minDate: null, | ||
maxDate: '2023-09-08T10:00:00+01:00', | ||
}, | ||
customOptions: { | ||
allowInvalidPreload: true, | ||
}, | ||
validate: {datetimeMinMax: true}, | ||
}; | ||
|
||
const componentInstance = new FormioComponent(component, {}, {}); | ||
|
||
const isValid1 = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2023-09-08T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid1).toBeTruthy(); | ||
}); | ||
|
||
test('Datetime validator: error message', () => { | ||
const component = { | ||
label: 'datetime', | ||
key: 'datetime', | ||
type: 'datetime', | ||
datePicker: { | ||
minDate: '2023-09-08T10:00:00+01:00', | ||
maxDate: null, | ||
}, | ||
customOptions: { | ||
allowInvalidPreload: true, | ||
}, | ||
validate: {datetimeMinMax: true}, | ||
}; | ||
|
||
const mockTranslation = jest.fn((message, values) => message); | ||
|
||
const componentInstance = new FormioComponent(component, {}, {}); | ||
componentInstance.t = mockTranslation; | ||
|
||
MinMaxDatetimeValidator.message(componentInstance); | ||
|
||
expect(mockTranslation.mock.calls[0][0]).toEqual('invalidDatetime'); | ||
|
||
set(componentInstance, 'openForms.validationErrorContext.minMaxDatetimeValidatorErrorKeys', [ | ||
'minDatetime', | ||
]); | ||
|
||
MinMaxDatetimeValidator.message(componentInstance); | ||
|
||
expect(mockTranslation.mock.calls[1][0]).toEqual('minDatetime'); | ||
|
||
set(componentInstance, 'openForms.validationErrorContext.minMaxDatetimeValidatorErrorKeys', [ | ||
'maxDatetime', | ||
]); | ||
|
||
MinMaxDatetimeValidator.message(componentInstance); | ||
|
||
expect(mockTranslation.mock.calls[2][0]).toEqual('maxDatetime'); | ||
}); | ||
|
||
test('Datetime validator: check max datetime AND min datetime', () => { | ||
const component = { | ||
label: 'datetime', | ||
key: 'datetime', | ||
type: 'datetime', | ||
datePicker: { | ||
minDate: '2023-09-01T10:00:00+01:00', | ||
maxDate: '2023-09-08T10:00:00+01:00', | ||
}, | ||
customOptions: { | ||
allowInvalidPreload: true, | ||
}, | ||
validate: {datetimeMinMax: true}, | ||
}; | ||
|
||
const componentInstance = new FormioComponent(component, {}, {}); | ||
|
||
const isValid1 = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2024-01-01T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid1).toBeFalsy(); | ||
expect( | ||
componentInstance.openForms.validationErrorContext.minMaxDatetimeValidatorErrorKeys | ||
).toContain('maxDatetime'); | ||
|
||
const isValid2 = MinMaxDatetimeValidator.check( | ||
componentInstance, | ||
{}, | ||
'2020-01-01T10:00:00+01:00' | ||
); | ||
|
||
expect(isValid2).toBeFalsy(); | ||
expect( | ||
componentInstance.openForms.validationErrorContext.minMaxDatetimeValidatorErrorKeys | ||
).toContain('minDatetime'); | ||
}); | ||
}); |