diff --git a/src/tests/createHeadlessForm.test.js b/src/tests/createHeadlessForm.test.js index 1be17398e..edb54e101 100644 --- a/src/tests/createHeadlessForm.test.js +++ b/src/tests/createHeadlessForm.test.js @@ -22,6 +22,7 @@ import { schemaInputTypeSelectMultiple, schemaInputTypeSelectMultipleOptional, schemaInputTypeFieldset, + schemaInputTypeIntegerNumber, schemaInputTypeNumber, schemaInputTypeNumberZeroMaximum, schemaInputTypeDate, @@ -994,6 +995,41 @@ describe('createHeadlessForm', () => { expect(fieldOptions).toEqual([]); }); + it('support "integer" field type', () => { + const result = createHeadlessForm(schemaInputTypeIntegerNumber); + expect(result).toMatchObject({ + fields: [ + { + description: 'How many open tabs do you have?', + label: 'Tabs', + name: 'tabs', + required: false, + schema: expect.any(Object), + type: 'number', + jsonType: 'integer', + inputType: 'number', + minimum: 1, + maximum: 10, + }, + ], + }); + + const fieldValidator = result.fields[0].schema; + expect(fieldValidator.isValidSync('0')).toBe(false); + expect(fieldValidator.isValidSync('10')).toBe(true); + expect(fieldValidator.isValidSync('11')).toBe(false); + expect(fieldValidator.isValidSync('5.5')).toBe(false); + expect(fieldValidator.isValidSync('1.0')).toBe(true); + expect(fieldValidator.isValidSync('this is text with a number 1')).toBe(false); + expect(() => fieldValidator.validateSync('5.5')).toThrowError( + 'Must not contain decimal points. E.g. 5 instead of 5.5' + ); + expect(() => fieldValidator.validateSync('some text')).toThrowError( + 'The value must be a number' + ); + expect(() => fieldValidator.validateSync('')).toThrowError('The value must be a number'); + }); + it('support "number" field type', () => { const result = createHeadlessForm(schemaInputTypeNumber); expect(result).toMatchObject({ diff --git a/src/tests/helpers.custom.js b/src/tests/helpers.custom.js index 024a255dc..e95de3c92 100644 --- a/src/tests/helpers.custom.js +++ b/src/tests/helpers.custom.js @@ -194,7 +194,7 @@ export const schemaInputTypeHidden = { title: 'Money hidden', 'x-jsf-presentation': { inputType: 'hidden', currency: 'EUR' }, minimum: 0, - default: 12.3, + default: 1099, }, a_hidden_select: { ...mockSelectInputSolo, diff --git a/src/tests/helpers.js b/src/tests/helpers.js index ff65ba78f..5cc8f320d 100644 --- a/src/tests/helpers.js +++ b/src/tests/helpers.js @@ -61,6 +61,21 @@ export const schemaInputTypeNumberZeroMaximum = { }, }; +export const schemaInputTypeIntegerNumber = { + properties: { + tabs: { + title: 'Tabs', + description: 'How many open tabs do you have?', + 'x-jsf-presentation': { + inputType: 'number', + }, + minimum: 1, + maximum: 10, + type: 'integer', + }, + }, +}; + export const mockNumberInputWithPercentage = { title: 'Shares', description: 'What % of shares do you own?', diff --git a/src/yupSchema.js b/src/yupSchema.js index 8f4f2e70e..c1f6143b8 100644 --- a/src/yupSchema.js +++ b/src/yupSchema.js @@ -293,6 +293,7 @@ export function buildYupSchema(field, config, logic) { const isCheckboxBoolean = typeof propertyFields.checkboxValue === 'boolean'; let baseSchema; const errorMessageFromConfig = config?.inputTypes?.[inputType]?.errorMessage || {}; + const jsonType = getJsonTypeInArray(field.jsonType); if (propertyFields.multiple) { // keep inputType while non-core are being removed #RMT-439 @@ -320,6 +321,18 @@ export function buildYupSchema(field, config, logic) { } return yupSchema.required(requiredMessage); } + + function withInteger(yupSchema) { + return yupSchema.integer( + (message) => + errorMessage.integer ?? + errorMessageFromConfig.integer ?? + `Must not contain decimal points. E.g. ${Math.floor(message.value)} instead of ${ + message.value + }` + ); + } + function withMin(yupSchema) { return yupSchema.min( propertyFields.minimum, @@ -488,6 +501,10 @@ export function buildYupSchema(field, config, logic) { validators.push(withFile); } + if (jsonType === 'integer') { + validators.push(withInteger); + } + // support minimum with 0 value if (typeof propertyFields.minimum !== 'undefined') { validators.push(withMin);