Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(FormGroupLabel): enable screenreaders to read a label's "optional" text #2996

Merged
merged 14 commits into from
Jan 15, 2025
Merged
13 changes: 2 additions & 11 deletions packages/gamut/src/Form/__tests__/FormGroup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const renderView = setupRtl(FormGroup, {

const label = 'up dog';
const htmlFor = 'up-dog';
const optional = '(optional)';
const optionalLabelText = `${label} (optional)`;

describe('FormGroup', () => {
Expand All @@ -19,22 +18,14 @@ describe('FormGroup', () => {

view.getByLabelText(optionalLabelText);
});
it('render (optional) as aria-hidden', async () => {
const { view } = renderView({ label, htmlFor });
expect(view.getByText(optional)).toHaveAttribute('aria-hidden', 'true');
});

});
describe('when htmlFor is not provided', () => {
it('renders Label as a div', () => {
const { view } = renderView({ label });

expect(view.queryByLabelText(optionalLabelText)).toBeNull();
view.getByText(label);
});

it('render (optional) as aria-hidden', () => {
const { view } = renderView({ label });
expect(view.getByText(optional)).toHaveAttribute('aria-hidden', 'true');
view.getByText(/up dog/);
});
});

Expand Down
8 changes: 5 additions & 3 deletions packages/gamut/src/Form/elements/FormGroupLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ export const FormGroupLabel: React.FC<FormGroupLabelProps> = ({
>
{children}
{!isSoloField && (
<Text as="span" aria-hidden>
{required ? '*' : ' \u00A0(optional)'}
</Text>
required ? (
<Text as="span" aria-hidden>*</Text>
) : (
'\u00A0(optional)'
)
)}
</Label>
{infotip && <InfoTip {...infotip} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('GridFormContent', () => {
const { view } = renderView();

view.getByLabelText('Stub Text (optional)');
view.getByRole('textbox', { name: 'Stub Text' });
view.getByRole('textbox', { name: /Stub Text/ });
});

it('gives the field access to form context and validation', async () => {
Expand All @@ -34,7 +34,7 @@ describe('GridFormContent', () => {
mode: 'onChange',
});

fireEvent.input(view.getByRole('textbox', { name: 'Stub Text' }), {
fireEvent.input(view.getByRole('textbox', { name: /Stub Text/ }), {
target: {
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { setupRtl } from '@codecademy/gamut-tests';
import { fireEvent } from '@testing-library/dom';
import { act } from 'react';

import {
stubFileField,
Expand Down Expand Up @@ -48,9 +49,9 @@ describe('GridFormSections', () => {
const { view } = renderView();

const textLabel = view.getByLabelText('Stub Text (optional)');
const textField = view.getByRole('textbox', { name: 'Stub Text' });
const textField = view.getByRole('textbox', { name: /Stub Text/ });
const radioLabel = view.getByLabelText('Stub Select (optional)');
const radioField = view.getByRole('combobox', { name: 'Stub Select' });
const radioField = view.getByRole('combobox', { name: /Stub Select/ });

expect(textLabel).toBeTruthy();
expect(textField).toBeTruthy();
Expand All @@ -64,18 +65,22 @@ describe('GridFormSections', () => {
mode: 'onChange',
});

fireEvent.input(view.getByRole('textbox', { name: 'Stub Text' }), {
target: {
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
},
await act(async () => {
fireEvent.input(view.getByRole('textbox', { name: 'Stub Text' }), {
target: {
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
},
});
});

fireEvent.input(view.getByRole('textbox', { name: 'Stub Text Again' }), {
target: {
value: 'Do you know what that is?',
},
});
await act(async () => {
fireEvent.input(view.getByRole('textbox', { name: 'Stub Text Again' }), {
target: {
value: 'Do you know what that is?',
},
});
})

await view.findByText('what is it?');
await view.findByText('not enough updog');
Expand All @@ -87,17 +92,21 @@ describe('GridFormSections', () => {
mode: 'onChange',
});

fireEvent.input(view.getByRole('textbox', { name: 'Stub Text' }), {
target: {
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
},
await act(async () => {
fireEvent.input(view.getByRole('textbox', { name: 'Stub Text' }), {
target: {
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
},
});
});

fireEvent.input(view.getByRole('textbox', { name: 'Stub Text Again' }), {
target: {
value: 'Do you know what that is?',
},
await act(async () => {
fireEvent.input(view.getByRole('textbox', { name: 'Stub Text Again' }), {
target: {
value: 'Do you know what that is?',
},
});
});

expect(await view.findAllByRole('alert')).toHaveLength(1);
Expand Down
8 changes: 4 additions & 4 deletions packages/gamut/src/GridForm/__tests__/GridForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ const getBaseCases = (view: RenderResult<typeof queries, HTMLElement>) => {
name: 'Check me!',
}) as HTMLInputElement;
const selectField = view.getByRole('combobox', {
name: 'Stub Select',
name: /Stub Select/,
}) as HTMLInputElement;
const textField = view.getByRole('textbox', {
name: 'Stub Text',
name: /Stub Text/,
}) as HTMLInputElement;
return { checkboxField, selectField, textField };
};
Expand Down Expand Up @@ -257,7 +257,7 @@ describe('GridForm', () => {
},
});

const textField = view.getByRole('textbox', { name: 'Stub Text' });
const textField = view.getByRole('textbox', { name: /Stub Text/ });

await act(async () => {
fireEvent.input(textField, {
Expand All @@ -284,7 +284,7 @@ describe('GridForm', () => {
validation: 'onChange',
});

const textField = view.getByRole('textbox', { name: 'Stub Text' });
const textField = view.getByRole('textbox', { name: /Stub Text/ });

await act(async () => {
fireEvent.input(textField, {
Expand Down
Loading