@@ -306,7 +306,140 @@ describe('ArrayInput', () => {
306306 } )
307307 } )
308308
309- // Test 12: itemParameters prop overrides inputParam.array display flags
309+ // Test 12: Nested array sub-fields render recursively
310+ it ( 'should render nested array sub-fields (e.g., addOptions inside formInputTypes)' , ( ) => {
311+ const nestedArrayParam : InputParam = {
312+ id : 'formInputTypes' ,
313+ name : 'formInputTypes' ,
314+ label : 'Form Input Type' ,
315+ type : 'array' ,
316+ array : [
317+ { id : 'type' , name : 'type' , label : 'Type' , type : 'options' , default : 'string' } as InputParam ,
318+ { id : 'label' , name : 'label' , label : 'Label' , type : 'string' } as InputParam ,
319+ {
320+ id : 'addOptions' ,
321+ name : 'addOptions' ,
322+ label : 'Add Options' ,
323+ type : 'array' ,
324+ display : true ,
325+ array : [ { id : 'option' , name : 'option' , label : 'Option' , type : 'string' } as InputParam ]
326+ } as InputParam
327+ ]
328+ }
329+
330+ const dataWithNestedArray : NodeData = {
331+ ...mockNodeData ,
332+ inputValues : {
333+ formInputTypes : [
334+ {
335+ type : 'options' ,
336+ label : 'Color' ,
337+ addOptions : [ { option : 'Red' } , { option : 'Blue' } ]
338+ }
339+ ]
340+ }
341+ } as NodeData
342+
343+ render ( < ArrayInput inputParam = { nestedArrayParam } data = { dataWithNestedArray } onDataChange = { mockOnDataChange } /> )
344+
345+ // The parent array item renders
346+ expect ( screen . getByText ( '0' ) ) . toBeInTheDocument ( )
347+
348+ // The nested array sub-field (addOptions) is rendered via NodeInputHandler
349+ // Since our mock NodeInputHandler renders a div with data-testid, the addOptions field should appear
350+ expect ( screen . getByTestId ( 'input-handler-addOptions' ) ) . toBeInTheDocument ( )
351+ } )
352+
353+ it ( 'should hide nested array sub-fields when display is false' , ( ) => {
354+ const nestedArrayParam : InputParam = {
355+ id : 'formInputTypes' ,
356+ name : 'formInputTypes' ,
357+ label : 'Form Input Type' ,
358+ type : 'array' ,
359+ array : [
360+ { id : 'type' , name : 'type' , label : 'Type' , type : 'options' } as InputParam ,
361+ {
362+ id : 'addOptions' ,
363+ name : 'addOptions' ,
364+ label : 'Add Options' ,
365+ type : 'array' ,
366+ display : false ,
367+ array : [ { id : 'option' , name : 'option' , label : 'Option' , type : 'string' } as InputParam ]
368+ } as InputParam
369+ ]
370+ }
371+
372+ const dataWithNestedArray : NodeData = {
373+ ...mockNodeData ,
374+ inputValues : {
375+ formInputTypes : [ { type : 'string' , label : 'Name' } ]
376+ }
377+ } as NodeData
378+
379+ render ( < ArrayInput inputParam = { nestedArrayParam } data = { dataWithNestedArray } onDataChange = { mockOnDataChange } /> )
380+
381+ expect ( screen . getByTestId ( 'input-handler-type' ) ) . toBeInTheDocument ( )
382+ expect ( screen . queryByTestId ( 'input-handler-addOptions' ) ) . not . toBeInTheDocument ( )
383+ } )
384+
385+ it ( 'should use itemParameters to control nested array visibility per row' , ( ) => {
386+ const nestedArrayParam : InputParam = {
387+ id : 'formInputTypes' ,
388+ name : 'formInputTypes' ,
389+ label : 'Form Input Type' ,
390+ type : 'array' ,
391+ array : [
392+ { id : 'type' , name : 'type' , label : 'Type' , type : 'options' } as InputParam ,
393+ {
394+ id : 'addOptions' ,
395+ name : 'addOptions' ,
396+ label : 'Add Options' ,
397+ type : 'array' ,
398+ array : [ { id : 'option' , name : 'option' , label : 'Option' , type : 'string' } as InputParam ]
399+ } as InputParam
400+ ]
401+ }
402+
403+ const dataWithTwoRows : NodeData = {
404+ ...mockNodeData ,
405+ inputValues : {
406+ formInputTypes : [
407+ { type : 'options' , label : 'Color' , addOptions : [ { option : 'Red' } ] } ,
408+ { type : 'string' , label : 'Name' }
409+ ]
410+ }
411+ } as NodeData
412+
413+ // Row 0: addOptions visible (type = options)
414+ // Row 1: addOptions hidden (type = string)
415+ const itemParameters : InputParam [ ] [ ] = [
416+ [
417+ { id : 'type' , name : 'type' , label : 'Type' , type : 'options' , display : true } as InputParam ,
418+ { id : 'addOptions' , name : 'addOptions' , label : 'Add Options' , type : 'array' , display : true } as InputParam
419+ ] ,
420+ [
421+ { id : 'type' , name : 'type' , label : 'Type' , type : 'options' , display : true } as InputParam ,
422+ { id : 'addOptions' , name : 'addOptions' , label : 'Add Options' , type : 'array' , display : false } as InputParam
423+ ]
424+ ]
425+
426+ render (
427+ < ArrayInput
428+ inputParam = { nestedArrayParam }
429+ data = { dataWithTwoRows }
430+ onDataChange = { mockOnDataChange }
431+ itemParameters = { itemParameters }
432+ />
433+ )
434+
435+ // Both rows show their Type field
436+ expect ( screen . getAllByTestId ( 'input-handler-type' ) ) . toHaveLength ( 2 )
437+
438+ // Only row 0 shows addOptions (row 1 has display: false)
439+ expect ( screen . getAllByTestId ( 'input-handler-addOptions' ) ) . toHaveLength ( 1 )
440+ } )
441+
442+ // Test 13: itemParameters prop overrides inputParam.array display flags
310443 it ( 'should use itemParameters prop for field visibility when provided, ignoring inputParam.array display flags' , ( ) => {
311444 // inputParam.array has both fields with no display flag (both would show)
312445 const dataWithItem : NodeData = {
0 commit comments