Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,35 @@ describe('radio validation', () => {
).toBeInTheDocument()
})

it('disables the "Others" input when an option other than "Others" is checked', async () => {
// Arrange
const user = userEvent.setup()
const checkboxOptionLabel =
ValidationRequired.args?.schema?.fieldOptions?.[0]
if (!checkboxOptionLabel) {
throw new Error(
'Test setup: ValidationRequired story must define at least one field option',
)
}
render(<ValidationRequired />)
const othersInput = screen.getByLabelText('"Other" response')
const checkboxOption = screen.getByLabelText(checkboxOptionLabel)

// Assert
// Initially nothing is selected, so the input stays editable to allow
// typing to auto-select the "Others" option.
expect(othersInput).toBeEnabled()

// Act
// Check a non-"Others" option.
await user.click(checkboxOption)

// Assert
// "Others" input should now be greyed out (disabled) to signal that its
// content will not be submitted unless "Others" is also checked.
expect(othersInput).toBeDisabled()
})

it('renders success when unchecking some options before submitting', async () => {
// Arrange
const user = userEvent.setup()
Expand Down
13 changes: 11 additions & 2 deletions apps/frontend/src/templates/Field/Checkbox/CheckboxField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ export const CheckboxField = ({
name={checkboxInputName}
control={control}
rules={validationRules}
render={({ field: { ref, onBlur, ...field } }) => (
<CheckboxGroup {...field}>
render={({ field: { ref, onBlur, value, ...field } }) => (
<CheckboxGroup {...field} value={value}>
{fieldOptions.map((o, idx) => (
<Checkbox
name={checkboxInputName}
Expand Down Expand Up @@ -155,6 +155,15 @@ export const CheckboxField = ({
<Checkbox.OthersInput
colorScheme={fieldColorScheme}
aria-label='"Other" response'
// Grey out the "Others" input when the user has selected
// option(s) that do not include "Others", to make it clear
// that text typed here will not be submitted.
isDisabled={
schema.disabled ||
(Array.isArray(value) &&
value.length > 0 &&
!value.includes(CHECKBOX_OTHERS_INPUT_VALUE))
}
{...register(othersInputName, othersValidationRules)}
{...(isHighContrast && { variant: 'highContrast' })}
/>
Expand Down
28 changes: 28 additions & 0 deletions apps/frontend/src/templates/Field/Radio/RadioField.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,34 @@ describe('radio validation', () => {
).toBeInTheDocument()
})

it('disables the "Others" input when another option is selected', async () => {
// Arrange
const user = userEvent.setup()
const radioOption = ValidationRequired.args?.schema?.fieldOptions?.[0]
if (!radioOption) {
throw new Error(
'Test setup: ValidationRequired story must define at least one field option',
)
}
render(<ValidationRequired />)
const othersInput = screen.getByLabelText('"Other" response')
const otherRadioButton = screen.getByRole('radio', { name: /other/i })
const altRadioButton = screen.getByLabelText(radioOption)

// Act
// Select "Others" and type a custom answer; input should be editable.
await user.click(otherRadioButton)
await user.type(othersInput, 'My custom answer')
expect(othersInput).toBeEnabled()
// Switch to a different option.
await user.click(altRadioButton)

// Assert
// "Others" input should now be greyed out (disabled) to signal that its
// content will not be submitted.
expect(othersInput).toBeDisabled()
})

it('renders success when switching options before submitting', async () => {
// Arrange
const user = userEvent.setup()
Expand Down
8 changes: 7 additions & 1 deletion apps/frontend/src/templates/Field/Radio/RadioField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,13 @@ export const RadioField = ({
>
<FormControl
isRequired={schema.required}
isDisabled={schema.disabled}
// Grey out the "Others" input unless the "Others" option is
// the selected one. This makes it clear that text typed here
// will not be submitted when another option is selected.
isDisabled={
schema.disabled ||
(!!value && value !== RADIO_OTHERS_INPUT_VALUE)
}
Comment thread
eliotlim marked this conversation as resolved.
isReadOnly={isValid && isSubmitting}
isInvalid={!!get(errors, othersInputName)}
>
Expand Down
Loading