Files
openpanel/packages/react-hook-form/src/useForm/index.spec.tsx
Stefan Pejcic 8595a9f4e5 back
2024-05-08 19:58:53 +02:00

249 lines
8.0 KiB
TypeScript

import React from "react";
import { useForm } from ".";
import { HttpError } from "@refinedev/core";
import { MockJSONServer, TestWrapper, act, render, waitFor } from "../../test";
import { Route, Routes } from "react-router-dom";
import { IRefineOptions } from "@refinedev/core/dist/interfaces";
interface IPost {
title: string;
content: string;
slug: string;
category: { id: number };
tags: string[];
}
const renderForm = ({
refineCoreProps,
refineOptions,
useFormProps,
}: {
useFormProps?: any;
refineCoreProps?: any;
refineOptions?: IRefineOptions;
}) => {
const EditPage = () => {
const {
refineCore: { formLoading },
saveButtonProps,
register,
formState: { errors },
} = useForm<IPost, HttpError, IPost>({
...useFormProps,
refineCoreProps: {
resource: "posts",
...refineCoreProps,
},
});
return (
<div>
{formLoading && <p>loading</p>}
<input {...register("title")} />
{errors.title && (
<span>{errors?.title?.message?.toString()}</span>
)}
<input {...register("content")} />
{errors.content && (
<span>{errors?.content?.message?.toString()}</span>
)}
<input {...register("slug")} />
{errors.slug && (
<span>{errors?.slug?.message?.toString()}</span>
)}
<select
{...register("category.id", {
required: true,
})}
>
{["1", "2", "3"]?.map((category) => (
<option key={category} value={category}>
{category}
</option>
))}
</select>
{errors.category && (
<span>{`${errors.category?.id?.message}`}</span>
)}
<button
{...saveButtonProps}
onClick={(e) => {
saveButtonProps?.onClick(e);
}}
data-testid="refine-save-button"
type="submit"
>
save
</button>
</div>
);
};
return render(
<Routes>
<Route path="/" element={<EditPage />} />
</Routes>,
{
wrapper: TestWrapper({
options: refineOptions,
i18nProvider: {
changeLocale: () => Promise.resolve(),
getLocale: () => "en",
translate: (key: string) => {
if (key === "form.error.content") {
return "Translated content error";
}
return key;
},
},
dataProvider: {
...MockJSONServer,
update: async () => {
const error: HttpError = {
message:
"An error occurred while updating the record.",
statusCode: 400,
errors: {
title: ["Title is required"],
"category.id": ["Category is required"],
slug: true,
content: {
key: "form.error.content",
message: "Content is required",
},
},
};
return Promise.reject(error);
},
create: async () => {
const error: HttpError = {
message:
"An error occurred while creating the record.",
statusCode: 400,
slug: true,
errors: {
title: ["Title is required"],
"category.id": ["Category is required"],
slug: true,
content: {
key: "form.error.content",
message: "Content is required",
},
},
};
return Promise.reject(error);
},
},
}),
},
);
};
describe("useForm hook", () => {
it.each(["edit", "create"] as const)(
"should set %s-form errors from data provider",
async (action) => {
const onMutationError = jest.fn();
const { getByText, getByTestId } = renderForm({
refineCoreProps: {
onMutationError,
action: action,
id: action === "edit" ? "1" : undefined,
},
});
await waitFor(() => {
expect(document.body).not.toHaveTextContent("loading");
});
await act(() => {
getByTestId("refine-save-button").click();
return Promise.resolve();
});
await waitFor(() => {
expect(document.body).not.toHaveTextContent("loading");
});
expect(onMutationError).toBeCalledTimes(1);
expect(getByText("Title is required")).toBeInTheDocument();
expect(getByText("Category is required")).toBeInTheDocument();
expect(getByText("Translated content error")).toBeInTheDocument();
expect(getByText("Field is not valid.")).toBeInTheDocument();
},
);
it.each([
{
action: "edit",
disableFromRefineOption: false,
disableFromHook: true,
},
{
action: "edit",
disableFromRefineOption: true,
disableFromHook: false,
},
{
action: "create",
disableFromRefineOption: false,
disableFromHook: true,
},
{
action: "create",
disableFromRefineOption: true,
disableFromHook: false,
},
] as const)("should disable server-side validation", async (testCase) => {
const onMutationErrorMock = jest.fn();
const { getByTestId, queryByText } = renderForm({
refineOptions: {
disableServerSideValidation: testCase.disableFromRefineOption,
},
useFormProps: {
disableServerSideValidation: testCase.disableFromHook,
},
refineCoreProps: {
action: testCase.action,
onMutationError: onMutationErrorMock,
id: testCase.action === "edit" ? "1" : undefined,
},
});
await waitFor(() => {
expect(document.body).not.toHaveTextContent("loading");
});
await act(() => {
getByTestId("refine-save-button").click();
return Promise.resolve();
});
await waitFor(() => {
expect(document.body).not.toHaveTextContent("loading");
expect(onMutationErrorMock).toBeCalledTimes(1);
});
await waitFor(() => {
expect(queryByText("Title is required")).not.toBeInTheDocument();
expect(queryByText("Category is required")).not.toBeInTheDocument();
expect(
queryByText("Translated content error"),
).not.toBeInTheDocument();
expect(queryByText("Field is not valid.")).not.toBeInTheDocument();
});
});
});