diff --git a/src/components/form/JSONSchemaForm.tsx b/src/components/form/JSONSchemaForm.tsx index 218b8c1d..3048db09 100644 --- a/src/components/form/JSONSchemaForm.tsx +++ b/src/components/form/JSONSchemaForm.tsx @@ -79,11 +79,18 @@ export const JSONSchemaFormFields = ({ Component: React.ComponentType; }; return ( - setValue(field.name, value)} - {...field} - /> + + setValue(field.name, value)} + {...field} + /> + {field.statement ? ( + + ) : null} + {field.extra ? field.extra : null} + ); } diff --git a/src/components/form/fields/FieldSetField.tsx b/src/components/form/fields/FieldSetField.tsx index 273230f3..a024b85b 100644 --- a/src/components/form/fields/FieldSetField.tsx +++ b/src/components/form/fields/FieldSetField.tsx @@ -258,16 +258,25 @@ export function FieldSetField({ Component: React.ComponentType<$TSFixMe>; }; return ( - - setValue( - isFlatFieldset ? field.name : `${name}.${field.name}`, - value, - ) - } - {...field} - /> + + + setValue( + isFlatFieldset ? field.name : `${name}.${field.name}`, + value, + ) + } + {...field} + /> + {field.statement ? ( + + ) : null} + {field.extra ? field.extra : null} + ); } @@ -294,6 +303,11 @@ export function FieldSetField({ components?.[field.inputType as keyof Components] } /> + {field.statement ? ( + + ) : null} {field.extra ? field.extra : null} ); diff --git a/src/components/form/tests/JSONSchemaFormCustomComponent.test.tsx b/src/components/form/tests/JSONSchemaFormCustomComponent.test.tsx index f2bbd0bd..3e4e2079 100644 --- a/src/components/form/tests/JSONSchemaFormCustomComponent.test.tsx +++ b/src/components/form/tests/JSONSchemaFormCustomComponent.test.tsx @@ -3,9 +3,22 @@ import { FormProvider, useForm } from 'react-hook-form'; import userEvent from '@testing-library/user-event'; import { JSONSchemaFormFields } from '@/src/components/form/JSONSchemaForm'; import { JSFCustomComponentProps } from '@/src/types/remoteFlows'; +import { StatementComponentProps } from '@/src/types/fields'; + +// Mock statement component +const MockStatement = ({ data }: StatementComponentProps) => ( +
+ {data.title &&
{data.title}
} +
{data.description}
+
+); vi.mock('@/src/context', () => ({ - useFormFields: vi.fn(() => ({ components: {} })), + useFormFields: vi.fn(() => ({ + components: { + statement: MockStatement, + }, + })), })); // Mock custom component that uses setValue @@ -144,4 +157,208 @@ describe('Custom JSF Component with setValue', () => { expect(screen.getByTestId('form-value')).toHaveTextContent('weekly'); }); }); + + it('should render statement prop alongside custom component', () => { + const TestComponent = () => { + const methods = useForm({ + defaultValues: { payment_type: '' }, + }); + + const fields = [ + { + name: 'payment_type', + label: 'Payment Type', + Component: CustomToggle, + options: [ + { value: 'monthly', label: 'Monthly' }, + { value: 'weekly', label: 'Weekly' }, + ], + statement: { + title: 'Important Notice', + description: 'Please select your preferred payment frequency.', + severity: 'info', + }, + }, + ]; + + return ( + + + + ); + }; + + render(); + + // Custom component should render + expect(screen.getByTestId('custom-toggle')).toBeInTheDocument(); + + // Statement should render alongside the custom component + expect(screen.getByTestId('mock-statement')).toBeInTheDocument(); + expect(screen.getByTestId('statement-title')).toHaveTextContent( + 'Important Notice', + ); + expect(screen.getByTestId('statement-description')).toHaveTextContent( + 'Please select your preferred payment frequency.', + ); + expect(screen.getByTestId('mock-statement')).toHaveAttribute( + 'data-severity', + 'info', + ); + }); + + it('should render extra prop alongside custom component', () => { + const ExtraContent = () => ( +
Additional info here
+ ); + + const TestComponent = () => { + const methods = useForm({ + defaultValues: { payment_type: '' }, + }); + + const fields = [ + { + name: 'payment_type', + label: 'Payment Type', + Component: CustomToggle, + options: [ + { value: 'monthly', label: 'Monthly' }, + { value: 'weekly', label: 'Weekly' }, + ], + extra: , + }, + ]; + + return ( + + + + ); + }; + + render(); + + // Custom component should render + expect(screen.getByTestId('custom-toggle')).toBeInTheDocument(); + + // Extra content should render alongside the custom component + expect(screen.getByTestId('extra-content')).toBeInTheDocument(); + expect(screen.getByTestId('extra-content')).toHaveTextContent( + 'Additional info here', + ); + }); + + it('should render statement prop alongside custom component inside fieldset', () => { + const TestComponent = () => { + const methods = useForm({ + defaultValues: { payment_info: { payment_type: '' } }, + }); + + const fields = [ + { + name: 'payment_info', + label: 'Payment Information', + description: 'Payment details', + inputType: 'fieldset' as const, + fields: [ + { + name: 'payment_type', + label: 'Payment Type', + Component: CustomToggle, + options: [ + { value: 'monthly', label: 'Monthly' }, + { value: 'weekly', label: 'Weekly' }, + ], + inputType: 'text' as const, + statement: { + title: 'Fieldset Statement Title', + description: 'This statement is inside a fieldset.', + severity: 'warning', + }, + }, + ], + isFlatFieldset: false, + variant: 'outset' as const, + }, + ]; + + return ( + + + + ); + }; + + render(); + + // Custom component should render inside fieldset + expect(screen.getByTestId('custom-toggle')).toBeInTheDocument(); + + // Statement should render alongside the custom component inside fieldset + expect(screen.getByTestId('mock-statement')).toBeInTheDocument(); + expect(screen.getByTestId('statement-title')).toHaveTextContent( + 'Fieldset Statement Title', + ); + expect(screen.getByTestId('statement-description')).toHaveTextContent( + 'This statement is inside a fieldset.', + ); + expect(screen.getByTestId('mock-statement')).toHaveAttribute( + 'data-severity', + 'warning', + ); + }); + + it('should render extra prop alongside custom component inside fieldset', () => { + const ExtraContent = () => ( +
Fieldset extra content
+ ); + + const TestComponent = () => { + const methods = useForm({ + defaultValues: { payment_info: { payment_type: '' } }, + }); + + const fields = [ + { + name: 'payment_info', + label: 'Payment Information', + description: 'Payment details', + inputType: 'fieldset' as const, + fields: [ + { + name: 'payment_type', + label: 'Payment Type', + Component: CustomToggle, + options: [ + { value: 'monthly', label: 'Monthly' }, + { value: 'weekly', label: 'Weekly' }, + ], + inputType: 'text' as const, + extra: , + }, + ], + isFlatFieldset: false, + variant: 'outset' as const, + }, + ]; + + return ( + + + + ); + }; + + render(); + + // Custom component should render inside fieldset + expect(screen.getByTestId('custom-toggle')).toBeInTheDocument(); + + // Extra content should render alongside the custom component inside fieldset + expect(screen.getByTestId('fieldset-extra')).toBeInTheDocument(); + expect(screen.getByTestId('fieldset-extra')).toHaveTextContent( + 'Fieldset extra content', + ); + }); });