Skip to content

Commit

Permalink
EES-5047: Move input/textarea useWatch usage to parent components and…
Browse files Browse the repository at this point in the history
… update tests.
  • Loading branch information
Tom Jones committed Dec 11, 2024
1 parent 22a94f2 commit 6be80fa
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,35 @@ import FormField, {
import FormTextArea from '@common/components/form/FormTextArea';
import { FormTextAreaProps } from '@common/components/form/FormBaseTextArea';
import React from 'react';
import { FieldValues } from 'react-hook-form';
import { FieldValues, useWatch } from 'react-hook-form';
import FormCharacterCount from '@common/components/form/FormCharacterCount';
import FormGroup from './FormGroup';

type Props<TFormValues extends FieldValues> = FormFieldComponentProps<
FormTextAreaProps,
TFormValues
>;

export default function FormFieldTextArea<TFormValues extends FieldValues>(
props: Props<TFormValues>,
) {
export default function FormFieldTextArea<TFormValues extends FieldValues>({
maxLength,
...props
}: Props<TFormValues>) {
const watchedValue = useWatch({ name: props.name });

if (!!maxLength && maxLength > 0) {
return (
<div className="govuk-character-count">
<FormGroup>
<FormField {...props} maxLength={maxLength} as={FormTextArea} />
<FormCharacterCount
id={props.id ?? ''}
maxLength={maxLength}
value={watchedValue}
/>
</FormGroup>
</div>
);
}

return <FormField {...props} as={FormTextArea} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,35 @@ import FormTextInput, {
FormTextInputProps,
} from '@common/components/form/FormTextInput';
import React from 'react';
import { FieldValues } from 'react-hook-form';
import { FieldValues, useWatch } from 'react-hook-form';
import FormCharacterCount from '@common/components/form/FormCharacterCount';
import FormGroup from './FormGroup';

type Props<TFormValues extends FieldValues> = FormFieldComponentProps<
FormTextInputProps,
TFormValues
>;

export default function FormFieldTextInput<TFormValues extends FieldValues>(
props: Props<TFormValues>,
) {
export default function FormFieldTextInput<TFormValues extends FieldValues>({
maxLength,
...props
}: Props<TFormValues>) {
const watchedValue = useWatch({ name: props.name });

if (!!maxLength && maxLength > 0) {
return (
<div className="govuk-character-count">
<FormGroup>
<FormField {...props} maxLength={maxLength} as={FormTextInput} />
<FormCharacterCount
id={props.id ?? ''}
maxLength={maxLength}
value={watchedValue}
/>
</FormGroup>
</div>
);
}

return <FormField {...props} as={FormTextInput} />;
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,8 @@
import FormGroup from '@common/components/form/FormGroup';
import FormCharacterCount from '@common/components/form/FormCharacterCount';
import FormBaseTextArea, {
FormTextAreaProps,
} from '@common/components/form/FormBaseTextArea';
import React from 'react';
import { useWatch } from 'react-hook-form';

export default function FormTextArea({
id,
maxLength,
name,
...props
}: FormTextAreaProps) {
const value = useWatch({ name });

if (!!maxLength && maxLength > 0) {
return (
<div className="govuk-character-count">
<FormGroup>
<FormBaseTextArea
{...props}
id={id}
maxLength={maxLength}
name={name}
/>
</FormGroup>
<FormCharacterCount id={id} maxLength={maxLength} value={value} />
</div>
);
}

return (
<FormBaseTextArea {...props} id={id} maxLength={maxLength} name={name} />
);
export default function FormTextArea(props: FormTextAreaProps) {
return <FormBaseTextArea {...props} />;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import FormBaseInput, {
FormBaseInputProps,
} from '@common/components/form/FormBaseInput';
import FormCharacterCount from '@common/components/form/FormCharacterCount';
import FormGroup from '@common/components/form/FormGroup';
import React from 'react';

export interface FormTextInputProps extends FormBaseInputProps {
Expand All @@ -13,24 +11,8 @@ export interface FormTextInputProps extends FormBaseInputProps {

export default function FormTextInput({
id,
maxLength,
value,
...props
}: FormTextInputProps) {
if (!!maxLength && maxLength > 0) {
return (
<div className="govuk-character-count">
<FormGroup>
<FormBaseInput
{...props}
id={id}
maxLength={maxLength}
value={value}
/>
<FormCharacterCount id={id} maxLength={maxLength} value={value} />
</FormGroup>
</div>
);
}
return <FormBaseInput id={id} {...props} value={value} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import FormFieldTextArea from '@common/components/form/FormFieldTextArea';
import FormProvider from '@common/components/form/FormProvider';
import { render, screen } from '@testing-library/react';
import noop from 'lodash/noop';
import React from 'react';

describe('FormFieldTextArea', () => {
describe('maxLength', () => {
test('shows a character count message when `maxLength` is above 0', () => {
render(
<FormProvider>
<FormFieldTextArea
id="test-input"
label="Test input"
name="testInput"
maxLength={10}
/>
</FormProvider>,
);

expect(
screen.getByText('You have 10 characters remaining'),
).toBeInTheDocument();
});

test('aria-describedby contains the character count message id when `maxLength` is above 0', () => {
render(
<FormProvider>
<FormFieldTextArea
id="test-input"
label="Test input"
name="testInput"
maxLength={10}
/>
</FormProvider>,
);

const ariaDescribedBy = screen
.getByLabelText('Test input')
.getAttribute('aria-describedby');

expect(
screen.getByText('You have 10 characters remaining'),
).toHaveAttribute('id', 'test-input-info');
expect(ariaDescribedBy).toContain('test-input-info');
});

test('does not show a character count message when `maxLength` is below 0', () => {
render(
<FormProvider>
<FormFieldTextArea
id="test-input"
label="Test input"
name="testInput"
maxLength={-1}
/>
</FormProvider>,
);

expect(
screen.queryByText(/You have .+ characters remaining/),
).not.toBeInTheDocument();
});

test('does not show a character count message when `maxLength` is 0', () => {
render(
<FormProvider>
<FormFieldTextArea
id="test-input"
label="Test input"
name="testInput"
maxLength={0}
/>
</FormProvider>,
);

expect(
screen.queryByText(/You have .+ characters remaining/),
).not.toBeInTheDocument();
});

test('shows correct character count message when difference to `maxLength` is 1', () => {
render(
<FormProvider initialValues={{ testInput: 'aaa' }}>
<FormFieldTextArea
id="test-input"
label="Test input"
name="testInput"
maxLength={4}
onChange={noop}
/>
</FormProvider>,
);

expect(
screen.getByText('You have 1 character remaining'),
).toBeInTheDocument();
});

test('shows correct character count message when difference to `maxLength` is 0', () => {
render(
<FormProvider initialValues={{ testInput: 'aaaa' }}>
<FormFieldTextArea
id="test-input"
label="Test input"
name="testInput"
maxLength={4}
onChange={noop}
/>
</FormProvider>,
);

expect(
screen.getByText('You have 0 characters remaining'),
).toBeInTheDocument();
});

test('shows correct character count message when difference to `maxLength` is -1', () => {
render(
<FormProvider initialValues={{ testInput: 'aaaaa' }}>
<FormFieldTextArea
id="test-input"
label="Test input"
name="testInput"
maxLength={4}
onChange={noop}
/>
</FormProvider>,
);

expect(
screen.getByText('You have 1 character too many'),
).toBeInTheDocument();
});
});
});
Loading

0 comments on commit 6be80fa

Please sign in to comment.