From 870ac12173775eb2d89a2c58bb02136909c265f5 Mon Sep 17 00:00:00 2001 From: Jarda Hejlek Date: Fri, 4 Nov 2022 21:28:04 +0100 Subject: [PATCH 1/2] feat(input_schema): new globs and datepicker editor, improved validation --- packages/input_schema/src/input_schema.ts | 23 +++++++++++++++++++++-- packages/input_schema/src/intl.ts | 2 ++ packages/input_schema/src/schema.json | 6 +++--- test/input_schema.test.ts | 15 +++++++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/packages/input_schema/src/input_schema.ts b/packages/input_schema/src/input_schema.ts index d33c19285..379d3d7e2 100644 --- a/packages/input_schema/src/input_schema.ts +++ b/packages/input_schema/src/input_schema.ts @@ -117,8 +117,24 @@ const validateField = > (validator: Ajv, fieldSche }; /** - * This function validates given input schema first just for basic structure then each field one by one and - * finally fully against the whole schema. + * Validates that all required fields are present in properties list + */ +export function validateExistenceOfRequiredFields>(inputSchema: T) { + // If the input schema does not have any required fields, we do not need to validate them + if (!inputSchema?.required?.length) return; + + Object.values(inputSchema?.required).forEach((fieldKey) => { + // If the required field is present in the list of properties, we can check the next one + if (inputSchema?.properties[fieldKey as string]) return; + + // The required field is not defined in list of properties. Which means the schema is not valid. + throw new Error(m('inputSchema.validation.missingRequiredField', { fieldKey })); + }); +} + +/** + * This function validates given input schema first just for basic structure then each field one by one, + * then checks that all required fields are present and finally checks fully against the whole schema. * * This way we get the most accurate error message for user. */ @@ -129,6 +145,9 @@ export function validateInputSchema>(validator: Aj // Then validate each field separately. Object.entries(inputSchema.properties).forEach(([fieldKey, fieldSchema]) => validateField(validator, fieldSchema, fieldKey)); + // Next validate if required fields are actually present in the schema + validateExistenceOfRequiredFields(inputSchema); + // Finally just to be sure run validation against the whole shema. validateAgainstSchemaOrThrow(validator, inputSchema, schema, 'schema'); } diff --git a/packages/input_schema/src/intl.ts b/packages/input_schema/src/intl.ts index 6a354aa68..c849e6988 100644 --- a/packages/input_schema/src/intl.ts +++ b/packages/input_schema/src/intl.ts @@ -30,6 +30,8 @@ const intlStrings = { 'Currently you do not have access to any proxy group usable in automatic mode.', 'inputSchema.validation.noMatchingDefinition': 'Field schema.properties.{fieldKey} is not matching any input schema type definition. Please make sure that it\'s type is valid.', + 'inputSchema.validation.missingRequiredField': + 'Field schema.properties.{fieldKey} does not exist, but it is specified in schema.required. Either define the field or remove it from schema.required.', }; /* eslint-enable max-len,quotes,quote-props */ diff --git a/packages/input_schema/src/schema.json b/packages/input_schema/src/schema.json index c806d9070..df3e570c7 100644 --- a/packages/input_schema/src/schema.json +++ b/packages/input_schema/src/schema.json @@ -85,7 +85,7 @@ "title": { "type": "string" }, "description": { "type": "string" }, "nullable": { "type": "boolean" }, - "editor": { "enum": ["javascript", "python", "textfield", "textarea", "hidden"] }, + "editor": { "enum": ["javascript", "python", "textfield", "textarea", "datepicker", "hidden"] }, "isSecret": { "type": "boolean" } }, "required": ["type", "title", "description", "editor"], @@ -111,7 +111,7 @@ "nullable": { "type": "boolean" }, "minLength": { "type": "integer" }, "maxLength": { "type": "integer" }, - "editor": { "enum": ["javascript", "python", "textfield", "textarea", "hidden"] }, + "editor": { "enum": ["javascript", "python", "textfield", "textarea", "datepicker", "hidden"] }, "isSecret": { "type": "boolean" }, "sectionCaption": { "type": "string" }, "sectionDescription": { "type": "string" } @@ -152,7 +152,7 @@ "maxItems": { "type": "integer" }, "uniqueItems": { "type": "boolean" }, - "editor": { "enum": ["json", "requestListSources", "pseudoUrls", "keyValue", "stringList", "hidden"] }, + "editor": { "enum": ["json", "requestListSources", "pseudoUrls", "globs", "keyValue", "stringList", "hidden"] }, "sectionCaption": { "type": "string" }, "sectionDescription": { "type": "string" } }, diff --git a/test/input_schema.test.ts b/test/input_schema.test.ts index cdc61fd52..2ba6b3cf7 100644 --- a/test/input_schema.test.ts +++ b/test/input_schema.test.ts @@ -207,5 +207,20 @@ describe('input_schema.json', () => { 'Input schema is not valid (Field schema.properties.myField.enum.0 must be string)', ); }); + + it('should throw error when required field is not defined', () => { + const schema = { + title: 'Test input schema', + type: 'object', + schemaVersion: 1, + properties: {}, + required: ['something'], + }; + + expect(() => validateInputSchema(validator, schema)).toThrow( + // eslint-disable-next-line + 'Field schema.properties.something does not exist, but it is specified in schema.required. Either define the field or remove it from schema.required.', + ); + }); }); }); From ac7c951f837583bf68aa304385c577b55bc5024b Mon Sep 17 00:00:00 2001 From: Jarda Hejlek Date: Fri, 4 Nov 2022 21:40:25 +0100 Subject: [PATCH 2/2] fix: fixed unit tests --- test/input_schema.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/input_schema.test.ts b/test/input_schema.test.ts index 2ba6b3cf7..11cef4f31 100644 --- a/test/input_schema.test.ts +++ b/test/input_schema.test.ts @@ -141,7 +141,7 @@ describe('input_schema.json', () => { expect(() => validateInputSchema(validator, schema)).toThrow( 'Input schema is not valid (Field schema.properties.myField.editor must be equal to one of the allowed values: ' - + '"javascript", "python", "textfield", "textarea", "hidden")', + + '"javascript", "python", "textfield", "textarea", "datepicker", "hidden")', ); });