AAE-23116 Dropdown should not display errors / call apis when it's in readOnly state [without refactor] (#9800)

* AAE-23116 Add tests for dropdown widget

* AAE-23116 Update form-field.model

* AAE-23116 Final

* AAE-23116 Restore formatting

* AAE-23116 Align with comments

* AAE-23116 Update

* AAE-23116 Fix process-services-cloud unit tests

* AAE-23116 Fix process services unit tests

* AAE-23116 Fix for core unit tests
This commit is contained in:
Wiktor Danielewski
2024-06-21 08:50:55 +02:00
committed by GitHub
parent 328d233b05
commit 4d2c489508
7 changed files with 395 additions and 344 deletions

View File

@@ -52,20 +52,20 @@ describe('FormFieldValidator', () => {
});
field.required = false;
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.validate(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(false);
expect(validator.validate(field)).toBe(true);
field.required = true;
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.validate(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
expect(validator.validate(field)).toBe(true);
});
it('should skip unsupported type', () => {
const field = new FormFieldModel(new FormModel(), { type: 'wrong-type' });
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for dropdown with empty value', () => {
it('should fail (display error) for dropdown with empty value', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: '<empty>',
@@ -75,29 +75,34 @@ describe('FormFieldValidator', () => {
});
field.emptyOption = { id: '<empty>' } as FormFieldOption;
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
field.value = '<non-empty>';
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for dropdown with zero selection', () => {
it('should fail (display error) for multiple type dropdown with zero selection', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: [],
hasEmptyValue: true,
value: [{ id: 'id_cat', name: 'Cat' }],
required: true,
selectionType: 'multiple'
selectionType: 'multiple',
hasEmptyValue: false,
options: [
{ id: 'id_cat', name: 'Cat' },
{ id: 'id_dog', name: 'Dog' }
]
});
field.emptyOption = { id: 'empty' } as FormFieldOption;
expect(validator.validate(field)).toBeFalsy();
const validateBeforeUnselect = validator.validate(field);
field.value = [];
expect(validator.validate(field)).toBe(false);
const validateAfterUnselect = validator.validate(field);
expect(validateBeforeUnselect).toBe(true);
expect(validateAfterUnselect).toBe(false);
});
it('should fail for dropdown with null value', () => {
it('should fail (display error) for dropdown with null value', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: null,
@@ -109,7 +114,7 @@ describe('FormFieldValidator', () => {
expect(validator.validate(field)).toBe(false);
});
it('should fail for dropdown with empty object', () => {
it('should fail (display error) for dropdown with empty object', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
value: {},
@@ -121,7 +126,7 @@ describe('FormFieldValidator', () => {
expect(validator.validate(field)).toBe(false);
});
it('should fail for radio buttons', () => {
it('should fail (display error) for radio buttons', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.RADIO_BUTTONS,
required: true,
@@ -129,7 +134,7 @@ describe('FormFieldValidator', () => {
});
field.value = 'one';
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
});
it('should succeed for radio buttons', () => {
@@ -140,10 +145,10 @@ describe('FormFieldValidator', () => {
options: [{ id: 'two', name: 'two' }]
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for upload', () => {
it('should fail (display error) for upload', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: null,
@@ -151,10 +156,10 @@ describe('FormFieldValidator', () => {
});
field.value = null;
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
field.value = [];
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
});
it('should succeed for upload', () => {
@@ -164,10 +169,10 @@ describe('FormFieldValidator', () => {
required: true
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for text', () => {
it('should fail (display error) for text', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TEXT,
value: null,
@@ -175,10 +180,10 @@ describe('FormFieldValidator', () => {
});
field.value = null;
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
field.value = '';
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
});
it('should succeed for date', () => {
@@ -188,10 +193,10 @@ describe('FormFieldValidator', () => {
required: true
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for date', () => {
it('should fail (display error) for date', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATE,
value: null,
@@ -199,10 +204,10 @@ describe('FormFieldValidator', () => {
});
field.value = null;
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
field.value = '';
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
});
it('should succeed for text', () => {
@@ -212,7 +217,7 @@ describe('FormFieldValidator', () => {
required: true
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for check box', () => {
@@ -223,10 +228,10 @@ describe('FormFieldValidator', () => {
options: [{ id: 'two', name: 'two' }]
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for check box', () => {
it('should fail (display error) for check box', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.BOOLEAN,
required: true,
@@ -235,7 +240,7 @@ describe('FormFieldValidator', () => {
});
field.value = false;
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
});
});
@@ -247,20 +252,20 @@ describe('FormFieldValidator', () => {
});
it('should verify number', () => {
expect(NumberFieldValidator.isNumber('1')).toBeTruthy();
expect(NumberFieldValidator.isNumber('1.0')).toBeTruthy();
expect(NumberFieldValidator.isNumber('-1')).toBeTruthy();
expect(NumberFieldValidator.isNumber(1)).toBeTruthy();
expect(NumberFieldValidator.isNumber(0)).toBeTruthy();
expect(NumberFieldValidator.isNumber(-1)).toBeTruthy();
expect(NumberFieldValidator.isNumber('1')).toBe(true);
expect(NumberFieldValidator.isNumber('1.0')).toBe(true);
expect(NumberFieldValidator.isNumber('-1')).toBe(true);
expect(NumberFieldValidator.isNumber(1)).toBe(true);
expect(NumberFieldValidator.isNumber(0)).toBe(true);
expect(NumberFieldValidator.isNumber(-1)).toBe(true);
});
it('should not verify number', () => {
expect(NumberFieldValidator.isNumber(null)).toBeFalsy();
expect(NumberFieldValidator.isNumber(undefined)).toBeFalsy();
expect(NumberFieldValidator.isNumber('')).toBeFalsy();
expect(NumberFieldValidator.isNumber('one')).toBeFalsy();
expect(NumberFieldValidator.isNumber('1q')).toBeFalsy();
expect(NumberFieldValidator.isNumber(null)).toBe(false);
expect(NumberFieldValidator.isNumber(undefined)).toBe(false);
expect(NumberFieldValidator.isNumber('')).toBe(false);
expect(NumberFieldValidator.isNumber('one')).toBe(false);
expect(NumberFieldValidator.isNumber('1q')).toBe(false);
});
it('should allow empty number value', () => {
@@ -269,7 +274,7 @@ describe('FormFieldValidator', () => {
value: null
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should allow number value', () => {
@@ -278,7 +283,7 @@ describe('FormFieldValidator', () => {
value: 44
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should allow zero number value', () => {
@@ -287,17 +292,17 @@ describe('FormFieldValidator', () => {
value: 0
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for wrong number value', () => {
it('should fail (display error) for wrong number value', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.NUMBER,
value: '<value>'
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -314,10 +319,10 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.minLength = 10;
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should allow empty values', () => {
@@ -327,7 +332,7 @@ describe('FormFieldValidator', () => {
value: null
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed text validation', () => {
@@ -337,10 +342,10 @@ describe('FormFieldValidator', () => {
value: '1234'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail text validation', () => {
it('should fail (display error) text validation', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TEXT,
minLength: 3,
@@ -348,7 +353,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -365,10 +370,10 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.maxLength = 10;
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should allow empty values', () => {
@@ -378,7 +383,7 @@ describe('FormFieldValidator', () => {
value: null
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed text validation', () => {
@@ -388,10 +393,10 @@ describe('FormFieldValidator', () => {
value: '123'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail text validation', () => {
it('should fail (display error) text validation', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TEXT,
maxLength: 3,
@@ -399,7 +404,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -415,10 +420,10 @@ describe('FormFieldValidator', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.NUMBER
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.minValue = '1';
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should support numeric widgets only', () => {
@@ -427,10 +432,10 @@ describe('FormFieldValidator', () => {
minValue: '1'
});
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
field.type = FormFieldTypes.TEXT;
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
});
it('should allow empty values', () => {
@@ -440,7 +445,7 @@ describe('FormFieldValidator', () => {
minValue: '1'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for unsupported types', () => {
@@ -448,7 +453,7 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed validating value', () => {
@@ -458,10 +463,10 @@ describe('FormFieldValidator', () => {
minValue: '10'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating value', () => {
it('should fail (display error) validating value', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.NUMBER,
value: '9',
@@ -469,7 +474,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -485,10 +490,10 @@ describe('FormFieldValidator', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.NUMBER
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.maxValue = '1';
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should support numeric widgets only', () => {
@@ -497,10 +502,10 @@ describe('FormFieldValidator', () => {
maxValue: '1'
});
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
field.type = FormFieldTypes.TEXT;
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
});
it('should allow empty values', () => {
@@ -510,7 +515,7 @@ describe('FormFieldValidator', () => {
maxValue: '1'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for unsupported types', () => {
@@ -518,7 +523,7 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed validating value', () => {
@@ -528,10 +533,10 @@ describe('FormFieldValidator', () => {
maxValue: '10'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating value', () => {
it('should fail (display error) validating value', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.NUMBER,
value: '11',
@@ -539,7 +544,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -555,10 +560,10 @@ describe('FormFieldValidator', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TEXT
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.regexPattern = '<pattern>';
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should allow empty values', () => {
@@ -568,7 +573,7 @@ describe('FormFieldValidator', () => {
regexPattern: 'pattern'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should allow empty string values', () => {
@@ -578,7 +583,7 @@ describe('FormFieldValidator', () => {
regexPattern: 'pattern'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed validating regex', () => {
@@ -588,17 +593,17 @@ describe('FormFieldValidator', () => {
regexPattern: 'pattern'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating regex', () => {
it('should fail (display error) validating regex', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TEXT,
value: 'some value',
regexPattern: 'pattern'
});
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
});
});
@@ -613,13 +618,13 @@ describe('FormFieldValidator', () => {
let field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TEXT
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TYPEAHEAD
});
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should allow empty values', () => {
@@ -629,7 +634,7 @@ describe('FormFieldValidator', () => {
regexPattern: 'pattern'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for a valid input value in options', () => {
@@ -642,10 +647,10 @@ describe('FormFieldValidator', () => {
]
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail for an invalid input value in options', () => {
it('should fail (display error) for an invalid input value in options', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.TYPEAHEAD,
value: 'Lean',
@@ -655,7 +660,7 @@ describe('FormFieldValidator', () => {
]
});
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
});
});
@@ -670,10 +675,10 @@ describe('FormFieldValidator', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATETIME
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.maxValue = '9999-02-08 10:10 AM';
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should support date time widgets only', () => {
@@ -682,10 +687,10 @@ describe('FormFieldValidator', () => {
maxValue: '9999-02-08 10:10 AM'
});
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
field.type = FormFieldTypes.TEXT;
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
});
it('should allow empty values', () => {
@@ -695,7 +700,7 @@ describe('FormFieldValidator', () => {
maxValue: '9999-02-08 10:10 AM'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for unsupported types', () => {
@@ -703,10 +708,10 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should take into account that max value is in UTC and NOT fail validating value checking the time', () => {
it('should take into account that max value is in UTC and NOT fail (display error) validating value checking the time', () => {
const localValidValue = '2018-03-30T22:59:00.000Z';
const field = new FormFieldModel(new FormModel(), {
@@ -715,10 +720,10 @@ describe('FormFieldValidator', () => {
maxValue: '2018-03-31T23:00:00.000Z'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should take into account that max value is in UTC and fail validating value checking the time', () => {
it('should take into account that max value is in UTC and fail (display error) validating value checking the time', () => {
const localInvalidValue = '2018-03-30T23:01:00.000Z';
const field = new FormFieldModel(new FormModel(), {
@@ -728,7 +733,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
expect(field.validationSummary.message).toBe('FORM.FIELD.VALIDATOR.NOT_GREATER_THAN');
});
@@ -740,10 +745,10 @@ describe('FormFieldValidator', () => {
maxValue: '9999-02-08T10:10:00.000Z'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating value checking the time', () => {
it('should fail (display error) validating value checking the time', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATETIME,
value: '9999-02-08T11:10:00.000Z',
@@ -751,7 +756,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
@@ -762,10 +767,10 @@ describe('FormFieldValidator', () => {
maxValue: '9999-02-08T10:10:00.000Z'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating value checking the date', () => {
it('should fail (display error) validating value checking the date', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATETIME,
value: '08-02-9999 12:10 AM',
@@ -773,7 +778,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -789,10 +794,10 @@ describe('FormFieldValidator', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATETIME
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.minValue = '9999-02-08 09:10 AM';
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should support date time widgets only', () => {
@@ -801,10 +806,10 @@ describe('FormFieldValidator', () => {
minValue: '9999-02-08 09:10 AM'
});
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
field.type = FormFieldTypes.TEXT;
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
});
it('should allow empty values', () => {
@@ -814,7 +819,7 @@ describe('FormFieldValidator', () => {
minValue: '9999-02-08 09:10 AM'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for unsupported types', () => {
@@ -822,10 +827,10 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should take into account that min value is in UTC and NOT fail validating value checking the time', () => {
it('should take into account that min value is in UTC and NOT fail (display error) validating value checking the time', () => {
const localValidValue = '2018-03-02T06:01:00.000Z';
const field = new FormFieldModel(new FormModel(), {
@@ -834,10 +839,10 @@ describe('FormFieldValidator', () => {
minValue: '2018-03-02T06:00:00.000Z'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should take into account that min value is in UTC and fail validating value checking the time', () => {
it('should take into account that min value is in UTC and fail (display error) validating value checking the time', () => {
const localInvalidValue = '2018-3-02 05:59 AM';
const field = new FormFieldModel(new FormModel(), {
@@ -847,7 +852,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
expect(field.validationSummary.message).toBe('FORM.FIELD.VALIDATOR.NOT_LESS_THAN');
});
@@ -859,7 +864,7 @@ describe('FormFieldValidator', () => {
minValue: '9999-02-08 09:00 AM'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed validating value by date', () => {
@@ -869,10 +874,10 @@ describe('FormFieldValidator', () => {
minValue: '9999-02-08 09:10 AM'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating value by time', () => {
it('should fail (display error) validating value by time', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATETIME,
value: '9999-08-02T08:10:00.000Z',
@@ -880,11 +885,11 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
it('should fail validating value by date', () => {
it('should fail (display error) validating value by date', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATETIME,
value: '9999-02-07T09:10:00.000Z',
@@ -892,7 +897,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -908,10 +913,10 @@ describe('FormFieldValidator', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATE
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.maxValue = '9999-02-08';
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should support date widgets only', () => {
@@ -920,10 +925,10 @@ describe('FormFieldValidator', () => {
maxValue: '9999-02-08'
});
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
field.type = FormFieldTypes.TEXT;
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
});
it('should allow empty values', () => {
@@ -933,7 +938,7 @@ describe('FormFieldValidator', () => {
maxValue: '9999-02-08'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for unsupported types', () => {
@@ -941,7 +946,7 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed validating value checking the date', () => {
@@ -951,10 +956,10 @@ describe('FormFieldValidator', () => {
maxValue: '9999-02-09'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating value checking the date', () => {
it('should fail (display error) validating value checking the date', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATE,
value: '9999-02-08T00:00:00',
@@ -962,7 +967,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
@@ -973,10 +978,10 @@ describe('FormFieldValidator', () => {
maxValue: '09-02-9999'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating with APS1 format', () => {
it('should fail (display error) validating with APS1 format', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATE,
value: '9999-02-08T00:00:00',
@@ -984,7 +989,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -1000,10 +1005,10 @@ describe('FormFieldValidator', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATE
});
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
field.minValue = '9999-02-08';
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
});
it('should support date widgets only', () => {
@@ -1012,10 +1017,10 @@ describe('FormFieldValidator', () => {
minValue: '9999-02-08'
});
expect(validator.isSupported(field)).toBeTruthy();
expect(validator.isSupported(field)).toBe(true);
field.type = FormFieldTypes.TEXT;
expect(validator.isSupported(field)).toBeFalsy();
expect(validator.isSupported(field)).toBe(false);
});
it('should allow empty values', () => {
@@ -1025,7 +1030,7 @@ describe('FormFieldValidator', () => {
minValue: '9999-02-08'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed for unsupported types', () => {
@@ -1033,7 +1038,7 @@ describe('FormFieldValidator', () => {
type: FormFieldTypes.TEXT
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should succeed validating value checking the date', () => {
@@ -1043,10 +1048,10 @@ describe('FormFieldValidator', () => {
minValue: '9999-02-07'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating value checking the date', () => {
it('should fail (display error) validating value checking the date', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATE,
value: '9999-02-08T00:00:00',
@@ -1054,7 +1059,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
@@ -1065,10 +1070,10 @@ describe('FormFieldValidator', () => {
minValue: '07-02-9999'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should fail validating with APS1 format', () => {
it('should fail (display error) validating with APS1 format', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DATE,
value: '9999-02-08T00:00:00',
@@ -1076,7 +1081,7 @@ describe('FormFieldValidator', () => {
});
field.validationSummary = new ErrorMessageModel();
expect(validator.validate(field)).toBeFalsy();
expect(validator.validate(field)).toBe(false);
expect(field.validationSummary).not.toBeNull();
});
});
@@ -1095,7 +1100,7 @@ describe('FormFieldValidator', () => {
dateDisplayFormat: 'YYYY-MM-DD HH:mm'
});
expect(validator.validate(field)).toBeTruthy();
expect(validator.validate(field)).toBe(true);
});
it('should validate dateTime format with default format', () => {
@@ -1105,7 +1110,7 @@ describe('FormFieldValidator', () => {
});
expect(field.value).toBe('9-6-2021 11:10 AM');
expect(field.dateDisplayFormat).toBe('D-M-YYYY hh:mm A');
expect(validator.validate(field)).toBeTrue();
expect(validator.validate(field)).toBe(true);
});
it('should not validate dateTime format with default format', () => {
@@ -1115,7 +1120,7 @@ describe('FormFieldValidator', () => {
});
expect(field.value).toBe('2021-06-09 14:10 AM');
expect(field.dateDisplayFormat).toBe('D-M-YYYY hh:mm A');
expect(validator.validate(field)).toBeFalse();
expect(validator.validate(field)).toBe(false);
});
});
@@ -1133,7 +1138,7 @@ describe('FormFieldValidator', () => {
precision: 2
});
expect(decimalValidator.validate(field)).toBeTrue();
expect(decimalValidator.validate(field)).toBe(true);
});
it('should return true when value is of lower precision', () => {
@@ -1143,7 +1148,7 @@ describe('FormFieldValidator', () => {
precision: 2
});
expect(decimalValidator.validate(field)).toBeTrue();
expect(decimalValidator.validate(field)).toBe(true);
});
it('should return false when value is of higher precision', () => {
@@ -1153,7 +1158,7 @@ describe('FormFieldValidator', () => {
precision: 1
});
expect(decimalValidator.validate(field)).toBeFalse();
expect(decimalValidator.validate(field)).toBe(false);
});
it('should validate decimal of wrong precision when value is of type string', () => {
@@ -1163,7 +1168,7 @@ describe('FormFieldValidator', () => {
precision: 1
});
expect(decimalValidator.validate(field)).toBeFalse();
expect(decimalValidator.validate(field)).toBe(false);
});
it('should return false, when value is a negative number and of correct precission', () => {
@@ -1173,7 +1178,7 @@ describe('FormFieldValidator', () => {
precision: 1
});
expect(decimalValidator.validate(field)).toBeFalse();
expect(decimalValidator.validate(field)).toBe(false);
});
it('should return true, when value is a positive number and of correct precission', () => {
@@ -1183,8 +1188,7 @@ describe('FormFieldValidator', () => {
precision: 3
});
expect(decimalValidator.validate(field)).toBeTrue();
expect(decimalValidator.validate(field)).toBe(true);
});
});
});

View File

@@ -24,15 +24,11 @@ import { DateFnsUtils } from '../../../../common/utils/date-fns-utils';
import { isValid as isDateValid, isBefore, isAfter } from 'date-fns';
export interface FormFieldValidator {
isSupported(field: FormFieldModel): boolean;
validate(field: FormFieldModel): boolean;
}
export class RequiredFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.TEXT,
FormFieldTypes.MULTILINE_TEXT,
@@ -54,14 +50,11 @@ export class RequiredFieldValidator implements FormFieldValidator {
];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 &&
field.required;
return field && this.supportedTypes.indexOf(field.type) > -1 && field.required;
}
validate(field: FormFieldModel): boolean {
if (this.isSupported(field) && field.isVisible) {
if (field.type === FormFieldTypes.DROPDOWN) {
if (field.hasMultipleValues) {
return Array.isArray(field.value) && !!field.value.length;
@@ -73,7 +66,7 @@ export class RequiredFieldValidator implements FormFieldValidator {
}
}
if (field.required && typeof field.value === 'object' && field.value && !Object.keys(field.value).length) {
if (field.required && field.value && typeof field.value === 'object' && !Object.keys(field.value).length) {
return false;
}
}
@@ -84,11 +77,11 @@ export class RequiredFieldValidator implements FormFieldValidator {
}
if (field.type === FormFieldTypes.UPLOAD) {
return field.value && field.value.length > 0;
return !!field.value && field.value.length > 0;
}
if (field.type === FormFieldTypes.DYNAMIC_TABLE) {
return field.value && field.value instanceof Array && field.value.length > 0;
return !!field.value && field.value instanceof Array && field.value.length > 0;
}
if (field.type === FormFieldTypes.BOOLEAN) {
@@ -101,15 +94,10 @@ export class RequiredFieldValidator implements FormFieldValidator {
}
return true;
}
}
export class NumberFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.NUMBER,
FormFieldTypes.AMOUNT
];
private supportedTypes = [FormFieldTypes.NUMBER, FormFieldTypes.AMOUNT];
static isNumber(value: any): boolean {
return isNumberValue(value);
@@ -121,9 +109,7 @@ export class NumberFieldValidator implements FormFieldValidator {
validate(field: FormFieldModel): boolean {
if (this.isSupported(field) && field.isVisible) {
if (field.value === null ||
field.value === undefined ||
field.value === '') {
if (field.value === null || field.value === undefined || field.value === '') {
return true;
}
const valueStr = '' + field.value;
@@ -142,10 +128,7 @@ export class NumberFieldValidator implements FormFieldValidator {
}
export class DateFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.DATE
];
private supportedTypes = [FormFieldTypes.DATE];
// Validates that the input string is a valid date formatted as <dateFormat> (default D-M-YYYY)
static isValidDate(inputDate: string, dateFormat: string = 'D-M-YYYY'): boolean {
@@ -169,10 +152,7 @@ export class DateFieldValidator implements FormFieldValidator {
}
export class DateTimeFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.DATETIME
];
private supportedTypes = [FormFieldTypes.DATETIME];
isSupported(field: FormFieldModel): boolean {
return field && this.supportedTypes.indexOf(field.type) > -1;
@@ -196,13 +176,10 @@ export class DateTimeFieldValidator implements FormFieldValidator {
}
export abstract class BoundaryDateFieldValidator implements FormFieldValidator {
DATE_FORMAT_CLOUD = 'YYYY-MM-DD';
DATE_FORMAT = 'DD-MM-YYYY';
supportedTypes = [
FormFieldTypes.DATE
];
supportedTypes = [FormFieldTypes.DATE];
validate(field: FormFieldModel): boolean {
let isValid = true;
@@ -226,11 +203,9 @@ export abstract class BoundaryDateFieldValidator implements FormFieldValidator {
abstract checkDate(field: FormFieldModel, dateFormat: string);
abstract isSupported(field: FormFieldModel);
}
export class MinDateFieldValidator extends BoundaryDateFieldValidator {
checkDate(field: FormFieldModel, dateFormat: string): boolean {
let isValid = true;
const fieldValueData = DateFnsUtils.parseDate(field.value, dateFormat, { dateOnly: true });
@@ -239,23 +214,18 @@ export class MinDateFieldValidator extends BoundaryDateFieldValidator {
if (DateFnsUtils.isBeforeDate(fieldValueData, min)) {
field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`;
field.validationSummary.attributes.set(
'minValue',
DateFnsUtils.formatDate(min, field.dateDisplayFormat).toLocaleUpperCase()
);
field.validationSummary.attributes.set('minValue', DateFnsUtils.formatDate(min, field.dateDisplayFormat).toLocaleUpperCase());
isValid = false;
}
return isValid;
}
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 && !!field.minValue;
return field && this.supportedTypes.indexOf(field.type) > -1 && !!field.minValue;
}
}
export class MaxDateFieldValidator extends BoundaryDateFieldValidator {
checkDate(field: FormFieldModel, dateFormat: string): boolean {
let isValid = true;
const fieldValueData = DateFnsUtils.parseDate(field.value, dateFormat, { dateOnly: true });
@@ -264,18 +234,14 @@ export class MaxDateFieldValidator extends BoundaryDateFieldValidator {
if (DateFnsUtils.isAfterDate(fieldValueData, max)) {
field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`;
field.validationSummary.attributes.set(
'maxValue',
DateFnsUtils.formatDate(max, field.dateDisplayFormat).toLocaleUpperCase()
);
field.validationSummary.attributes.set('maxValue', DateFnsUtils.formatDate(max, field.dateDisplayFormat).toLocaleUpperCase());
isValid = false;
}
return isValid;
}
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 && !!field.maxValue;
return field && this.supportedTypes.indexOf(field.type) > -1 && !!field.maxValue;
}
}
@@ -288,14 +254,10 @@ export class MaxDateFieldValidator extends BoundaryDateFieldValidator {
*
*/
export class MinDateTimeFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.DATETIME
];
private supportedTypes = [FormFieldTypes.DATETIME];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 && !!field.minValue;
return field && this.supportedTypes.indexOf(field.type) > -1 && !!field.minValue;
}
validate(field: FormFieldModel): boolean {
@@ -318,10 +280,7 @@ export class MinDateTimeFieldValidator implements FormFieldValidator {
if (isBefore(fieldValueDate, min)) {
field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`;
field.validationSummary.attributes.set(
'minValue',
DateFnsUtils.formatDate(min, field.dateDisplayFormat).replace(':', '-')
);
field.validationSummary.attributes.set('minValue', DateFnsUtils.formatDate(min, field.dateDisplayFormat).replace(':', '-'));
isValid = false;
}
return isValid;
@@ -337,14 +296,10 @@ export class MinDateTimeFieldValidator implements FormFieldValidator {
*
*/
export class MaxDateTimeFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.DATETIME
];
private supportedTypes = [FormFieldTypes.DATETIME];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 && !!field.maxValue;
return field && this.supportedTypes.indexOf(field.type) > -1 && !!field.maxValue;
}
validate(field: FormFieldModel): boolean {
@@ -367,10 +322,7 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator {
if (isAfter(fieldValueDate, max)) {
field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`;
field.validationSummary.attributes.set(
'maxValue',
DateFnsUtils.formatDate(max, field.dateDisplayFormat).replace(':', '-')
);
field.validationSummary.attributes.set('maxValue', DateFnsUtils.formatDate(max, field.dateDisplayFormat).replace(':', '-'));
isValid = false;
}
return isValid;
@@ -378,16 +330,10 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator {
}
export class MinLengthFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.TEXT,
FormFieldTypes.MULTILINE_TEXT
];
private supportedTypes = [FormFieldTypes.TEXT, FormFieldTypes.MULTILINE_TEXT];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 &&
field.minLength > 0;
return field && this.supportedTypes.indexOf(field.type) > -1 && field.minLength > 0;
}
validate(field: FormFieldModel): boolean {
@@ -404,16 +350,10 @@ export class MinLengthFieldValidator implements FormFieldValidator {
}
export class MaxLengthFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.TEXT,
FormFieldTypes.MULTILINE_TEXT
];
private supportedTypes = [FormFieldTypes.TEXT, FormFieldTypes.MULTILINE_TEXT];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 &&
field.maxLength > 0;
return field && this.supportedTypes.indexOf(field.type) > -1 && field.maxLength > 0;
}
validate(field: FormFieldModel): boolean {
@@ -430,17 +370,10 @@ export class MaxLengthFieldValidator implements FormFieldValidator {
}
export class MinValueFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.NUMBER,
FormFieldTypes.DECIMAL,
FormFieldTypes.AMOUNT
];
private supportedTypes = [FormFieldTypes.NUMBER, FormFieldTypes.DECIMAL, FormFieldTypes.AMOUNT];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 &&
NumberFieldValidator.isNumber(field.minValue);
return field && this.supportedTypes.indexOf(field.type) > -1 && NumberFieldValidator.isNumber(field.minValue);
}
validate(field: FormFieldModel): boolean {
@@ -461,17 +394,10 @@ export class MinValueFieldValidator implements FormFieldValidator {
}
export class MaxValueFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.NUMBER,
FormFieldTypes.DECIMAL,
FormFieldTypes.AMOUNT
];
private supportedTypes = [FormFieldTypes.NUMBER, FormFieldTypes.DECIMAL, FormFieldTypes.AMOUNT];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 &&
NumberFieldValidator.isNumber(field.maxValue);
return field && this.supportedTypes.indexOf(field.type) > -1 && NumberFieldValidator.isNumber(field.maxValue);
}
validate(field: FormFieldModel): boolean {
@@ -492,15 +418,10 @@ export class MaxValueFieldValidator implements FormFieldValidator {
}
export class RegExFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.TEXT,
FormFieldTypes.MULTILINE_TEXT
];
private supportedTypes = [FormFieldTypes.TEXT, FormFieldTypes.MULTILINE_TEXT];
isSupported(field: FormFieldModel): boolean {
return field &&
this.supportedTypes.indexOf(field.type) > -1 && !!field.regexPattern;
return field && this.supportedTypes.indexOf(field.type) > -1 && !!field.regexPattern;
}
validate(field: FormFieldModel): boolean {
@@ -513,14 +434,10 @@ export class RegExFieldValidator implements FormFieldValidator {
}
return true;
}
}
export class FixedValueFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.TYPEAHEAD
];
private supportedTypes = [FormFieldTypes.TYPEAHEAD];
isSupported(field: FormFieldModel): boolean {
return field && this.supportedTypes.indexOf(field.type) > -1;
@@ -558,10 +475,7 @@ export class FixedValueFieldValidator implements FormFieldValidator {
}
export class DecimalFieldValidator implements FormFieldValidator {
private supportedTypes = [
FormFieldTypes.DECIMAL
];
private supportedTypes = [FormFieldTypes.DECIMAL];
isSupported(field: FormFieldModel): boolean {
return field && this.supportedTypes.indexOf(field.type) > -1 && !!field.value;

View File

@@ -60,7 +60,7 @@ describe('FormFieldModel', () => {
};
const field = new FormFieldModel(new FormModel(), json);
Object.keys(json).forEach((key) => {
expect(field[key]).toBe(json[key]);
expect(field[key]).toEqual(json[key]);
});
});
@@ -122,6 +122,59 @@ describe('FormFieldModel', () => {
expect(field.value).toBe('deferred');
});
it('should add value to field options if NOT present', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [],
value: { id: 'id_one', name: 'One' }
});
expect(field.options).toEqual([{ id: 'id_one', name: 'One' }]);
expect(field.value).toEqual('id_one');
});
it('should assign "empty" option as value if value is null and "empty" option is present in options', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [
{ id: 'empty', name: 'Chose one...' },
{ id: 'one', name: 'One' }
],
value: null
});
expect(field.hasEmptyValue).toBe(true);
expect(field.emptyOption).toEqual({ id: 'empty', name: 'Chose one...' });
expect(field.value).toEqual('empty');
});
it('should set hasEmptyValue to true if "empty" option is present in options', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [{ id: 'empty', name: 'Choose one...' }],
value: null
});
expect(field.hasEmptyValue).toBe(true);
expect(field.emptyOption).toEqual({ id: 'empty', name: 'Choose one...' });
});
it('should add default "empty" option to the options if hasEmptyValue is true but "empty" option is not present', () => {
const field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.DROPDOWN,
options: [{ id: 'one', name: 'One' }],
value: null,
hasEmptyValue: true
});
expect(field.hasEmptyValue).toBe(true);
expect(field.emptyOption).toEqual({ id: 'empty', name: 'Choose one...' });
expect(field.options).toEqual([
{ id: 'empty', name: 'Choose one...' },
{ id: 'one', name: 'One' }
]);
});
it('should parse the date with the default format (D-M-YYYY) if the display format is missing', () => {
const form = new FormModel();
const field = new FormFieldModel(form, {

View File

@@ -40,6 +40,8 @@ export class FormFieldModel extends FormWidgetModel {
readonly defaultDateFormat: string = 'D-M-YYYY';
readonly defaultDateTimeFormat: string = 'D-M-YYYY hh:mm A';
private readonly defaultEmptyOptionId = 'empty';
private readonly defaultEmptyOptionName = 'Choose one...';
// model members
fieldType: string;
@@ -187,8 +189,9 @@ export class FormFieldModel extends FormWidgetModel {
this.maxDateRangeValue = json.maxDateRangeValue;
this.dynamicDateRangeSelection = json.dynamicDateRangeSelection;
this.regexPattern = json.regexPattern;
this.options = json.options || [];
this.hasEmptyValue = json.hasEmptyValue;
this.options = this.parseValidOptions(json.options);
this.emptyOption = this.getEmptyOption(this.options);
this.hasEmptyValue = json?.hasEmptyValue ?? !!this.emptyOption;
this.className = json.className;
this.optionType = json.optionType;
this.params = json.params || {};
@@ -198,7 +201,6 @@ export class FormFieldModel extends FormWidgetModel {
this.enableFractions = json.enableFractions;
this.currency = json.currency;
this.dateDisplayFormat = json.dateDisplayFormat || this.getDefaultDateFormat(json);
this._value = this.parseValue(json);
this.validationSummary = new ErrorMessageModel();
this.tooltip = json.tooltip;
this.selectionType = json.selectionType;
@@ -210,6 +212,7 @@ export class FormFieldModel extends FormWidgetModel {
this.schemaDefinition = json.schemaDefinition;
this.precision = json.precision;
this.externalProperty = json.externalProperty;
this._value = this.parseValue(json);
if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') {
this.placeholder = json.placeholder;
@@ -230,18 +233,13 @@ export class FormFieldModel extends FormWidgetModel {
this.leftLabels = form.json.leftLabels || false;
}
const emptyOption = Array.isArray(this.options) ? this.options.find(({ id }) => id === 'empty') : undefined;
if (this.hasEmptyValue === undefined) {
this.hasEmptyValue = json?.hasEmptyValue ?? !!emptyOption;
}
if (this.options && this.options.length > 0 && this.hasEmptyValue) {
this.emptyOption = emptyOption;
}
this.updateForm();
}
private getEmptyOption(options: FormFieldOption[]): FormFieldOption {
return options.find((option) => option?.id === this.defaultEmptyOptionId);
}
private setValueForReadonlyType(form: any) {
const value = this.getProcessVariableValue(this.params.field, form);
if (value) {
@@ -308,22 +306,34 @@ export class FormFieldModel extends FormWidgetModel {
but saving back as object: { id: <id>, name: <name> }
*/
if (json.type === FormFieldTypes.DROPDOWN) {
if (json.options) {
if (json.hasEmptyValue) {
const emptyOption = json.options[0];
if (value === '' || value === emptyOption.id || value === emptyOption.name) {
value = emptyOption.id;
}
} else {
if (value?.id && value?.name) {
value = value.id;
if (this.hasEmptyValue) {
if (!this.emptyOption) {
this.emptyOption = {
id: this.defaultEmptyOptionId,
name: this.defaultEmptyOptionName
};
this.options.unshift(this.emptyOption);
}
const isEmptyValue = !value || [this.emptyOption.id, this.emptyOption.name].includes(value);
if (isEmptyValue) {
return this.emptyOption.id;
}
}
if (this.hasMultipleValues) {
value = Array.isArray(json.value) ? json.value : [];
if (this.isValidOption(value)) {
this.addOption(value);
return value.id;
}
if (this.hasMultipleValues) {
const validSelectedOptions = (Array.isArray(json.value) ? json.value : []).filter((option) => this.isValidOption(option));
this.addOptions(validSelectedOptions);
return validSelectedOptions;
}
return value;
}
/*
@@ -337,9 +347,8 @@ export class FormFieldModel extends FormWidgetModel {
const entry: FormFieldOption[] = this.options.filter(
(opt) => opt.id === value || opt.name === value || (value && (opt.id === value.id || opt.name === value.name))
);
if (entry.length > 0) {
value = entry[0].id;
}
return entry.length > 0 ? entry[0].id : value;
}
/*
@@ -359,13 +368,15 @@ export class FormFieldModel extends FormWidgetModel {
}
if (isValidDate(dateValue)) {
value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat);
}
return DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat);
}
}
return value;
}
if (this.isCheckboxField(json)) {
value = json.value === 'true' || json.value === true;
return json.value === 'true' || json.value === true;
}
return value;
@@ -511,6 +522,29 @@ export class FormFieldModel extends FormWidgetModel {
return this.options?.length > 0;
}
isEmptyValueOption(option: FormFieldOption): boolean {
return this.hasEmptyValue && option?.id === this.defaultEmptyOptionId;
}
private addOptions(options: FormFieldOption[]) {
options.forEach((option) => this.addOption(option));
}
private addOption(option: FormFieldOption) {
const alreadyExists = this.options.find((opt) => opt?.id === option?.id);
if (!alreadyExists) {
this.options.push(option);
}
}
private parseValidOptions(options: any): FormFieldOption[] {
return Array.isArray(options) ? options.filter((option) => this.isValidOption(option)) : [];
}
private isValidOption(option: any): boolean {
return typeof option === 'object' && !Array.isArray(option) && option?.id && option?.name;
}
private isDateField(json: any) {
return json.params?.field?.type === FormFieldTypes.DATE || json.type === FormFieldTypes.DATE;
}

View File

@@ -64,11 +64,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('Simple Dropdown', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: false,
restUrl: 'https://fake-rest-url',
options: [{ id: 'empty', name: 'Choose one...' }]
});
@@ -120,6 +119,18 @@ describe('DropdownCloudWidgetComponent', () => {
expect(await allOptions[2].getText()).toEqual('option_3');
});
it('should NOT load data from restUrl when field is readonly', () => {
spyOn(formCloudService, 'getRestWidgetData');
widget.field.readOnly = true;
widget.field.restUrl = 'https://fake-rest-url';
widget.field.optionType = 'rest';
widget.field.restIdProperty = 'name';
widget.ngOnInit();
expect(formCloudService.getRestWidgetData).not.toHaveBeenCalled();
});
it('should show error message if the restUrl failed to fetch options', async () => {
const jsonDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(throwError('Failed to fetch options'));
const errorIcon: string = 'error_outline';
@@ -315,15 +326,30 @@ describe('DropdownCloudWidgetComponent', () => {
const requiredErrorElement = fixture.debugElement.query(By.css('.adf-dropdown-required-message .adf-error-text'));
expect(requiredErrorElement.nativeElement.innerText).toEqual('FORM.FIELD.REQUIRED');
});
it('should NOT display a required error when dropdown is readonly', async () => {
widget.field.readOnly = true;
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('.adf-invalid')).toBeFalsy();
const dropdownSelect = element.querySelector('.adf-select');
dropdownSelect.dispatchEvent(new Event('blur'));
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('.adf-invalid')).toBeFalsy();
});
});
describe('filter', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'option list',
type: 'dropdown',
readOnly: false,
options: filterOptionList
});
widget.ngOnInit();
@@ -370,11 +396,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('multiple selection', () => {
it('should show preselected option', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
options: fakeOptionList,
selectionType: 'multiple',
value: [
@@ -389,11 +414,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should support multiple options', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
selectionType: 'multiple',
options: fakeOptionList
});
@@ -408,11 +432,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should show preselected option for rest options', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
restUrl: 'https://fake-rest-url',
optionType: 'rest',
selectionType: 'multiple',
@@ -448,11 +471,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should support multiple options for rest options', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'dropdown-id',
name: 'date-name',
type: 'dropdown',
readOnly: 'false',
restUrl: 'https://fake-rest-url',
optionType: 'rest',
selectionType: 'multiple'
@@ -498,11 +520,10 @@ describe('DropdownCloudWidgetComponent', () => {
validate: () => true
});
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'rest',
restUrl: 'myFakeDomain.com/cities?country=${parentDropdown}',
rule: {
@@ -605,11 +626,10 @@ describe('DropdownCloudWidgetComponent', () => {
const parentDropdown = new FormFieldModel(new FormModel(), { id: 'parentDropdown', type: 'dropdown' });
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'manual',
rule: {
ruleOn: 'parentDropdown',
@@ -694,11 +714,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('Load selection for linked dropdown (i.e. saved, completed forms)', () => {
it('should load the selection of a manual type linked dropdown', () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'manual',
rule: {
ruleOn: 'parentDropdown',
@@ -718,11 +737,10 @@ describe('DropdownCloudWidgetComponent', () => {
it('should load the selection of a rest type linked dropdown', () => {
const jsonDataSpy = spyOn(formCloudService, 'getRestWidgetData').and.returnValue(of(mockRestDropdownOptions));
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false' }), {
id: 'child-dropdown-id',
name: 'child-dropdown',
type: 'dropdown',
readOnly: 'false',
restUrl: 'mock-url.com/country=${country}',
optionType: 'rest',
rule: {
@@ -744,11 +762,10 @@ describe('DropdownCloudWidgetComponent', () => {
describe('when form model has left labels', () => {
it('should have left labels classes on leftLabels true', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: true }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false, leftLabels: true }), {
id: 'dropdown-id',
name: 'option list',
type: FormFieldTypes.DROPDOWN,
readOnly: false,
options: filterOptionList
});
@@ -763,11 +780,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should not have left labels classes on leftLabels false', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', leftLabels: false }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false, leftLabels: false }), {
id: 'dropdown-id',
name: 'option list',
type: FormFieldTypes.DROPDOWN,
readOnly: false,
options: filterOptionList
});
@@ -782,11 +798,10 @@ describe('DropdownCloudWidgetComponent', () => {
});
it('should not have left labels classes on leftLabels not present', async () => {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id' }), {
widget.field = new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: false }), {
id: 'dropdown-id',
name: 'option list',
type: FormFieldTypes.DROPDOWN,
readOnly: false,
options: filterOptionList
});
@@ -813,11 +828,10 @@ describe('DropdownCloudWidgetComponent', () => {
processVariables?: TaskVariableCloud[],
variables?: TaskVariableCloud[]
) =>
new FormFieldModel(new FormModel({ taskId: 'fake-task-id', processVariables, variables }), {
new FormFieldModel(new FormModel({ taskId: 'fake-task-id', readOnly: 'false', processVariables, variables }), {
id: 'variable-dropdown-id',
name: 'variable-options-dropdown',
type: 'dropdown',
readOnly: 'false',
optionType: 'variable',
variableConfig: {
variableName,
@@ -961,5 +975,20 @@ describe('DropdownCloudWidgetComponent', () => {
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(failedErrorMsgElement).toBeNull();
});
it('should NOT display errors if field is readonly', () => {
widget.field = getVariableDropdownWidget(
'variables.wrong-variable-id',
'response.wrongPath.players',
'wrongId',
'wrongFullName',
mockProcessVariablesWithJson
);
widget.field.readOnly = true;
fixture.detectChanges();
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-dropdown-failed-message'));
expect(failedErrorMsgElement).toBeNull();
});
});
});

View File

@@ -84,7 +84,9 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
private checkFieldOptionsSource(): void {
switch (true) {
case this.field.restUrl && !this.isLinkedWidget():
case this.isReadOnly():
break;
case this.hasRestUrl() && !this.isLinkedWidget():
this.persistFieldOptionsFromRestApi();
break;
@@ -377,7 +379,7 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
private isValidRestType(): boolean {
return this.field.optionType === 'rest' && !!this.field.restUrl;
return this.field.optionType === 'rest' && this.hasRestUrl();
}
private setPreviewState(): void {
@@ -390,6 +392,14 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
}
private isReadOnly(): boolean {
return this.field.readOnly;
}
private hasRestUrl(): boolean {
return !!this.field.restUrl;
}
isReadOnlyType(): boolean {
return this.field.type === 'readonly';
}
@@ -400,6 +410,10 @@ export class DropdownCloudWidgetComponent extends WidgetComponent implements OnI
}
updateOptions(): void {
if (this.isReadOnly()) {
this.list$ = of(this.field.options);
}
this.showInputFilter = this.field.options.length > this.appConfig.get<number>('form.dropDownFilterLimit', HIDE_FILTER_LIMIT);
this.list$ = combineLatest([of(this.field.options), this.filter$]).pipe(
map(([items, search]) => {

View File

@@ -944,10 +944,13 @@ describe('FormComponent', () => {
const formValues: any = {};
formValues.dropdownId = {
id: 'option_2',
name: 'test2'
id: 'dropdown_option_2',
name: 'Dropdown option 2'
};
formValues.radio = {
id: 'radio_option_3',
name: 'Radio option 3'
};
formValues.radio = { id: 'option_2', name: 'Option 2' };
const change = new SimpleChange(null, formValues, false);
formComponent.data = formValues;
formComponent.ngOnChanges({ data: change });
@@ -956,9 +959,9 @@ describe('FormComponent', () => {
dropdownField = formFields.find((field) => field.id === 'dropdownId');
radioField = formFields.find((field) => field.id === 'radio');
expect(dropdownField.value.id).toBe('option_2');
expect(dropdownField.value.name).toBe('test2');
expect(radioField.value).toBe('option_2');
expect(dropdownField.value).toBe('dropdown_option_2');
expect(radioField.value.id).toBe('radio_option_3');
expect(radioField.value.name).toBe('Radio option 3');
});
it('should refresh radio buttons value when id is given to data', () => {