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

test: feedback component unit tests #3937

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
918afc6
Clarify how-to doc
jamdelion Oct 28, 2024
576087e
Reorganise Feedback folder
jamdelion Oct 29, 2024
abcc570
Use latest planx-core hash
jamdelion Oct 29, 2024
9a12ba4
Use types.feedback
jamdelion Oct 29, 2024
b559588
Add types.feedback to more places
jamdelion Oct 29, 2024
20cba62
Fix import
jamdelion Oct 29, 2024
2e225b5
Add to preview node
jamdelion Oct 29, 2024
8ecfd4f
Add feedback to summaryList
jamdelion Oct 29, 2024
01187ec
Update doc
jamdelion Oct 29, 2024
de19573
Add basic editor test
jamdelion Oct 30, 2024
96a9872
Improve editor modal with more fields - not wired up yet
jamdelion Oct 30, 2024
637fa91
Add feature flag for dropdown menu
jamdelion Oct 30, 2024
40393bd
Update props
jamdelion Oct 30, 2024
7ff31e4
Render richtextinputs ok with reactorhtml component
jamdelion Oct 30, 2024
70648bc
Use placeholders if no inputs given
jamdelion Oct 30, 2024
c5ed74a
Remove validation line
jamdelion Oct 30, 2024
26bc608
Merge branch 'main' into jh/feedback-editor-side
jamdelion Oct 30, 2024
79e2377
Fixes after merge conflict
jamdelion Oct 30, 2024
d224f21
Merge branch 'main' into jh/follow-on-feedback-component
jamdelion Nov 1, 2024
ae23fc7
Make facebox text lowercase and improve storybook
jamdelion Nov 1, 2024
9f39ac9
Merge branch 'main' into jh/follow-on-feedback-component
jamdelion Nov 1, 2024
478a8cd
Reverse inappropriate linting
jamdelion Nov 1, 2024
a1d3e60
Add moreInfo component propbs into public view and update doc
jamdelion Nov 1, 2024
50c0c58
Use shared disclaimer component
jamdelion Nov 1, 2024
779d7be
Use defaultContent obj instead of placeholders
jamdelion Nov 1, 2024
015867c
Use Input instead of richtextinput in public view
jamdelion Nov 1, 2024
47d51bc
add aria label
jamdelion Nov 4, 2024
cc587ee
Merge branch 'main' into jh/follow-on-feedback-component
jamdelion Nov 4, 2024
38d134c
Merge branch 'main' into jh/follow-on-feedback-component
jamdelion Nov 4, 2024
0cb581e
On submit add to feedback table and breadcrumbs
jamdelion Nov 6, 2024
9d4fbe9
Merge branch 'main' into jh/follow-on-feedback-component
jamdelion Nov 6, 2024
7e7eb05
Fix unit test
jamdelion Nov 6, 2024
adeb9da
Fix type issue
jamdelion Nov 6, 2024
d380647
Add feedback log category for component feedback
jamdelion Nov 6, 2024
a8380f9
Undo changes to tables.yaml
jamdelion Nov 7, 2024
0fd922b
Merge branch 'main' into jh/follow-on-feedback-component
jamdelion Nov 7, 2024
fc55b80
style: Feedback component style refinement (#3925)
ianjon3s Nov 11, 2024
0aba609
Minor edits from PR comments - delete unneccessary code
jamdelion Nov 11, 2024
aa19903
Change feedback field to userComment
jamdelion Nov 11, 2024
72f3da8
Use capitlize type utility
jamdelion Nov 11, 2024
637f525
Change feedback_score column to number
jamdelion Nov 11, 2024
bb6f614
Add down.sql for add feedback_score column as int
jamdelion Nov 11, 2024
22fdc80
Fix disclaimer and default fallbacks
jamdelion Nov 11, 2024
bc4d4d8
Remove fallback in disclaimer
jamdelion Nov 11, 2024
119dd0a
Initial tests and notes
jamdelion Nov 12, 2024
63bd97e
Validate feedback required and show error messages
jamdelion Nov 12, 2024
a7c17ce
Refactor public tests to use describe.each
jamdelion Nov 12, 2024
5ea67fc
Add keyboard navigation test
jamdelion Nov 12, 2024
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
4 changes: 2 additions & 2 deletions editor.planx.uk/docs/adding-a-new-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function SetValueComponent(props: Props) {
}
```

5. `Public.tsx`
5. `Public.tsx` - note the props below are needed to display the 'More Information' sidebar correctly.

```typescript
import { PublicProps } from "@planx/components/shared/types";
Expand Down Expand Up @@ -156,4 +156,4 @@ function isTypeForBopsPayload(type?: TYPES) {
// ...
}
}
```
```
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import { setup } from "testUtils";
import { FeedbackEditor } from "./Editor";

