I'm using react-hook-form
to control my form inputs (ChakraUI inputs) and disable Submit button in case an input is invalid
Since I have a multipage form I use FormProvider
in parent component, changing validation schema depending on the current page
const currentValidationSchema = validationSchema[activeStep];
const methods = useForm({
mode: 'all',
defaultValues: DEFAULT_VALUES,
resolver: yupResolver(currentValidationSchema),
});
<FormProvider {...methods}>
<Box >{renderCurrentStep(activeStep)}</Box>
</FormProvider>
And consume it with useFormContext
in child component
const {
control,
watch,
getValues,
clearErrors,
setError,
setValue,
formState: { errors, isValid },
} = useFormContext<IOrderProductFormData>();
<Controller
control={control}
name="phoneNumber"
render={({ field: { onChange, value } }) => {
return (
<InputMask
mask="999 99 999"
onChange={onChange}
maskChar=" "
value={value}
>
{(inputProps: any) => (
<InputGroup variant="phone">
<InputLeftAddon>+1</InputLeftAddon>
<Input
type="tel"
ref={inputRef}
aria-label="phone-number"
data-testid="phone-number"
{...inputProps}
/>
</InputGroup>
)}
</InputMask>
);
}}
/>
The buttons gets disabled if the form does not pass validation but the current schema
<ArrowButton onClick={handleSendOtp} disabled={!isValid} />
The code works as expected but I'm struggling with writing unit tests to verify the button is indeed disabled when necessary.
describe('<PhoneNumber />', () => {
beforeEach(async () => {
await act(async () => {
render(
<WrapperForm>
<WrapperRouter>
<PhoneNumber {...props} />
</WrapperRouter>
</WrapperForm>
);
});
});
describe('with valid input', () => {
it('should show enabled button', async () => {
const nextPageButton = screen.getByRole('button', { name: 'chevron-right' });
fireEvent.input(screen.getByTestId('phone-number'), {
target: {
value: '22222222',
},
});
expect(nextPageButton).not.toBeDisabled();
});
});
describe('with invalid input', () => {
it('should show disabled button', async () => {
const nextPageButton = screen.getByRole('button', { name: 'chevron-right' });
fireEvent.input(screen.getByTestId('phone-number'), {
target: {
value: '0',
},
});
expect(nextPageButton).toBeDisabled();
});
});
});
The first step passes as it should with the valid value. The second one however fails with the following message
expect(element).toBeDisabled() Received element is not disabled: <button aria-label="chevron-right" class="chakra-button css-5c2176" name="chevron-right" type="button" />
For some reason, there is no disabled
attribute on the button even though it works just fine from the UI. I would appreciate some help with that