Skip to content

Commit c57341f

Browse files
committed
Fix deep nested dependencies issue with formData
1 parent 8c4e726 commit c57341f

File tree

2 files changed

+244
-1
lines changed

2 files changed

+244
-1
lines changed

packages/utils/src/schema/getDefaultFormState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ export function computeDefaults<T = any, S extends StrictRJSFSchema = RJSFSchema
219219
} else if (DEPENDENCIES_KEY in schema) {
220220
// Get the default if set from properties to ensure the dependencies conditions are resolved based on it
221221
const defaultFormData: T = {
222-
...formData,
223222
...getDefaultBasedOnSchemaType(validator, schema, computeDefaultsProps, defaults),
223+
...formData,
224224
};
225225
const resolvedSchema = resolveDependencies<T, S, F>(
226226
validator,

packages/utils/test/schema/getDefaultFormStateTest.ts

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from '../../src/schema/getDefaultFormState';
1010
import { RECURSIVE_REF, RECURSIVE_REF_ALLOF } from '../testUtils/testData';
1111
import { TestValidatorType } from './types';
12+
import { resolveDependencies } from '../../src/schema/retrieveSchema';
1213

1314
export default function getDefaultFormStateTest(testValidator: TestValidatorType) {
1415
describe('getDefaultFormState()', () => {
@@ -78,9 +79,179 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
7879
fromFormData: 'fromFormData',
7980
});
8081
});
82+
it('test an object with deep nested dependencies with formData', () => {
83+
const schema: RJSFSchema = {
84+
type: 'object',
85+
properties: {
86+
nestedObject: {
87+
type: 'object',
88+
properties: {
89+
first: {
90+
type: 'string',
91+
enum: ['no', 'yes'],
92+
default: 'no',
93+
},
94+
},
95+
dependencies: {
96+
first: {
97+
oneOf: [
98+
{
99+
properties: {
100+
first: {
101+
enum: ['yes'],
102+
},
103+
second: {
104+
type: 'object',
105+
properties: {
106+
deeplyNestedThird: {
107+
type: 'string',
108+
enum: ['before', 'after'],
109+
default: 'before',
110+
},
111+
},
112+
},
113+
},
114+
},
115+
{
116+
properties: {
117+
first: {
118+
enum: ['no'],
119+
},
120+
},
121+
},
122+
],
123+
},
124+
},
125+
},
126+
},
127+
};
128+
129+
// Mock isValid so that withExactlyOneSubschema works as expected
130+
testValidator.setReturnValues({
131+
isValid: [
132+
true, // First oneOf... first === first
133+
false, // Second oneOf... second !== first
134+
],
135+
});
136+
expect(
137+
getDefaultFormState(
138+
testValidator,
139+
schema,
140+
{
141+
nestedObject: {
142+
first: 'yes',
143+
},
144+
},
145+
schema,
146+
false,
147+
{
148+
emptyObjectFields: 'populateAllDefaults',
149+
allOf: 'skipDefaults',
150+
arrayMinItems: {
151+
populate: 'populate' as any,
152+
mergeExtraDefaults: false,
153+
},
154+
mergeDefaultsIntoFormData: 'useFormDataIfPresent',
155+
}
156+
)
157+
).toEqual({
158+
nestedObject: {
159+
first: 'yes',
160+
second: {
161+
deeplyNestedThird: 'before',
162+
},
163+
},
164+
});
165+
});
81166
it('getInnerSchemaForArrayItem() item of type boolean returns empty schema', () => {
82167
expect(getInnerSchemaForArrayItem({ items: [true] }, AdditionalItemsHandling.Ignore, 0)).toEqual({});
83168
});
169+
describe('resolveDependencies()', () => {
170+
it('test an object with dependencies', () => {
171+
const schema: RJSFSchema = {
172+
type: 'object',
173+
properties: {
174+
first: {
175+
type: 'string',
176+
enum: ['no', 'yes'],
177+
default: 'no',
178+
},
179+
},
180+
dependencies: {
181+
first: {
182+
oneOf: [
183+
{
184+
properties: {
185+
first: {
186+
enum: ['yes'],
187+
},
188+
second: {
189+
type: 'object',
190+
properties: {
191+
deeplyNestedThird: {
192+
type: 'string',
193+
enum: ['before', 'after'],
194+
default: 'before',
195+
},
196+
},
197+
},
198+
},
199+
},
200+
{
201+
properties: {
202+
first: {
203+
enum: ['no'],
204+
},
205+
},
206+
},
207+
],
208+
},
209+
},
210+
};
211+
212+
// Mock isValid so that withExactlyOneSubschema works as expected
213+
testValidator.setReturnValues({
214+
isValid: [
215+
true, // First oneOf... first === first
216+
false, // Second oneOf... second !== first
217+
],
218+
});
219+
expect(
220+
resolveDependencies(
221+
testValidator,
222+
schema,
223+
schema,
224+
false,
225+
[],
226+
{
227+
first: 'yes',
228+
},
229+
undefined
230+
)
231+
).toEqual([
232+
{
233+
type: 'object',
234+
properties: {
235+
first: {
236+
type: 'string',
237+
enum: ['no', 'yes'],
238+
default: 'no',
239+
},
240+
second: {
241+
type: 'object',
242+
properties: {
243+
deeplyNestedThird: {
244+
type: 'string',
245+
enum: ['before', 'after'],
246+
default: 'before',
247+
},
248+
},
249+
},
250+
},
251+
},
252+
]);
253+
});
254+
});
84255
describe('computeDefaults()', () => {
85256
it('test computeDefaults that is passed a schema with a ref', () => {
86257
const schema: RJSFSchema = {
@@ -401,6 +572,78 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType
401572
})
402573
).toEqual({});
403574
});
575+
it('test an object with deep nested dependencies with formData', () => {
576+
const schema: RJSFSchema = {
577+
type: 'object',
578+
properties: {
579+
nestedObject: {
580+
type: 'object',
581+
properties: {
582+
first: {
583+
type: 'string',
584+
enum: ['no', 'yes'],
585+
default: 'no',
586+
},
587+
},
588+
dependencies: {
589+
first: {
590+
oneOf: [
591+
{
592+
properties: {
593+
first: {
594+
enum: ['yes'],
595+
},
596+
second: {
597+
type: 'object',
598+
properties: {
599+
deeplyNestedThird: {
600+
type: 'string',
601+
enum: ['before', 'after'],
602+
default: 'before',
603+
},
604+
},
605+
},
606+
},
607+
},
608+
{
609+
properties: {
610+
first: {
611+
enum: ['no'],
612+
},
613+
},
614+
},
615+
],
616+
},
617+
},
618+
},
619+
},
620+
};
621+
622+
// Mock isValid so that withExactlyOneSubschema works as expected
623+
testValidator.setReturnValues({
624+
isValid: [
625+
true, // First oneOf... first === first
626+
false, // Second oneOf... second !== first
627+
],
628+
});
629+
expect(
630+
computeDefaults(testValidator, schema, {
631+
rootSchema: schema,
632+
rawFormData: {
633+
nestedObject: {
634+
first: 'yes',
635+
},
636+
},
637+
})
638+
).toEqual({
639+
nestedObject: {
640+
first: 'no',
641+
second: {
642+
deeplyNestedThird: 'before',
643+
},
644+
},
645+
});
646+
});
404647
it('test computeDefaults handles an invalid property schema', () => {
405648
const schema: RJSFSchema = {
406649
type: 'object',

0 commit comments

Comments
 (0)