From bda8da02b61ea52ca1f1a1ee00a3bb8d1a946d56 Mon Sep 17 00:00:00 2001 From: qsmr Date: Mon, 11 Nov 2024 11:32:10 -0500 Subject: [PATCH 1/6] Use default values when switching anyOf option --- packages/core/test/anyOf.test.jsx | 37 +++++++++++++++++++ .../src/schema/sanitizeDataForNewSchema.ts | 12 +++++- .../schema/sanitizeDataForNewSchemaTest.ts | 11 ++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/packages/core/test/anyOf.test.jsx b/packages/core/test/anyOf.test.jsx index b043ad7923..c62a661abb 100644 --- a/packages/core/test/anyOf.test.jsx +++ b/packages/core/test/anyOf.test.jsx @@ -165,6 +165,43 @@ describe('anyOf', () => { ); }); + it('should assign a default value and set defaults on option change for scalar types schemas', () => { + const { node, onChange } = createFormComponent({ + schema: { + type: 'object', + properties: { + foo: { + anyOf: [ + { + type: 'string', + default: 'defaultfoo', + }, + { + type: 'boolean', + default: true, + }, + ], + }, + }, + }, + }); + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { foo: 'defaultfoo' }, + }); + + const $select = node.querySelector('select'); + + act(() => { + fireEvent.change($select, { + target: { value: $select.options[1].value }, + }); + }); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { foo: true }, + }); + }); + it('should assign a default value and set defaults on option change when using references', () => { const { node, onChange } = createFormComponent({ schema: { diff --git a/packages/utils/src/schema/sanitizeDataForNewSchema.ts b/packages/utils/src/schema/sanitizeDataForNewSchema.ts index c1ab83c7b8..39563abc71 100644 --- a/packages/utils/src/schema/sanitizeDataForNewSchema.ts +++ b/packages/utils/src/schema/sanitizeDataForNewSchema.ts @@ -51,6 +51,8 @@ const NO_VALUE = Symbol('no Value'); * - For each element in the `data` recursively sanitize the data, stopping at `maxItems` if specified * - Otherwise, just return the `data` removing any values after `maxItems` if it is set * - If the type of the old and new schema `items` are booleans of the same value, return `data` as is + * - If the new schema contains a default value then: + * - return the default value. We expect this to be a scalar value * - Otherwise return `undefined` * * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary @@ -60,7 +62,8 @@ const NO_VALUE = Symbol('no Value'); * @param [data={}] - The form data associated with the schema, defaulting to an empty object when undefined * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas * @returns - The new form data, with all the fields uniquely associated with the old schema set - * to `undefined`. Will return `undefined` if the new schema is not an object containing properties. + * to `undefined`. Will return `undefined` if the new schema is not an object containing properties + * and doesn't provide a default value */ export default function sanitizeDataForNewSchema< T = any, @@ -234,5 +237,12 @@ export default function sanitizeDataForNewSchema< } // Also probably want to deal with `prefixItems` as tuples with the latest 2020 draft } + // Schema contains a single scalar value + else { + const newDefaultValue = get(newSchema, 'default'); + if (newDefaultValue !== undefined) { + newFormData = newDefaultValue; + } + } return newFormData as T; } diff --git a/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts b/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts index 1069ee9780..41a774741d 100644 --- a/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts +++ b/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts @@ -483,5 +483,16 @@ export default function sanitizeDataForNewSchemaTest(testValidator: TestValidato }; expect(schemaUtils.sanitizeDataForNewSchema(newSchema, oldSchema, ['qwerty', 'asdfg'])).toEqual({}); }); + + it('returns default value when new schema is a scalar schema', () => { + const oldSchema: RJSFSchema = { + type: 'string', + }; + const newSchema: RJSFSchema = { + type: 'boolean', + default: true, + }; + expect(schemaUtils.sanitizeDataForNewSchema(newSchema, oldSchema, 'oldValue')).toEqual(true); + }); }); } From c40e1a33890032a75aaa25c3957b5377b21f742c Mon Sep 17 00:00:00 2001 From: qsmr Date: Mon, 18 Nov 2024 09:11:40 -0500 Subject: [PATCH 2/6] review --- .../core/src/components/fields/MultiSchemaField.tsx | 2 +- .../utils/src/schema/sanitizeDataForNewSchema.ts | 12 +----------- .../test/schema/sanitizeDataForNewSchemaTest.ts | 11 ----------- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/packages/core/src/components/fields/MultiSchemaField.tsx b/packages/core/src/components/fields/MultiSchemaField.tsx index 7808f3289c..d4dd390a90 100644 --- a/packages/core/src/components/fields/MultiSchemaField.tsx +++ b/packages/core/src/components/fields/MultiSchemaField.tsx @@ -123,7 +123,7 @@ class AnyOfField= 0 ? retrievedOptions[selectedOption] : undefined; let newFormData = schemaUtils.sanitizeDataForNewSchema(newOption, oldOption, formData); - if (newFormData && newOption) { + if (newOption) { // Call getDefaultFormState to make sure defaults are populated on change. Pass "excludeObjectChildren" // so that only the root objects themselves are created without adding undefined children properties newFormData = schemaUtils.getDefaultFormState(newOption, newFormData, 'excludeObjectChildren') as T; diff --git a/packages/utils/src/schema/sanitizeDataForNewSchema.ts b/packages/utils/src/schema/sanitizeDataForNewSchema.ts index 39563abc71..c1ab83c7b8 100644 --- a/packages/utils/src/schema/sanitizeDataForNewSchema.ts +++ b/packages/utils/src/schema/sanitizeDataForNewSchema.ts @@ -51,8 +51,6 @@ const NO_VALUE = Symbol('no Value'); * - For each element in the `data` recursively sanitize the data, stopping at `maxItems` if specified * - Otherwise, just return the `data` removing any values after `maxItems` if it is set * - If the type of the old and new schema `items` are booleans of the same value, return `data` as is - * - If the new schema contains a default value then: - * - return the default value. We expect this to be a scalar value * - Otherwise return `undefined` * * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary @@ -62,8 +60,7 @@ const NO_VALUE = Symbol('no Value'); * @param [data={}] - The form data associated with the schema, defaulting to an empty object when undefined * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas * @returns - The new form data, with all the fields uniquely associated with the old schema set - * to `undefined`. Will return `undefined` if the new schema is not an object containing properties - * and doesn't provide a default value + * to `undefined`. Will return `undefined` if the new schema is not an object containing properties. */ export default function sanitizeDataForNewSchema< T = any, @@ -237,12 +234,5 @@ export default function sanitizeDataForNewSchema< } // Also probably want to deal with `prefixItems` as tuples with the latest 2020 draft } - // Schema contains a single scalar value - else { - const newDefaultValue = get(newSchema, 'default'); - if (newDefaultValue !== undefined) { - newFormData = newDefaultValue; - } - } return newFormData as T; } diff --git a/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts b/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts index 41a774741d..1069ee9780 100644 --- a/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts +++ b/packages/utils/test/schema/sanitizeDataForNewSchemaTest.ts @@ -483,16 +483,5 @@ export default function sanitizeDataForNewSchemaTest(testValidator: TestValidato }; expect(schemaUtils.sanitizeDataForNewSchema(newSchema, oldSchema, ['qwerty', 'asdfg'])).toEqual({}); }); - - it('returns default value when new schema is a scalar schema', () => { - const oldSchema: RJSFSchema = { - type: 'string', - }; - const newSchema: RJSFSchema = { - type: 'boolean', - default: true, - }; - expect(schemaUtils.sanitizeDataForNewSchema(newSchema, oldSchema, 'oldValue')).toEqual(true); - }); }); } From 630689fa161bf753a68838887ff3aa686fbb188d Mon Sep 17 00:00:00 2001 From: qsmr Date: Mon, 18 Nov 2024 09:48:26 -0500 Subject: [PATCH 3/6] Update changelog --- CHANGELOG.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a84feb1b99..586da84955 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ should change the heading of the (upcoming) version to include a major version b ## @rjsf/core - Updated `SchemaField` to no longer make schema fields with const read-only by default, partially fixing [#4344](https://github.com/rjsf-team/react-jsonschema-form/issues/4344) +- Fix default value population when switching between options in `MultiSchemaField` [#4375](https://github.com/rjsf-team/react-jsonschema-form/pull/4375). Fixes [#4367](https://github.com/rjsf-team/react-jsonschema-form/issues/4367) ## @rjsf/utils @@ -61,7 +62,7 @@ should change the heading of the (upcoming) version to include a major version b - Fix issue 'Maximum call stack size exceeded' with playground share with large content. -# 5.22.3 +# 5.22.3 ## @rjsf/utils @@ -137,7 +138,7 @@ should change the heading of the (upcoming) version to include a major version b ## @rjsf/core -- Updated `Form` to fix `focusOnError()` to support the ids that include dots, fixing [#4279](https://github.com/rjsf-team/react-jsonschema-form/issues/4279) +- Updated `Form` to fix `focusOnError()` to support the ids that include dots, fixing [#4279](https://github.com/rjsf-team/react-jsonschema-form/issues/4279) ## @rjsf/mui @@ -165,7 +166,7 @@ should change the heading of the (upcoming) version to include a major version b # 5.20.0 -## @rjsf/core +## @rjsf/core - Support allowing raising errors from within a custom Widget [#2718](https://github.com/rjsf-team/react-jsonschema-form/issues/2718) - Updated `ArrayField`, `BooleanField` and `StringField` to call `optionsList()` with the additional `UiSchema` parameter, fixing [#4215](https://github.com/rjsf-team/react-jsonschema-form/issues/4215) and [#4260](https://github.com/rjsf-team/react-jsonschema-form/issues/4260) @@ -183,7 +184,7 @@ should change the heading of the (upcoming) version to include a major version b # 5.19.4 -## @rjsf/core +## @rjsf/core - Fix XSS when rendering schema validation errors [#4254](https://github.com/rjsf-team/react-jsonschema-form/issues/2718) - NOTE: This will have potential consequences if you are using the [translateString](https://rjsf-team.github.io/react-jsonschema-form/docs/api-reference/form-props/#translatestring) feature and are trying to render HTML. Switching to [Markdown](https://www.markdownguide.org/) will solve your problems. @@ -200,7 +201,7 @@ should change the heading of the (upcoming) version to include a major version b ## Dev / docs / playground -- Updated the `Validator` dropdown to add `AJV8 (discriminator)` which sets the AJV validator [discriminator](https://ajv.js.org/json-schema.html#discriminator) option to `true` to support testing schemas with that option in them +- Updated the `Validator` dropdown to add `AJV8 (discriminator)` which sets the AJV validator [discriminator](https://ajv.js.org/json-schema.html#discriminator) option to `true` to support testing schemas with that option in them # 5.19.3 From c939d29a412afbf4e5b276e9e111be79b7f47dd4 Mon Sep 17 00:00:00 2001 From: qsmr Date: Fri, 22 Nov 2024 16:44:50 -0500 Subject: [PATCH 4/6] review: add oneOf test --- packages/core/test/anyOf.test.jsx | 10 ++------- packages/core/test/oneOf.test.jsx | 34 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/packages/core/test/anyOf.test.jsx b/packages/core/test/anyOf.test.jsx index c62a661abb..0c30e92113 100644 --- a/packages/core/test/anyOf.test.jsx +++ b/packages/core/test/anyOf.test.jsx @@ -172,14 +172,8 @@ describe('anyOf', () => { properties: { foo: { anyOf: [ - { - type: 'string', - default: 'defaultfoo', - }, - { - type: 'boolean', - default: true, - }, + { type: 'string', default: 'defaultfoo' }, + { type: 'boolean', default: true }, ], }, }, diff --git a/packages/core/test/oneOf.test.jsx b/packages/core/test/oneOf.test.jsx index 3c76c6cfd5..4c021b2464 100644 --- a/packages/core/test/oneOf.test.jsx +++ b/packages/core/test/oneOf.test.jsx @@ -222,6 +222,37 @@ describe('oneOf', () => { ); }); + it('should assign a default value and set defaults on option change for scalar types schemas', () => { + const { node, onChange } = createFormComponent({ + schema: { + type: 'object', + properties: { + foo: { + oneOf: [ + { type: 'string', default: 'defaultfoo' }, + { type: 'boolean', default: true }, + ], + }, + }, + }, + }); + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { foo: 'defaultfoo' }, + }); + + const $select = node.querySelector('select'); + + act(() => { + fireEvent.change($select, { + target: { value: $select.options[1].value }, + }); + }); + + sinon.assert.calledWithMatch(onChange.lastCall, { + formData: { foo: true }, + }); + }); + it('should render a custom widget', () => { const schema = { type: 'object', @@ -573,6 +604,7 @@ describe('oneOf', () => { }, }; const formContext = { root: 'root-id', root_userId: 'userId-id' }; + function CustomSchemaField(props) { const { formContext, idSchema } = props; return ( @@ -582,6 +614,7 @@ describe('oneOf', () => { ); } + const { node } = createFormComponent({ schema, formData: { userId: 'foobarbaz' }, @@ -1598,6 +1631,7 @@ describe('oneOf', () => { }, }, }; + function customValidate(formData, errors) { errors.userId.addError('test'); return errors; From cff6785fe22809a33f76f6d16a12377aa9cae5f2 Mon Sep 17 00:00:00 2001 From: qsmr Date: Fri, 22 Nov 2024 16:48:40 -0500 Subject: [PATCH 5/6] Move changelog entry to 5.23.1 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 586da84955..5395bd45ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ should change the heading of the (upcoming) version to include a major version b ## @rjsf/core - Updated `NumberField` to properly pass through the `errorSchema` and `id` in the onChange handler, fixing [#4382](https://github.com/rjsf-team/react-jsonschema-form/issues/4382) +- Fix default value population when switching between options in `MultiSchemaField` [#4375](https://github.com/rjsf-team/react-jsonschema-form/pull/4375). Fixes [#4367](https://github.com/rjsf-team/react-jsonschema-form/issues/4367) ## Dev / docs / playground @@ -35,7 +36,6 @@ should change the heading of the (upcoming) version to include a major version b ## @rjsf/core - Updated `SchemaField` to no longer make schema fields with const read-only by default, partially fixing [#4344](https://github.com/rjsf-team/react-jsonschema-form/issues/4344) -- Fix default value population when switching between options in `MultiSchemaField` [#4375](https://github.com/rjsf-team/react-jsonschema-form/pull/4375). Fixes [#4367](https://github.com/rjsf-team/react-jsonschema-form/issues/4367) ## @rjsf/utils From fad30a8234c7a473a54bc0730558457818383c08 Mon Sep 17 00:00:00 2001 From: Heath C <51679588+heath-freenome@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:57:51 -0800 Subject: [PATCH 6/6] Update CHANGELOG.md Fixed up release --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5395bd45ea..ffdce1c64c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,12 @@ should change the heading of the (upcoming) version to include a major version b --> +# 5.23.2 + +## @rjsf/core + +- Fix default value population when switching between options in `MultiSchemaField` [#4375](https://github.com/rjsf-team/react-jsonschema-form/pull/4375). Fixes [#4367](https://github.com/rjsf-team/react-jsonschema-form/issues/4367) + # 5.23.1 ## @rjsf/chakra-ui @@ -25,7 +31,6 @@ should change the heading of the (upcoming) version to include a major version b ## @rjsf/core - Updated `NumberField` to properly pass through the `errorSchema` and `id` in the onChange handler, fixing [#4382](https://github.com/rjsf-team/react-jsonschema-form/issues/4382) -- Fix default value population when switching between options in `MultiSchemaField` [#4375](https://github.com/rjsf-team/react-jsonschema-form/pull/4375). Fixes [#4367](https://github.com/rjsf-team/react-jsonschema-form/issues/4367) ## Dev / docs / playground