describe("When the Feedback editor modal is rendered", () => {
it("does not throw an error", () => {
beforeEach(() => {
setup(
<DndProvider backend={HTML5Backend}>
<FeedbackEditor id="test-feedback-editor" />
</DndProvider>,
);
});
it("does not throw an error", () => {
expect(screen.getByText("Feedback")).toBeInTheDocument();
});
it("displays the default title if no edits are made", () => {
expect(
screen.getByPlaceholderText("Tell us what you think"),
).toBeInTheDocument();
});
});
29 changes: 15 additions & 14 deletions editor.planx.uk/src/@planx/components/Feedback/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,13 @@ import RichTextInput from "ui/editor/RichTextInput/RichTextInput";
import Input from "ui/shared/Input/Input";
import InputRow from "ui/shared/InputRow";

import {
descriptionPlaceholder,
disclaimerPlaceholder,
freeformQuestionPlaceholder,
ratingQuestionPlaceholder,
titlePlaceholder,
} from "../components/placeholders";
import { defaultContent } from "../components/defaultContent";
import { Feedback, parseFeedback } from "../model";

type FeedbackEditorProps = EditorProps<TYPES.Feedback, Feedback>;

const HTML_TAG_REGEX = /<[^>]*>/g;

export const FeedbackEditor = (props: FeedbackEditorProps) => {
const formik = useFormik<Feedback>({
initialValues: parseFeedback(props.node?.data),
Expand All @@ -47,9 +43,9 @@ export const FeedbackEditor = (props: FeedbackEditorProps) => {
<InputLabel label="Title">
<Input
format="large"
placeholder={titlePlaceholder}
placeholder={defaultContent.title}
name="title"
value={formik.values.title || titlePlaceholder}
value={formik.values.title}
onChange={formik.handleChange}
/>
</InputLabel>
Expand All @@ -58,7 +54,7 @@ export const FeedbackEditor = (props: FeedbackEditorProps) => {
<InputLabel label="Description" htmlFor="description">
<RichTextInput
name="description"
value={formik.values.description || descriptionPlaceholder}
value={formik.values.description}
placeholder="Description"
onChange={formik.handleChange}
/>
Expand All @@ -68,7 +64,10 @@ export const FeedbackEditor = (props: FeedbackEditorProps) => {
<InputRow>
<InputLabel label="Rating question" htmlFor="ratingQuestion">
<RichTextInput
placeholder={ratingQuestionPlaceholder}
placeholder={defaultContent.ratingQuestion?.replaceAll(
HTML_TAG_REGEX,
"",
)}
name="ratingQuestion"
value={formik.values.ratingQuestion}
onChange={formik.handleChange}
Expand All @@ -78,7 +77,10 @@ export const FeedbackEditor = (props: FeedbackEditorProps) => {
<InputRow>
<InputLabel label="Freeform question" htmlFor="freeformQuestion">
<RichTextInput
placeholder={freeformQuestionPlaceholder}
placeholder={defaultContent.freeformQuestion?.replaceAll(
HTML_TAG_REGEX,
"",
)}
name="freeformQuestion"
value={formik.values.freeformQuestion}
onChange={formik.handleChange}
Expand All @@ -89,8 +91,7 @@ export const FeedbackEditor = (props: FeedbackEditorProps) => {
<InputLabel label="Disclaimer text" htmlFor="disclaimer">
<RichTextInput
name="disclaimer"
value={formik.values.disclaimer || disclaimerPlaceholder}
placeholder={disclaimerPlaceholder}
value={formik.values.disclaimer}
onChange={formik.handleChange}
/>
</InputLabel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { Meta, StoryObj } from "@storybook/react";
import React from "react";

import { FeedbackEditor } from "./Editor";

const meta = {
title: "Editor Components/Feedback",
component: FeedbackEditor,
} satisfies Meta<typeof FeedbackEditor>;

type Story = StoryObj<typeof meta>;
export default meta;

export const Basic = {
render: () => <FeedbackEditor />,
} satisfies Story;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Meta, StoryObj } from "@storybook/react";

import { defaultContent } from "../components/defaultContent";
import Public from "./Public";

const meta = {
Expand All @@ -12,8 +13,5 @@ type Story = StoryObj<typeof meta>;
export default meta;

export const Basic = {
args: {
title: "Tell us what you think",
feedbackRequired: false,
},
args: defaultContent,
} satisfies Story;

This file was deleted.

158 changes: 101 additions & 57 deletions editor.planx.uk/src/@planx/components/Feedback/Public/Public.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,63 @@
import Box from "@mui/material/Box";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import { Disclaimer } from "@planx/components/shared/Disclaimer";
import Card from "@planx/components/shared/Preview/Card";
import { CardHeader } from "@planx/components/shared/Preview/CardHeader/CardHeader";
import type { PublicProps } from "@planx/components/shared/types";
import { FeedbackView } from "components/Feedback/types";
import { useFormik } from "formik";
import {
getInternalFeedbackMetadata,
insertFeedbackMutation,
} from "lib/feedback";
import React from "react";
import RichTextInput from "ui/editor/RichTextInput/RichTextInput";
import TerribleFace from "ui/images/feedback_filled-01.svg";
import PoorFace from "ui/images/feedback_filled-02.svg";
import NeutralFace from "ui/images/feedback_filled-03.svg";
import GoodFace from "ui/images/feedback_filled-04.svg";
import ExcellentFace from "ui/images/feedback_filled-05.svg";
import InputLabel from "ui/public/InputLabel";
import ErrorWrapper from "ui/shared/ErrorWrapper";
import Input from "ui/shared/Input/Input";
import ReactMarkdownOrHtml from "ui/shared/ReactMarkdownOrHtml/ReactMarkdownOrHtml";

import { getPreviouslySubmittedData, makeData } from "../../shared/utils";
import { FaceBox } from "../components/FaceBox";
import { Feedback, FormProps } from "../model";
import { createFeedbackSchema, Feedback, FormProps } from "../model";
import { StyledToggleButtonGroup } from "../styled";

export const PASSPORT_FEEDBACK_KEY = "_feedback";

const FeedbackComponent = (props: PublicProps<Feedback>): FCReturn => {
const feedbackDataSchema = createFeedbackSchema(props.feedbackRequired);

const handleSubmitFeedback = async (values: FormProps) => {
const metadata = await getInternalFeedbackMetadata();
const data = {
...metadata,
...values,
feedbackType: "component" as FeedbackView,
};
const submitFeedbackResult = await insertFeedbackMutation(data).catch(
(err) => {
console.error(err);
},
);
props.handleSubmit?.(makeData(props, values, PASSPORT_FEEDBACK_KEY));
if (!submitFeedbackResult) {
return;
}
};

const formik = useFormik<FormProps>({
initialValues: getPreviouslySubmittedData(props) ?? {
feedbackScore: "",
feedback: "",
},
onSubmit: (values) => {
props.handleSubmit?.(makeData(props, values));
userComment: "",
},
onSubmit: handleSubmitFeedback,
validateOnBlur: false,
validateOnChange: false,
validationSchema: feedbackDataSchema,
});

const handleFeedbackChange = (
Expand All @@ -42,13 +71,18 @@ const FeedbackComponent = (props: PublicProps<Feedback>): FCReturn => {

return (
<Card handleSubmit={formik.handleSubmit}>
<CardHeader title={props.title} />
<CardHeader
title={props.title}
info={props.info}
policyRef={props.policyRef}
howMeasured={props.howMeasured}
/>
<ReactMarkdownOrHtml
source={props.description}
id={"DESCRIPTION_TEXT"}
openLinksOnNewTab
/>
<Box pt={2} mb={3}>
<Box my={4}>
{props.ratingQuestion && (
<InputLabel
label={
Expand All @@ -60,47 +94,54 @@ const FeedbackComponent = (props: PublicProps<Feedback>): FCReturn => {
}
/>
)}
<StyledToggleButtonGroup
value={formik.values.feedbackScore}
exclusive
id="feedbackButtonGroup"
onChange={handleFeedbackChange}
aria-label="feedback score"
>
<Grid container columnSpacing={15} component="fieldset">
<FaceBox
value="1"
testId="feedback-button-terrible"
icon={TerribleFace}
label="Terrible"
altText="very unhappy face"
/>
<FaceBox
value="2"
icon={PoorFace}
label="Poor"
altText="slightly unhappy face"
/>
<FaceBox
value="3"
icon={NeutralFace}
label="Neutral"
altText="neutral face"
/>
<FaceBox
value="4"
icon={GoodFace}
label="Good"
altText="smiling face"
/>
<FaceBox
value="5"
icon={ExcellentFace}
label="Excellent"
altText="very happy face"
/>
</Grid>
</StyledToggleButtonGroup>
<ErrorWrapper error={formik.errors.feedbackScore}>
<StyledToggleButtonGroup
value={formik.values.feedbackScore}
exclusive
id="feedbackButtonGroup"
onChange={handleFeedbackChange}
aria-label="feedback score"
>
<Grid
container
columnSpacing={2}
component="fieldset"
direction={{ xs: "column", formWrap: "row" }}
>
<FaceBox
value={1}
testId="feedback-button-terrible"
icon={TerribleFace}
label="Terrible"
altText="very unhappy face"
/>
<FaceBox
value={2}
icon={PoorFace}
label="Poor"
altText="slightly unhappy face"
/>
<FaceBox
value={3}
icon={NeutralFace}
label="Neutral"
altText="neutral face"
/>
<FaceBox
value={4}
icon={GoodFace}
label="Good"
altText="smiling face"
/>
<FaceBox
value={5}
icon={ExcellentFace}
label="Excellent"
altText="very happy face"
/>
</Grid>
</StyledToggleButtonGroup>
</ErrorWrapper>
{props.freeformQuestion && (
<InputLabel
label={
Expand All @@ -112,16 +153,19 @@ const FeedbackComponent = (props: PublicProps<Feedback>): FCReturn => {
}
/>
)}
<RichTextInput
name="feedback"
value={formik.values.feedback}
placeholder="What did you think?"
<Input
multiline={true}
rows={3}
name="userComment"
value={formik.values.userComment}
bordered
onChange={formik.handleChange}
aria-label="user comment"
data-testid="user-comment"
errorMessage={formik.errors.userComment}
/>
</Box>
<Typography variant="caption">
<ReactMarkdownOrHtml source={props?.disclaimer} id={"DISCLAIMER"} />
</Typography>
{props.disclaimer && <Disclaimer text={props.disclaimer} />}
</Card>
);
};
Expand Down
Loading
Loading