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(a11y): Add labels to all feedback form inputs #2939

Merged
merged 2 commits into from
Apr 2, 2024
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
48 changes: 6 additions & 42 deletions editor.planx.uk/src/components/Feedback/FeedbackForm.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Story = StoryObj<typeof meta>;

export default meta;

export const EmptyLabelledForm: Story = {
export const EmptyForm: Story = {
args: {
inputs: [
{ id: "userContext", name: "userContext", label: "What were you doing?" },
Expand All @@ -24,17 +24,8 @@ export const EmptyLabelledForm: Story = {
},
};

export const EmptyUnlabelledForm: Story = {
args: {
inputs: [{ id: "userComment", name: "userComment" }],
handleSubmit: async (values) => {
console.log(values);
},
},
};

export const SuccessfulLabelledFormSubmit: Story = {
...EmptyLabelledForm,
export const SuccessfulFormSubmit: Story = {
...EmptyForm,
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

Expand All @@ -55,8 +46,8 @@ export const SuccessfulLabelledFormSubmit: Story = {
},
};

export const MissingInputLabelledForm: Story = {
...EmptyLabelledForm,
export const MissingInputForm: Story = {
...EmptyForm,
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

Expand All @@ -68,31 +59,4 @@ export const MissingInputLabelledForm: Story = {
const submitButton = canvas.getByRole("button", { name: "Send feedback" });
await userEvent.click(submitButton);
},
};

export const SuccessfulUnlabelledFormSubmit: Story = {
...EmptyUnlabelledForm,
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

const commentInput = canvas.getByLabelText("Leave your feedback");
await userEvent.type(
commentInput,
"It said I own a house but it's actually a flat.",
{ delay: 100 },
);

const submitButton = canvas.getByRole("button", { name: "Send feedback" });
await userEvent.click(submitButton);
},
};

export const MissingInputUnlabelledFormSubmit: Story = {
...EmptyUnlabelledForm,
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

const submitButton = canvas.getByRole("button", { name: "Send feedback" });
await userEvent.click(submitButton);
},
};
};
70 changes: 3 additions & 67 deletions editor.planx.uk/src/components/Feedback/FeedbackForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ import FeedbackForm from "./FeedbackForm";

const mockHandleSubmit = jest.fn();

const mockUnlabelledInput: FeedbackFormInput[] = [
{
name: "userComment",
ariaDescribedBy: "comment-title",
},
];

const mockLabelledInputs: FeedbackFormInput[] = [
{ name: "userContext", id: "userContext", label: "User Context" },
{ name: "userComment", id: "userComment", label: "User Comment" },
Expand All @@ -23,18 +16,7 @@ describe("FeedbackForm functionality", () => {
jest.clearAllMocks();
});

test("renders unlabelled input correctly", () => {
const { getByLabelText } = setup(
<FeedbackForm
inputs={mockUnlabelledInput}
handleSubmit={mockHandleSubmit}
/>,
);
const renderedInput = getByLabelText("Leave your feedback");
expect(renderedInput).toBeInTheDocument();
});

test("renders labelled inputs correctly", () => {
test("renders inputs correctly", () => {
const { getByLabelText } = setup(
<FeedbackForm
inputs={mockLabelledInputs}
Expand All @@ -47,42 +29,7 @@ describe("FeedbackForm functionality", () => {
expect(commentInput).toBeInTheDocument();
});

test("renders the feedback disclaimer with the input", () => {
const { getByText } = setup(
<FeedbackForm
inputs={mockUnlabelledInput}
handleSubmit={mockHandleSubmit}
/>,
);
expect(
getByText(
/Do not share personal or financial information in your feedback./i,
),
).toBeInTheDocument();
});

test("can submit an unlabelled input", async () => {
const { getByLabelText, getByText, user } = setup(
<FeedbackForm
inputs={mockUnlabelledInput}
handleSubmit={mockHandleSubmit}
/>,
);
await user.type(
getByLabelText("Leave your feedback"),
"This is a test comment",
);
await user.click(getByText("Send feedback"));

expect(mockHandleSubmit).toHaveBeenCalledWith(
expect.objectContaining({
userComment: "This is a test comment",
}),
expect.any(Object),
);
});

test("can submit labelled inputs", async () => {
test("can submit inputs", async () => {
const { getByLabelText, getByText, user } = setup(
<FeedbackForm
inputs={mockLabelledInputs}
Expand All @@ -109,18 +56,7 @@ describe("FeedbackForm accessibility tests", () => {
jest.clearAllMocks();
});

test("renders unlabelled inputs with no accessibility violations", async () => {
const { container } = setup(
<FeedbackForm
inputs={mockUnlabelledInput}
handleSubmit={mockHandleSubmit}
/>,
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});

test("renders labelled inputs with no accessibility violations", async () => {
test("renders inputs with no accessibility violations", async () => {
const { container } = setup(
<FeedbackForm
inputs={mockLabelledInputs}
Expand Down
24 changes: 5 additions & 19 deletions editor.planx.uk/src/components/Feedback/FeedbackForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,20 @@ function FormInputs({ inputs }: { inputs: FeedbackFormInput[] }): FCReturn {
<ErrorWrapper
key={input.name}
error={errors?.[input.name]}
id={`${input.label || input.ariaDescribedBy}-error`}
id={`${input.label}-error`}
>
{input.label ? (
<InputLabel label={input.label} htmlFor={input.id}>
<Input
required
multiline
bordered
id={input.id}
name={input.name}
value={values?.[input.name]}
onChange={handleChange}
data-testid={`${input.name}Textarea`}
/>
</InputLabel>
) : (
<InputLabel label={input.label} htmlFor={input.id}>
<Input
name={input.name}
required
multiline
bordered
aria-label={"Leave your feedback"}
aria-describedby={input.ariaDescribedBy}
id={input.id}
name={input.name}
value={values?.[input.name]}
onChange={handleChange}
data-testid={`${input.name}Textarea`}
/>
)}
</InputLabel>
</ErrorWrapper>
))}
</>
Expand Down
3 changes: 2 additions & 1 deletion editor.planx.uk/src/components/Feedback/MoreInfoFeedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ const MoreInfoFeedbackComponent: React.FC = () => {
const commentFormInputs: FeedbackFormInput[] = [
{
name: "userComment",
ariaDescribedBy: "comment-title",
label: "What's your feedback?",
id: "feedback-input",
},
];

Expand Down
11 changes: 6 additions & 5 deletions editor.planx.uk/src/components/Feedback/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@ export interface FormProps {

export type FeedbackFormInput = {
name: keyof UserFeedback;
label?: string;
id?: string;
ariaDescribedBy?: string;
label: string;
id: string;
};

const Feedback: React.FC = () => {
Expand Down Expand Up @@ -331,7 +330,8 @@ const Feedback: React.FC = () => {
const shareFormInputs: FeedbackFormInput[] = [
{
name: "userComment",
ariaDescribedBy: "idea-title",
label: "What's your idea?",
id: "share-idea-input",
},
];

Expand Down Expand Up @@ -362,7 +362,8 @@ const Feedback: React.FC = () => {
const commentFormInputs: FeedbackFormInput[] = [
{
name: "userComment",
ariaDescribedBy: "comment-title",
label: "What's you comment?",
id: "comment-input",
},
];

Expand Down
Loading