Skip to content

Commit

Permalink
feat: add form tests (#1089)
Browse files Browse the repository at this point in the history
* feat: add form tests

* chore: clean

* chore: clean

* refactor: TU

* refactor: TU

---------

Co-authored-by: Victor Zeinstra <zeinsta.victor@gmail.com>
Co-authored-by: Victor <victor.zeinstra@gmail.com>
  • Loading branch information
3 people authored Nov 30, 2023
1 parent 6a6ebb9 commit b0aa4b5
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { render, screen } from "@testing-library/react";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";
import { fireEvent } from "@testing-library/react";

import { AnswerForm } from "../AnswerForm";
import { AnswerWithStatus } from "../answer.query";
Expand Down Expand Up @@ -44,16 +46,17 @@ jest.mock("next/router", () => {
events: {
emit: jest.fn(),
on: jest.fn(),
off: jest.fn(),
},
})),
};
});

const answerBase: AnswerWithStatus = {
id: "369336d2-994f-48b1-b6ac-fec78cff240e",
questionId: "2c820037-62bd-4c0e-a1a8-ca80b97b5958",
id: "",
questionId: "",
agreementId: "0000",
content: "",
content: "content",
contentType: "ANSWER",
updatedAt: "2023-09-29T14:09:52.01401+00:00",
contentServicePublicCdtnId: null,
Expand All @@ -70,11 +73,61 @@ const answerBase: AnswerWithStatus = {
},
answerComments: [],
statuses: [],
kaliReferences: [],
legiReferences: [],
otherReferences: [],
cdtnReferences: [],
contentFichesSpDocument: null,
kaliReferences: [
{
label: "kaliRef1",
kaliArticle: {
label: "kaliArt1",
},
},
{
label: "kaliRef2",
kaliArticle: {
label: "kaliArt2",
},
},
],
legiReferences: [
{
legiArticle: { cid: "1", id: "1", label: "legiArticle1" },
},
{
legiArticle: { cid: "2", id: "2", label: "legiArticle2" },
},
],
otherReferences: [
{
label: "otherReferences1",
url: "http://otherReferences1.fr",
},
{
label: "otherReferences2",
},
],
cdtnReferences: [
{
document: {
cdtnId: "1",
slug: "1",
source: "information",
title: "reference1",
},
},
{
document: {
cdtnId: "2",
slug: "2",
source: "information",
title: "reference2",
},
},
],
contentFichesSpDocument: {
cdtnId: "1",
slug: "1",
source: "",
title: "ficheSP",
},
status: {
id: "",
status: "TODO",
Expand All @@ -89,18 +142,43 @@ const answerBase: AnswerWithStatus = {
updateDate: "29/09/2023",
};

describe("Given a component AnswerForm and a basic default generic answer", () => {
beforeEach(() => {
render(
<AnswerForm
answer={answerBase}
onSubmit={() => {
return Promise.resolve();
}}
/>
const onSubmit = jest.fn(() => Promise.resolve());

describe("AnswerForm", () => {
test("Vérifier l'affichage du contenu", () => {
render(<AnswerForm answer={answerBase} onSubmit={onSubmit} />);
expect(screen.queryByText("content")).toBeInTheDocument();

const spInput = screen.getByLabelText("Fiche service-public");
expect(spInput?.closest("input")?.value).toContain("ficheSP");

const cdtInput = screen.queryByLabelText(
"Références liées au code du travail"
);
expect(cdtInput?.parentElement?.innerHTML).toContain("legiArticle1");
expect(cdtInput?.parentElement?.innerHTML).toContain("legiArticle2");

const [nameInput1, nameInput2] = screen.queryAllByLabelText("Nom");
expect(nameInput1?.closest("input")?.value).toContain("otherReferences1");
expect(nameInput2?.closest("input")?.value).toContain("otherReferences2");
const [linkInput1] = screen.queryAllByLabelText("Lien");
expect(linkInput1?.closest("input")?.value).toContain(
"http://otherReferences1.fr"
);

const linkedContentInput = screen.queryByLabelText("Contenus liés");
expect(linkedContentInput?.parentElement?.innerHTML).toContain(
"reference1"
);
expect(linkedContentInput?.parentElement?.innerHTML).toContain(
"reference2"
);
});
test("Check options are displayed", () => {

test("Vérifier l'affichage des options", () => {
const { rerender } = render(
<AnswerForm answer={answerBase} onSubmit={onSubmit} />
);
expect(screen.queryByText("Afficher la réponse")).toBeInTheDocument();
expect(
screen.queryByText("Utiliser la fiche service public")
Expand All @@ -111,31 +189,22 @@ describe("Given a component AnswerForm and a basic default generic answer", () =
expect(
screen.queryByText("Nous n'avons pas la réponse")
).not.toBeInTheDocument();
});
});

describe("Given a component AnswerForm and a basic default CC answer", () => {
beforeEach(() => {
const answer = {
...answerBase,
agreementId: "0016",
agreement: {
...answerBase.agreement,
id: "0016",
name: "0016",
kaliId: "0016",
},
};
render(
rerender(
<AnswerForm
answer={answer}
onSubmit={() => {
return Promise.resolve();
answer={{
...answerBase,
agreementId: "0016",
agreement: {
...answerBase.agreement,
id: "0016",
name: "0016",
kaliId: "0016",
},
}}
onSubmit={onSubmit}
/>
);
});
test("Check options are displayed", () => {
expect(screen.queryByText("Afficher la réponse")).toBeInTheDocument();
expect(
screen.queryByText("Utiliser la fiche service public")
Expand All @@ -147,4 +216,41 @@ describe("Given a component AnswerForm and a basic default CC answer", () => {
screen.queryByText("Nous n'avons pas la réponse")
).toBeInTheDocument();
});

test("Vérifier que la sauvegarde fonctionne", async () => {
render(<AnswerForm answer={answerBase} onSubmit={onSubmit} />);
fireEvent.click(screen.getByText("Sauvegarder"));
await waitFor(() => {
expect(onSubmit).toHaveBeenCalledTimes(1);
});
});

test("Vérifier l'affichage du message d'erreur pour les fiches SP", async () => {
render(<AnswerForm answer={answerBase} onSubmit={onSubmit} />);
fireEvent.click(screen.getByText("Utiliser la fiche service public"));
userEvent.clear(screen.getByLabelText("Fiche service-public"));
fireEvent.click(screen.getByText("Sauvegarder"));
expect(
await screen.findByText(/Le document doit être renseigné/)
).toBeInTheDocument();
});

test("Vérifier l'affichage du message d'erreur pour les références", async () => {
render(<AnswerForm answer={answerBase} onSubmit={onSubmit} />);
fireEvent.click(screen.getByText("Ajouter une référence"));
fireEvent.click(screen.getByText("Sauvegarder"));
const [labelRequired] = await screen.findAllByText(
/Un libellé doit être renseigné/
);
expect(labelRequired).toBeInTheDocument();
const [field] = screen.getAllByLabelText("Lien");
fireEvent.change(field!, {
target: { value: "t" },
});
fireEvent.click(screen.getByText("Sauvegarder"));
const [invalidFormat] = await screen.findAllByText(
"Le format du lien est invalide"
);
expect(invalidFormat).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export const KaliReferenceInput = ({
<Grid item xs={2} mr={2}>
<FormTextField
name={`${name}.${index}.label`}
label="Label"
label="Libellé"
control={control}
rules={{ required: true }}
size="small"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const OtherReferenceLine = ({
name={`${name}.${index}.label`}
label="Nom"
control={control}
rules={{ required: true }}
size="small"
disabled={disabled}
/>
Expand Down
35 changes: 19 additions & 16 deletions targets/frontend/src/components/contributions/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const kaliArticleSchema = z.object({
path: z.string(),
label: z
.string({ required_error: "Un libellé doit être renseigné" })
.min(1, "un label doit être renseigné"),
.min(1, "Un libellé doit être renseigné"),
agreementId: z.string(),
createdAt: z.string(),
});
Expand All @@ -69,8 +69,8 @@ export type LegiArticle = z.infer<typeof legiArticleSchema>;
export const kaliReferenceSchema = z.object({
kaliArticle: kaliArticleSchema.partial(),
label: z
.string({ required_error: "Un libellé doit être renseigner" })
.min(1, "un label doit être renseigner"),
.string({ required_error: "Un libellé doit être renseigné" })
.min(1, "Un libellé doit être renseigné"),
});
export type KaliReference = z.infer<typeof kaliReferenceSchema>;

Expand All @@ -81,22 +81,25 @@ export type LegiReference = z.infer<typeof legiReferenceSchema>;

export const otherReferenceSchema = z.object({
label: z
.string({ required_error: "un libellé doit être renseigné" })
.min(1, "un nom doit être renseigné"),
.string({ required_error: "Un libellé doit être renseigné" })
.min(1, "Un libellé doit être renseigné"),
url: z
.string({ required_error: "Une url doit être renseigné" })
.url("le format du lien est invalide")
.string()
.url("Le format du lien est invalide")
.optional()
.or(z.literal("")),
});
export type OtherReference = z.infer<typeof otherReferenceSchema>;

export const documentSchema = z.object({
title: z.string(),
cdtnId: z.string(),
source: z.string(),
slug: z.string(),
});
export const documentSchema = z.object(
{
title: z.string(),
cdtnId: z.string(),
source: z.string(),
slug: z.string(),
},
{ invalid_type_error: "Le document doit être renseigné" }
);
export type Document = z.infer<typeof documentSchema>;

export const cdtnReferenceSchema = z.object({
Expand All @@ -112,7 +115,7 @@ const answerBaseSchema = z.object({
["ANSWER", "NOTHING", "CDT", "UNFAVOURABLE", "UNKNOWN", "SP"],
{
required_error: "Un type de réponse doit être sélectionné",
invalid_type_error: " type de réponse doit être sélectionné",
invalid_type_error: "Un type de réponse doit être sélectionné",
}
),
contentServicePublicCdtnId: z.string().nullable().optional(),
Expand All @@ -124,9 +127,9 @@ export const questionBaseSchema = z.object({
id: z.string().uuid(),
content: z
.string({
required_error: "une question doit être renseigné",
required_error: "Une question doit être renseignée",
})
.min(1, "une question doit être renseigné"),
.min(1, "Une question doit être renseignée"),
order: z.number(),
message_id: z
.string({
Expand Down
6 changes: 2 additions & 4 deletions targets/frontend/src/components/forms/Autocomplete/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
TextField,
} from "@mui/material";
import { AutocompleteRenderGetTagProps } from "@mui/material/Autocomplete/Autocomplete";
import { styled } from "@mui/system";
import React, { PropsWithChildren } from "react";
import { Controller } from "react-hook-form";

Expand Down Expand Up @@ -95,7 +94,9 @@ export const FormAutocomplete = <T,>({
renderInput={(params) => (
<TextField
{...params}
id={name}
error={!!error}
helperText={error?.message}
label={label}
InputProps={{
...params.InputProps,
Expand All @@ -111,9 +112,6 @@ export const FormAutocomplete = <T,>({
/>
)}
/>
{error && error.message === "Required" ? (
<FormHelperText>Ce champ est requis</FormHelperText>
) : null}
</FormControl>
)}
/>
Expand Down
34 changes: 16 additions & 18 deletions targets/frontend/src/components/forms/TextField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,22 @@ export const FormTextField = ({
name={name}
control={control}
rules={rules}
render={({ field: { onChange, value }, fieldState: { error } }) => {
return (
<TextField
helperText={error?.message}
size={size}
error={!!error}
onChange={onChange}
value={value}
fullWidth={fullWidth}
label={label}
variant="outlined"
multiline={multiline}
disabled={disabled}
InputLabelProps={labelFixed ? { shrink: true } : {}}
id={name}
/>
);
}}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<TextField
helperText={error?.message}
size={size}
error={!!error}
onChange={onChange}
value={value}
fullWidth={fullWidth}
label={label}
variant="outlined"
multiline={multiline}
disabled={disabled}
InputLabelProps={labelFixed ? { shrink: true } : {}}
id={name}
/>
)}
/>
);
};
Loading

0 comments on commit b0aa4b5

Please sign in to comment.