Skip to content

Commit

Permalink
Bug: Deep nested dependencies issue with assigning values to formData (
Browse files Browse the repository at this point in the history
…#4356)

* Fix deep nested dependencies issue with formData

* update changelog

---------

Co-authored-by: Abdallah Al-Soqatri <abdallah.al-soqatri@aspentech.com>
  • Loading branch information
abdalla-rko and Abdallah Al-Soqatri authored Oct 30, 2024
1 parent 8c4e726 commit 9104467
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 1 deletion.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ should change the heading of the (upcoming) version to include a major version b
-->

# 5.22.3

## @rjsf/utils

- Fixed deep nested dependencies issue with assigning values to formData, fixing [[#4334](https://github.com/rjsf-team/react-jsonschema-form/issues/4334)]

# 5.22.2

## @rjsf/core
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/schema/getDefaultFormState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
} else if (DEPENDENCIES_KEY in schema) {
// Get the default if set from properties to ensure the dependencies conditions are resolved based on it
const defaultFormData: T = {
...formData,
...getDefaultBasedOnSchemaType(validator, schema, computeDefaultsProps, defaults),
...formData,
};
const resolvedSchema = resolveDependencies<T, S, F>(
validator,
Expand Down
243 changes: 243 additions & 0 deletions packages/utils/test/schema/getDefaultFormStateTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '../../src/schema/getDefaultFormState';
import { RECURSIVE_REF, RECURSIVE_REF_ALLOF } from '../testUtils/testData';
import { TestValidatorType } from './types';
import { resolveDependencies } from '../../src/schema/retrieveSchema';

export default function getDefaultFormStateTest(testValidator: TestValidatorType) {
describe('getDefaultFormState()', () => {
Expand Down Expand Up @@ -78,9 +79,179 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
fromFormData: 'fromFormData',
});
});
it('test an object with deep nested dependencies with formData', () => {
const schema: RJSFSchema = {
type: 'object',
properties: {
nestedObject: {
type: 'object',
properties: {
first: {
type: 'string',
enum: ['no', 'yes'],
default: 'no',
},
},
dependencies: {
first: {
oneOf: [
{
properties: {
first: {
enum: ['yes'],
},
second: {
type: 'object',
properties: {
deeplyNestedThird: {
type: 'string',
enum: ['before', 'after'],
default: 'before',
},
},
},
},
},
{
properties: {
first: {
enum: ['no'],
},
},
},
],
},
},
},
},
};

// Mock isValid so that withExactlyOneSubschema works as expected
testValidator.setReturnValues({
isValid: [
true, // First oneOf... first === first
false, // Second oneOf... second !== first
],
});
expect(
getDefaultFormState(
testValidator,
schema,
{
nestedObject: {
first: 'yes',
},
},
schema,
false,
{
emptyObjectFields: 'populateAllDefaults',
allOf: 'skipDefaults',
arrayMinItems: {
populate: 'populate' as any,
mergeExtraDefaults: false,
},
mergeDefaultsIntoFormData: 'useFormDataIfPresent',
}
)
).toEqual({
nestedObject: {
first: 'yes',
second: {
deeplyNestedThird: 'before',
},
},
});
});
it('getInnerSchemaForArrayItem() item of type boolean returns empty schema', () => {
expect(getInnerSchemaForArrayItem({ items: [true] }, AdditionalItemsHandling.Ignore, 0)).toEqual({});
});
describe('resolveDependencies()', () => {
it('test an object with dependencies', () => {
const schema: RJSFSchema = {
type: 'object',
properties: {
first: {
type: 'string',
enum: ['no', 'yes'],
default: 'no',
},
},
dependencies: {
first: {
oneOf: [
{
properties: {
first: {
enum: ['yes'],
},
second: {
type: 'object',
properties: {
deeplyNestedThird: {
type: 'string',
enum: ['before', 'after'],
default: 'before',
},
},
},
},
},
{
properties: {
first: {
enum: ['no'],
},
},
},
],
},
},
};

// Mock isValid so that withExactlyOneSubschema works as expected
testValidator.setReturnValues({
isValid: [
true, // First oneOf... first === first
false, // Second oneOf... second !== first
],
});
expect(
resolveDependencies(
testValidator,
schema,
schema,
false,
[],
{
first: 'yes',
},
undefined
)
).toEqual([
{
type: 'object',
properties: {
first: {
type: 'string',
enum: ['no', 'yes'],
default: 'no',
},
second: {
type: 'object',
properties: {
deeplyNestedThird: {
type: 'string',
enum: ['before', 'after'],
default: 'before',
},
},
},
},
},
]);
});
});
describe('computeDefaults()', () => {
it('test computeDefaults that is passed a schema with a ref', () => {
const schema: RJSFSchema = {
Expand Down Expand Up @@ -401,6 +572,78 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
})
).toEqual({});
});
it('test an object with deep nested dependencies with formData', () => {
const schema: RJSFSchema = {
type: 'object',
properties: {
nestedObject: {
type: 'object',
properties: {
first: {
type: 'string',
enum: ['no', 'yes'],
default: 'no',
},
},
dependencies: {
first: {
oneOf: [
{
properties: {
first: {
enum: ['yes'],
},
second: {
type: 'object',
properties: {
deeplyNestedThird: {
type: 'string',
enum: ['before', 'after'],
default: 'before',
},
},
},
},
},
{
properties: {
first: {
enum: ['no'],
},
},
},
],
},
},
},
},
};

// Mock isValid so that withExactlyOneSubschema works as expected
testValidator.setReturnValues({
isValid: [
true, // First oneOf... first === first
false, // Second oneOf... second !== first
],
});
expect(
computeDefaults(testValidator, schema, {
rootSchema: schema,
rawFormData: {
nestedObject: {
first: 'yes',
},
},
})
).toEqual({
nestedObject: {
first: 'no',
second: {
deeplyNestedThird: 'before',
},
},
});
});
it('test computeDefaults handles an invalid property schema', () => {
const schema: RJSFSchema = {
type: 'object',
Expand Down

0 comments on commit 9104467

Please sign in to comment.