diff --git a/common/mockData/formatterMockData.ts b/common/mockData/formatterMockData.ts index bdba25f..9ce275d 100644 --- a/common/mockData/formatterMockData.ts +++ b/common/mockData/formatterMockData.ts @@ -252,6 +252,57 @@ export const JSON_SCHEMA_DUPLICATED_CHOICES_SINGLE_SELECT_FAKE_DATA = '{\n' + ' }\n' + '}'; +export const JSON_SCHEMA_DUPLICATED_REQUIRED_PROPERTIES_FAKE_DATA = '{\n' + + ' "definition": [\n' + + ' "fieldset__title_abnormalities_info",\n' + + ' "fieldset__title_general_info",\n' + + ' "fieldset__title_markings_info",\n' + + ' "fieldset__title_tagging_info"\n' + + ' ],\n' + + ' "schema": {\n' + + ' "icon_id": "reptiles_amphibians_rep",\n' + + ' "image_url": "https://mobile-bash.pamdas.org/static/sprite-src/reptiles_amphibians_rep.svg",\n' + + ' "properties": {\n' + + ' "fieldset__title_abnormalities_info": {\n' + + ' "display": "header",\n' + + ' "isHidden": false,\n' + + ' "readOnly": true,\n' + + ' "title": "Abnormalities info",\n' + + ' "type": "string"\n' + + ' },\n' + + ' "fieldset__title_general_info": {\n' + + ' "display": "header",\n' + + ' "isHidden": false,\n' + + ' "readOnly": true,\n' + + ' "title": "General info",\n' + + ' "type": "string"\n' + + ' },\n' + + ' "fieldset__title_markings_info": {\n' + + ' "display": "header",\n' + + ' "isHidden": false,\n' + + ' "readOnly": true,\n' + + ' "title": "Markings info",\n' + + ' "type": "string"\n' + + ' },\n' + + ' "fieldset__title_tagging_info": {\n' + + ' "display": "header",\n' + + ' "isHidden": false,\n' + + ' "readOnly": true,\n' + + ' "title": "Tagging info",\n' + + ' "type": "string"\n' + + ' }\n' + + ' },\n' + + ' "required": [\n' + + ' "fieldset__title_abnormalities_info",\n' + + ' "fieldset__title_general_info",\n' + + ' "fieldset__title_markings_info",\n' + + ' "fieldset__title_markings_info"\n' + + ' ],\n' + + ' "title": "Turtle data Report",\n' + + ' "type": "object"\n' + + ' }\n' + + '}'; + export const JSON_SCHEMA_DATE_TIME_FIELD_SETS = '{\n' + ' "schema": {\n' + ' "$schema": "http://json-schema.org/draft-04/schema#",\n' + diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 3040d46..2d53716 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -82,4 +82,4 @@ export const isInactiveChoice = (item: any) => item.type === STRING_TYPE export const isDisabledChoice = (item: any) => isObject(item) && item.type === CHECKBOXES && item.inactive_titleMap?.length > 0 && item.titleMap?.length > 0; -export const hasEnumDuplicatedItems = (options: string[]) => (new Set(options).size !== options.length); +export const hasDuplicatedItems = (items: string[]) => (new Set(items).size !== items.length); diff --git a/src/validateJsonSchema.ts b/src/validateJsonSchema.ts index f449002..7b25eef 100644 --- a/src/validateJsonSchema.ts +++ b/src/validateJsonSchema.ts @@ -3,7 +3,7 @@ import { ElementDisplay, getFieldSetTitleKey, getSchemaValidations, - hasEnumDuplicatedItems, + hasDuplicatedItems, HELP_VALUE, isArrayProperty, isCheckbox, @@ -236,9 +236,9 @@ const validateSchema = (validations: any, schema: any) => { // Detect duplicated enum items if ( schema.schema.properties[key].enum?.length > 0 - && hasEnumDuplicatedItems(schema.schema.properties[key].enum) + && hasDuplicatedItems(schema.schema.properties[key].enum) ) { - throw new Error('Duplicated items'); + throw new Error('Duplicated enum items'); } } } @@ -270,6 +270,9 @@ export const validateJSONSchema = (stringSchema: string) => { if (stringSchema.includes(REQUIRED_PROPERTY)) { schema.schema = cleanUpRequiredProperty(schema.schema); + if (schema.schema.required?.length > 0 && hasDuplicatedItems(schema.schema.required)) { + throw new Error('Duplicated required properties'); + } } return schema; }; diff --git a/test/JsonFormatter.test.tsx b/test/JsonFormatter.test.tsx index d044937..b515407 100644 --- a/test/JsonFormatter.test.tsx +++ b/test/JsonFormatter.test.tsx @@ -6,6 +6,7 @@ import { JSON_SCHEMA_DATE_TIME_FIELD_SETS, JSON_SCHEMA_DEFAULT_VALUES, JSON_SCHEMA_DUPLICATED_CHOICES_SINGLE_SELECT_FAKE_DATA, + JSON_SCHEMA_DUPLICATED_REQUIRED_PROPERTIES_FAKE_DATA, JSON_SCHEMA_EMPTY_CHOICES_FAKE_DATA, JSON_SCHEMA_FIELD_SETS_FAKE_DATA, JSON_SCHEMA_ID_$SCHEMA_FAKE_DATA, @@ -39,9 +40,9 @@ describe("JSON Schema validation", () => { it("Validate empty choices", () => { const validSchema = validateJSONSchema(JSON_SCHEMA_EMPTY_CHOICES_FAKE_DATA).toString; - expect(validSchema).not.toContain(/\"enum\"\n*\s*\:\n*\s*\[\n*\s*\]/g); - expect(validSchema).not.toContain(/\"enumNames\"\n*\s*\:\n*\s*\{\n*\s*\}/g); - expect(validSchema).not.toContain(/\"titleMap\"\n*\s*\:\n*\s*\[\n*\s*\]/g); + expect(validSchema).not.toContain(/"enum"\n*\s*:\n*\s*\[\n*\s*\]/g); + expect(validSchema).not.toContain(/"enumNames"\n*\s*:\n*\s*\{\n*\s*\}/g); + expect(validSchema).not.toContain(/"titleMap"\n*\s*:\n*\s*\[\n*\s*\]/g); }); it("Validate remove $schema and id properties", () => { @@ -88,7 +89,11 @@ describe("JSON Schema validation", () => { }); it('Validate duplicated items in single select', () => { - expect(() => validateJSONSchema(JSON_SCHEMA_DUPLICATED_CHOICES_SINGLE_SELECT_FAKE_DATA)).toThrow('Duplicated items'); + expect(() => validateJSONSchema(JSON_SCHEMA_DUPLICATED_CHOICES_SINGLE_SELECT_FAKE_DATA)).toThrow('Duplicated enum items'); + }); + + it('Validate duplicated required properties', () => { + expect(() => validateJSONSchema(JSON_SCHEMA_DUPLICATED_REQUIRED_PROPERTIES_FAKE_DATA)).toThrow('Duplicated required properties'); }); it("Format schema definition location", () => {