I have a testStep component, a step that can be edited separately and the save button is inside testStep, but this testStep component is mapped inside testDetails component to create multiple new steps and the save button is on the testDetails component. Using formik to handle the teststep component edit changes. I am confused about how to implement same for testDetails also.
testDetails.tsx
const testStepSchema = Yup.object().shape({
testStepId: Yup.number().notRequired(),
type: Yup.string().oneOf(allActionTypes, 'Invalid type').required('Type is required'),
value: Yup.string().when('type', {
is: (type: string) => typesRequiringValue.includes(type),
then: Yup.string().required('Value is required'),
otherwise: Yup.string().notRequired(),
}),
mandatory: Yup.boolean().required('Mandatory field is required'),
elements: Yup.array().when('type', {
is: (type: string) => typesRequiringElements.includes(type),
then: Yup.array()
.of(
Yup.object().shape({
element: Yup.string()
.required('Element is required')
.test('not-empty', 'Element cannot be an empty', (value) => value?.trim() !== ''),
})
)
.required('Elements are required')
.min(1, 'At least one element is required'),
otherwise: Yup.array().notRequired(),
}),
notes: Yup.string().nullable(),
});
const validationSchema = Yup.object().shape({
testSteps: Yup.array().of(testStepSchema),
});
const initialValues = {
testSteps: [],
};
{newStep.map((step, index) => {
const lastPosition = testDetail
? testDetail.testStepDetails.length + index + 1
: index;
return (
<div key={step.testStepId} className='mb-4'>
<TestStep
testStep={step}
startUrl={''}
stepPosition={lastPosition}
status={TestStepStatus.CREATE}
testId={testId}
onUpdateNewStep={(updatedStep: TestStepResponse) =>
updateStepItem(index, updatedStep)
}
onDeleteStep={() => handleDeleteStep(index)}
/>
</div>
);
})}
<div className='d-flex flex-column flex-md-row justify-content-between'>
<div className='w-60 mb-3 mb-md-0'>
<GlobalButton
buttonText={formatMessage({ id: 'Add steps' })}
buttonType={ButtonTypes.SECONDARY}
onButtonClick={handleAddStep}
isImage={true}
alt='plus icon'
src={toAbsoluteUrl('/media/automation/test/addstep.svg')}
/>
</div>
{newStep.length > 0 && (
<div className='d-flex justify-content-md-end gap-4 my-3 my-md-0'>
<GlobalButton
buttonText={formatMessage({ id: 'Cancel' })}
buttonType={ButtonTypes.SECONDARY}
onButtonClick={() => {
setNewStep([]);
}}
/>
<GlobalButton
buttonText={formatMessage({ id: 'Save' })}
buttonType={ButtonTypes.PRIMARY}
onButtonClick={handleAddStepsInTest}
isLoading={loader}
isDisable={isDisable}
/>
</div>
)}
</div>
testStep.tsx
const renderEditElements = (type: string, formik: any) => {
return(
<BWInput
fieldName='value'
formik={formik}
fieldType={containsPasswordInput ? InputTypes.PASSWORD : InputTypes.TEXT}
placeholder={formatMessage({ id: 'Input value' })}
isRequired={true}
/>)
}
<Formik
initialValues={initialStep}
validationSchema={testStepSchema}
onSubmit={(values) => {
handleModifySingleStep(values);
}}
>
{(formik) => {
return (
<>
{ status === TestStepStatus.EDIT ||
editMode ||
status === TestStepStatus.CREATE ? (
<div className='d-flex flex-column w-100'>
{renderEditElements(step.type, formik)}
</div>
)
{editMode ? (
<>
<div className='d-flex justify-content-end gap-4 mt-5 me-3'>
<GlobalButton
buttonText={formatMessage({ id: 'Cancel' })}
buttonType={ButtonTypes.SECONDARY}
onButtonClick={() => {
setEditMode(false);
setStep(initialStep);
}}
/>
<GlobalButton
buttonText={formatMessage({ id: 'Save' })}
buttonType={ButtonTypes.PRIMARY}
onButtonClick={formik.handleSubmit}
isLoading={loader}
// isDisable={isDisable}
/>
</div>
</>
) : (
<></>
)}
</>
i have tried making field array testSteps and handling it conditionally, like giving path as testSteps[index].value instead of value when the create mode is activated, but the code is breaking, giving undefined errors something and I am not able to console.log the values after I click save for multiple teststeps.