From 22d14d3f533d3f134aaeebebc79f0e8b60eba850 Mon Sep 17 00:00:00 2001 From: Drew Hoover Date: Tue, 8 Aug 2023 19:06:22 -0400 Subject: [PATCH] Support overridable combinator labels 'title' can be defined in both the resolving subschema and the resolved to subschema. This fix enhances JSON Forms to take both of these cases into account when resolving subschemas in combinators. Intermediate titles will still be ignored. Fixes #2164 --- packages/core/src/util/combinators.ts | 25 +++---- packages/core/test/util/combinators.test.ts | 82 +++++++++++++++++++++ 2 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 packages/core/test/util/combinators.test.ts diff --git a/packages/core/src/util/combinators.ts b/packages/core/src/util/combinators.ts index e502d229f..9ebb3b6cc 100644 --- a/packages/core/src/util/combinators.ts +++ b/packages/core/src/util/combinators.ts @@ -35,18 +35,6 @@ export interface CombinatorSubSchemaRenderInfo { export type CombinatorKeyword = 'anyOf' | 'oneOf' | 'allOf'; -const createLabel = ( - subSchema: JsonSchema, - subSchemaIndex: number, - keyword: CombinatorKeyword -): string => { - if (subSchema.title) { - return subSchema.title; - } else { - return keyword + '-' + subSchemaIndex; - } -}; - export const createCombinatorRenderInfos = ( combinatorSubSchemas: JsonSchema[], rootSchema: JsonSchema, @@ -56,9 +44,11 @@ export const createCombinatorRenderInfos = ( uischemas: JsonFormsUISchemaRegistryEntry[] ): CombinatorSubSchemaRenderInfo[] => combinatorSubSchemas.map((subSchema, subSchemaIndex) => { - const schema = subSchema.$ref - ? Resolve.schema(rootSchema, subSchema.$ref, rootSchema) - : subSchema; + const resolvedSubSchema = + subSchema.$ref && Resolve.schema(rootSchema, subSchema.$ref, rootSchema); + + const schema = resolvedSubSchema ?? subSchema; + return { schema, uischema: findUISchema( @@ -70,6 +60,9 @@ export const createCombinatorRenderInfos = ( control, rootSchema ), - label: createLabel(subSchema, subSchemaIndex, keyword), + label: + subSchema.title ?? + resolvedSubSchema.title ?? + `${keyword}-${subSchemaIndex}`, }; }); diff --git a/packages/core/test/util/combinators.test.ts b/packages/core/test/util/combinators.test.ts new file mode 100644 index 000000000..548760967 --- /dev/null +++ b/packages/core/test/util/combinators.test.ts @@ -0,0 +1,82 @@ +import test from 'ava'; +import { createCombinatorRenderInfos } from '../../src/util/combinators'; +import { ControlElement } from '../../src'; + +const rootSchema = { + type: 'object', + properties: { + widget: { + anyOf: [ + { + $ref: '#/definitions/Dua', + }, + { + $ref: '#/definitions/Lipa', + }, + ], + }, + }, + definitions: { + Dua: { + title: 'Dua', + type: 'object', + properties: { name: { type: 'string' } }, + }, + Lipa: { + title: 'Lipa', + type: 'object', + properties: { name: { type: 'string' } }, + }, + }, +}; + +const rootSchemaWithOverrides = { + ...rootSchema, + properties: { + ...rootSchema.properties, + widget: { + ...rootSchema.properties.widget, + anyOf: [ + { + ...rootSchema.properties.widget.anyOf[0], + title: 'DuaOverride', + }, + { + ...rootSchema.properties.widget.anyOf[1], + title: 'LipaOverride', + }, + ], + }, + }, +}; + +const control: ControlElement = { + type: 'Control', + scope: '#', +}; + +test('createCombinatorRenderInfos - uses titles for labels when subschemas are refs', (t) => { + const [duaRenderInfo, lipaRenderInfo] = createCombinatorRenderInfos( + rootSchema.properties.widget.anyOf, + rootSchema, + 'anyOf', + control, + 'widget', + [] + ); + t.deepEqual(duaRenderInfo.label, 'Dua'); + t.deepEqual(lipaRenderInfo.label, 'Lipa'); +}); + +test('createCombinatorRenderInfos - uses overrides for labels when subschemas are refs', (t) => { + const [duaRenderInfo, lipaRenderInfo] = createCombinatorRenderInfos( + rootSchemaWithOverrides.properties.widget.anyOf, + rootSchemaWithOverrides, + 'anyOf', + control, + 'widget', + [] + ); + t.deepEqual(duaRenderInfo.label, 'DuaOverride'); + t.deepEqual(lipaRenderInfo.label, 'LipaOverride'); +});