From 91f4bce8b1ee2d99c1c550de1c372fa9f1f87499 Mon Sep 17 00:00:00 2001 From: Mike Heneghan Date: Fri, 23 Feb 2024 13:01:52 +0000 Subject: [PATCH 1/4] chore: add explicit data-testid to aid in testing --- editor.planx.uk/src/components/Feedback/FeedbackForm.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx b/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx index b500d143ed..bb95c41436 100644 --- a/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx +++ b/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx @@ -35,6 +35,7 @@ function FormInputs({ inputs }: { inputs: FeedbackFormInput[] }): FCReturn { name={input.name} value={values?.[input.name]} onChange={handleChange} + data-testid={`${input.name}Textarea`} /> ) : ( @@ -46,6 +47,7 @@ function FormInputs({ inputs }: { inputs: FeedbackFormInput[] }): FCReturn { aria-describedby={input.ariaDescribedBy} value={values?.[input.name]} onChange={handleChange} + data-testid={`${input.name}Textarea`} /> )} From 9d2ea6a25f8f157490a4efc860d31af1e4901737 Mon Sep 17 00:00:00 2001 From: Mike Heneghan Date: Fri, 23 Feb 2024 13:21:47 +0000 Subject: [PATCH 2/4] chore: add explicit aria-label for feedback form input --- editor.planx.uk/src/components/Feedback/FeedbackForm.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx b/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx index bb95c41436..55a5e85d1d 100644 --- a/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx +++ b/editor.planx.uk/src/components/Feedback/FeedbackForm.tsx @@ -44,6 +44,7 @@ function FormInputs({ inputs }: { inputs: FeedbackFormInput[] }): FCReturn { required multiline bordered + aria-label={"Leave your feedback"} aria-describedby={input.ariaDescribedBy} value={values?.[input.name]} onChange={handleChange} From a228bb9977f57e22ba44acb10d7e9d2aedf0f506 Mon Sep 17 00:00:00 2001 From: Mike Heneghan Date: Fri, 23 Feb 2024 13:22:49 +0000 Subject: [PATCH 3/4] chore: add id to the input view title --- .../src/components/Feedback/MoreInfoFeedback.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/editor.planx.uk/src/components/Feedback/MoreInfoFeedback.tsx b/editor.planx.uk/src/components/Feedback/MoreInfoFeedback.tsx index d69500a462..804d9333ea 100644 --- a/editor.planx.uk/src/components/Feedback/MoreInfoFeedback.tsx +++ b/editor.planx.uk/src/components/Feedback/MoreInfoFeedback.tsx @@ -107,7 +107,12 @@ const MoreInfoFeedbackComponent: React.FC = () => { return ( - + Please help us to improve this service by sharing feedback From eff4e54005c5272f00a6c5c5f7a9b1585b90dde3 Mon Sep 17 00:00:00 2001 From: Mike Heneghan Date: Fri, 23 Feb 2024 13:43:35 +0000 Subject: [PATCH 4/4] test: the MoreInfoFeedback component functionality and accessibility --- .../Feedback/MoreInfoFeedback.test.tsx | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 editor.planx.uk/src/components/Feedback/MoreInfoFeedback.test.tsx diff --git a/editor.planx.uk/src/components/Feedback/MoreInfoFeedback.test.tsx b/editor.planx.uk/src/components/Feedback/MoreInfoFeedback.test.tsx new file mode 100644 index 0000000000..60232e83d5 --- /dev/null +++ b/editor.planx.uk/src/components/Feedback/MoreInfoFeedback.test.tsx @@ -0,0 +1,155 @@ +import "@testing-library/jest-dom/extend-expect"; + +import { fireEvent, waitFor } from "@testing-library/react"; +// eslint-disable-next-line no-restricted-imports +import userEvent from "@testing-library/user-event"; +import { + getInternalFeedbackMetadata, + insertFeedbackMutation, +} from "lib/feedback"; +import React from "react"; +import { axe, setup } from "testUtils"; + +import MoreInfoFeedbackComponent from "./MoreInfoFeedback"; + +jest.mock("lib/feedback", () => { + return { + getInternalFeedbackMetadata: jest.fn(), + insertFeedbackMutation: jest.fn(), + }; +}); + +const scrollIntoView = jest.fn(); +window.Element.prototype.scrollIntoView = scrollIntoView; + +describe("MoreInfoFeedbackComponent presentation and functionality", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + // Initial load + test('Initial loads renders "Yes" and "No" buttons initially', () => { + const { getByText } = setup(); + expect(getByText("Yes")).toBeInTheDocument(); + expect(getByText("No")).toBeInTheDocument(); + }); + + test("Does not scroll into view on initial render", () => { + setup(); + expect(scrollIntoView).not.toBeCalled(); + }); + + // Sentiment selection + test("Clicking Yes input form scrolls into view", async () => { + const { getByText } = setup(); + fireEvent.click(getByText("Yes")); + expect(scrollIntoView).toBeCalled(); + await waitFor(() => { + expect( + getByText("Please help us to improve this service by sharing feedback"), + ).toBeInTheDocument(); + }); + }); + + test("Clicking No input form scrolls into view", async () => { + const { getByText } = setup(); + fireEvent.click(getByText("No")); + expect(scrollIntoView).toBeCalled(); + await waitFor(() => { + expect( + getByText("Please help us to improve this service by sharing feedback"), + ).toBeInTheDocument(); + }); + }); + + // Form submission + test("Submitting feedback changes view to thank you message", async () => { + const { getByText, getByTestId } = setup(); + + fireEvent.click(getByText("Yes")); + await waitFor(() => { + expect(getByTestId("userCommentTextarea")).toBeInTheDocument(); + }); + + await userEvent.type( + getByTestId("userCommentTextarea"), + "Great help, thanks!", + ); + + fireEvent.click(getByText("Send feedback")); + await waitFor(() => { + expect(getInternalFeedbackMetadata).toBeCalled(); + expect(insertFeedbackMutation).toBeCalled(); + }); + + await waitFor(() => { + expect(getByText("Thank you for your feedback.")).toBeInTheDocument(); + }); + }); + + /* + We use the `required` property to validate that a user can't submit an empty + comment. + + It doesn't seem to be possible to test that the Browser stops form + submit in the Jest environment. + + Checking for `required` property currently but we could add explicit + validation. + */ + test("Feedback form requires a comment before submitting", async () => { + const { getByTestId, getByText } = setup(); + + fireEvent.click(getByText("Yes")); + await waitFor(() => { + expect(getByTestId("userCommentTextarea")).toBeInTheDocument(); + }); + + expect(getByTestId("userCommentTextarea")).toHaveAttribute("required"); + }); +}); + +describe("MoreInfoFeedbackComponent accessibility", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test("Initial load should have no accessibility violations", async () => { + const { container } = setup(); + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); + + test("Form view should have no accessability violations", async () => { + const { container, getByText } = setup(); + fireEvent.click(getByText("Yes")); + + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); + + test("Thank you view should have no accessibility violations", async () => { + const { container, getByText, getByTestId } = setup( + , + ); + + fireEvent.click(getByText("Yes")); + await waitFor(() => { + expect(getByTestId("userCommentTextarea")).toBeInTheDocument(); + }); + + await userEvent.type( + getByTestId("userCommentTextarea"), + "Great help, thanks!", + ); + + fireEvent.click(getByText("Send feedback")); + + await waitFor(() => { + expect(getByText("Thank you for your feedback.")).toBeInTheDocument(); + }); + + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); +});