From 91bb99ae2288e5046fa27e6cee9489aa6b1f2b77 Mon Sep 17 00:00:00 2001 From: Bogdan Nechyporenko Date: Sun, 5 Jan 2025 12:33:58 +0100 Subject: [PATCH] Fixed the issue #28239 (Bug Report: Field extension validation does not work when field is in dependencies in an array field) Signed-off-by: Bogdan Nechyporenko --- .changeset/little-scissors-fold.md | 5 ++ .../Stepper/createAsyncValidators.test.ts | 58 +++++++++++++++++++ .../Stepper/createAsyncValidators.ts | 22 ++++++- 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 .changeset/little-scissors-fold.md diff --git a/.changeset/little-scissors-fold.md b/.changeset/little-scissors-fold.md new file mode 100644 index 0000000000..a8a0c917b8 --- /dev/null +++ b/.changeset/little-scissors-fold.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Fixed the issue #28239 (Bug Report: Field extension validation does not work when field is in dependencies in an array field) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index f4dab376bc..02e15ec53b 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -435,4 +435,62 @@ describe('createAsyncValidators', () => { expect(validators.CustomLinkField).toHaveBeenCalled(); }); + + it('should validate field in the dependencies in an array field', async () => { + const schema: JsonObject = { + title: 'Make a choice', + properties: { + myArray: { + type: 'array', + title: 'Array', + items: { + type: 'object', + required: ['selector'], + properties: { + selector: { + title: 'Selector', + type: 'string', + enum: ['Choice 1', 'Choice 2'], + }, + }, + dependencies: { + selector: { + oneOf: [ + { properties: { selector: { enum: ['Choice 1'] } } }, + { + properties: { + selector: { enum: ['Choice 2'] }, + customValidatedField: { + title: 'Custom validated field', + type: 'string', + 'ui:field': 'ValidateKebabCase', + }, + }, + }, + ], + }, + }, + }, + }, + }, + }; + + const validators = { ValidateKebabCase: jest.fn() }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await validate({ + myArray: [ + { + selector: 'Choice 2', + customValidatedField: 'apple', + }, + { selector: 'Choice 1' }, + ], + }); + + expect(validators.ValidateKebabCase).toHaveBeenCalled(); + }); }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index d11d0b9b3b..b0ba844e54 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -15,7 +15,7 @@ */ import { FieldValidation } from '@rjsf/utils'; -import type { JsonObject, JsonValue } from '@backstage/types'; +import { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema, @@ -135,6 +135,26 @@ export const createAsyncValidators = ( for (const [, propValue] of Object.entries(properties)) { await doValidate(propValue); } + if (Array.isArray(value)) { + for (const [_, v] of Object.entries(value)) { + const { schema: itemSchema, uiSchema: itemUiSchema } = + extractSchemaFromStep(definitionInSchema.items); + + if (isObject(v)) { + for (const [pK, pV] of Object.entries(v)) { + if ('ui:field' in itemUiSchema[pK]) { + await validateForm( + itemUiSchema[pK]['ui:field'], + pK, + pV, + itemSchema, + itemUiSchema, + ); + } + } + } + } + } } else if (isObject(value)) { formValidation[key] = await validate(formData, pointer, value); }