Skip to content

Commit

Permalink
test(FormBuilder): add tests to FormBuilder elements
Browse files Browse the repository at this point in the history
  • Loading branch information
ribeirojose committed Apr 28, 2024
1 parent 8f93804 commit c8aebb2
Show file tree
Hide file tree
Showing 23 changed files with 776 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/components/FormBuilder/fields/FieldArray.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export const FieldArray = withConditional<FieldArrayFieldProps>(
// eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
data-testid="remove-button"
onClick={() => handleRemove(Number(index))}
className="mt-4"
>
Expand Down
6 changes: 3 additions & 3 deletions src/components/FormBuilder/fields/HiddenField.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { FormControl, FormField } from "#/components/ui/Form";
import { FormControl, FormField, FormItem } from "#/components/ui/Form";

import { withConditional } from "../fields";

Expand All @@ -9,9 +9,9 @@ export const HiddenField = withConditional(({ form, field }) => (
name={field.name}
defaultValue={field.value}
render={({ field: formField }) => (
<FormControl>
<FormItem>
<input type="hidden" {...formField} />
</FormControl>
</FormItem>
)}
/>
));
1 change: 1 addition & 0 deletions src/components/RichTextEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export function RichTextEditor({ initialValue, onChange }) {
<div>
<Suspense fallback={<Trans>Loading</Trans>}>
<JoditEditor
data-testid="rich-text-editor"
value={initialValue}
config={{
// @ts-ignore
Expand Down
47 changes: 47 additions & 0 deletions tests/components/FormBuilder/CheckboxField.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { render, screen, fireEvent, renderHook } from "@testing-library/react";
import { FormProvider, useForm, UseFormReturn } from "react-hook-form";

import { CheckboxField, CheckboxFieldProps } from "#/components";

const TestForm = ({
field,
form,
}: {
field: CheckboxFieldProps;
form: UseFormReturn<any>;
}) => (
<FormProvider {...form}>
<CheckboxField form={form} field={field} />
</FormProvider>
);

describe("CheckboxField", () => {
it("renders a checkbox element", () => {
const field: CheckboxFieldProps = {
type: "checkbox",
name: "test",
value: "",
label: "Test Checkbox",
};
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const checkboxElement = screen.getByRole("checkbox");
expect(checkboxElement).toBeInTheDocument();
});

it("updates the form state correctly when interacted with", () => {
const field: CheckboxFieldProps = {
type: "checkbox",
name: "test",
value: "",
label: "Test Checkbox",
};
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const checkboxElement = screen.getByRole("checkbox");
fireEvent.click(checkboxElement);
expect(result.current.getValues("test")).toBe(true);
});
});
37 changes: 37 additions & 0 deletions tests/components/FormBuilder/DatePickerInput.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from "react";
import { vi, describe, it, expect } from "vitest";
import { render, screen, fireEvent, renderHook } from "@testing-library/react";
import { FormProvider, useForm } from "react-hook-form";
import { DatePickerInput } from "#/components";

const TestForm = ({ form, field }) => (
<FormProvider {...form}>
<DatePickerInput form={form} field={field} />
</FormProvider>
);

describe("DatePickerInput", () => {
it("renders a date picker input", () => {
const field = { type: "date", name: "test" };
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const datePickerElement = screen.getByText("Pick a date");
expect(datePickerElement).toBeInTheDocument();
});

it("updates the form state correctly when a date is selected", () => {
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);

const field = { type: "date", name: "test" };
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const datePickerElement = screen.getByText("Pick a date");
fireEvent.click(datePickerElement);
const dateElement = screen.getByText("10");
fireEvent.click(dateElement);
expect(result.current.getValues("test")).toStrictEqual(
new Date(2022, 0, 10)
);
});
});
64 changes: 64 additions & 0 deletions tests/components/FormBuilder/FieldArray.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { render, screen, fireEvent, renderHook } from "@testing-library/react";
import { FormProvider, useForm } from "react-hook-form";
import { FieldArray } from "#/components";

const TestForm = ({ form, field }) => (
<FormProvider {...form}>
<FieldArray form={form} field={field} />
</FormProvider>
);

describe("FieldArray", () => {
it("renders an 'Add' button", () => {
const field = {
type: "field_array",
name: "test",
defaultValues: {},
fields: [],
hasSequence: false,
};
const { result } = renderHook(() =>
useForm({ defaultValues: { [field.name]: [{ name: "John" }] } })
);

render(<TestForm field={field} form={result.current} />);
const addButton = screen.getByText("Add");
expect(addButton).toBeInTheDocument();
});

it("adds a new field when the 'Add' button is clicked", () => {
const field = {
type: "field_array",
name: "test",
label: "Test",
defaultValues: { name: "" },
fields: [{ type: "input", name: "name" }],
hasSequence: false,
};
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const addButton = screen.getByText(`Add ${field.label}`);
fireEvent.click(addButton);
expect(result.current.getValues(field.name)).toHaveLength(1);
});

it("removes a field when the remove button is clicked", () => {
const field = {
type: "field_array",
name: "test",
defaultValues: { name: "" },
fields: [{ type: "input", name: "name" }],
hasSequence: false,
remove: true,
};
const { result } = renderHook(() =>
useForm({ defaultValues: { [field.name]: [{ name: "John" }] } })
);
render(<TestForm field={field} form={result.current} />);
const removeButton = screen.getByTestId("remove-button");
fireEvent.click(removeButton);
expect(result.current.getValues(field.name)).toHaveLength(0);
});
});
35 changes: 35 additions & 0 deletions tests/components/FormBuilder/FileUploadField.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { render, screen, fireEvent, renderHook } from "@testing-library/react";
import { FormProvider, useForm } from "react-hook-form";
import { FileUploadField } from "#/components";

const TestForm = ({ form, field }) => (
<FormProvider {...form}>
<FileUploadField form={form} field={field} />
</FormProvider>
);

describe("FileUploadField", () => {
it("renders an upload button", () => {
const field = { type: "file", name: "test", mode: "file" };
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const uploadButton = screen.getByText("Upload a file");
expect(uploadButton).toBeInTheDocument();
});

it("updates the form state when a file is uploaded", async () => {
const field = { type: "file", name: "test", mode: "file" };
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const file = new File(["test"], "test.txt", { type: "text/plain" });
const inputElement = screen.getByRole("button", { name: "Upload a file" });
Object.defineProperty(inputElement, "files", {
value: [file],
});
fireEvent.change(inputElement);

expect(result.current.getValues(field.name)).toBeInstanceOf(File);
});
});
40 changes: 40 additions & 0 deletions tests/components/FormBuilder/FormField.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// FormField.test.tsx
import React from "react";
import { describe, it, expect, vi } from "vitest";
import { render, renderHook, screen } from "@testing-library/react";
import { FormProvider, useForm } from "react-hook-form";
import { FormField } from "#/components";

describe("FormField", () => {
const renderFormField = (props) => {
const { result } = renderHook(() => useForm());
return (
<FormProvider {...result.current}>
<FormField {...props} />
</FormProvider>
);
};

it("renders the appropriate field component based on the render prop", () => {
render(
renderFormField({
name: "test",
render: ({ field }) => <input {...field} placeholder="Enter text" />,
})
);
const inputElement = screen.getByPlaceholderText("Enter text");
expect(inputElement).toBeInTheDocument();
});

it("passes the correct props to the render function", () => {
const renderMock = vi.fn();
render(renderFormField({ name: "test", render: renderMock }));
expect(renderMock).toHaveBeenCalledWith(
expect.objectContaining({
field: expect.any(Object),
fieldState: expect.any(Object),
formState: expect.any(Object),
})
);
});
});
41 changes: 41 additions & 0 deletions tests/components/FormBuilder/FormFieldProvider.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// import * as React from "react";
// import { describe, it, expect } from "vitest";
// import { render, screen, renderHook } from "@testing-library/react";
// import {
// FormFieldProvider,
// useFormFieldState,
// useFormFieldUpdater,
// } from "#/components";

// describe("FormFieldProvider", () => {
// it("correctly initializes the field state with the provided name", () => {
// render(
// <FormFieldProvider
// name="test"
// render={({ field }) => <div {...field} data-testid="child" />}
// />
// );
// const childElement = screen.getByTestId("child");
// expect(childElement).toBeInTheDocument();
// });

// it("provides the field state and updater function to its children", () => {
// const { result } = renderHook(
// () => {
// const fieldState = useFormFieldState();
// const setFieldState = useFormFieldUpdater();
// return { fieldState, setFieldState };
// },
// {
// wrapper: ({ children }) => (
// <FormFieldProvider
// name="test"
// render={({ field }) => <div>{children}</div>}
// />
// ),
// }
// );
// expect(result.current.fieldState.name).toBe("test");
// expect(typeof result.current.setFieldState).toBe("function");
// });
// });
21 changes: 21 additions & 0 deletions tests/components/FormBuilder/HiddenField.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { render, renderHook } from "@testing-library/react";
import { FormProvider, useForm } from "react-hook-form";
import { HiddenField } from "#/components";

const TestForm = ({ form, field }) => (
<FormProvider {...form}>
<HiddenField form={form} field={field} />
</FormProvider>
);

describe("HiddenField", () => {
it("renders a hidden input field", () => {
const field = { type: "hidden", name: "test", value: "hiddenValue" };
const { result } = renderHook(() => useForm());
render(<TestForm field={field} form={result.current} />);
const hiddenInput = result.current.getValues("test");
expect(hiddenInput).toBe("hiddenValue");
});
});
49 changes: 49 additions & 0 deletions tests/components/FormBuilder/InputField.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from "react";
import { describe, it, expect } from "vitest";
import { render, screen, fireEvent, renderHook } from "@testing-library/react";
import { FormProvider, useForm } from "react-hook-form";
import { InputField } from "#/components";

const TestForm = ({ field }) => {
const form = useForm();
return (
<FormProvider {...form}>
<InputField form={form} field={field} />
</FormProvider>
);
};

describe("InputField", () => {
it("renders an input element", () => {
const field = { type: "input", name: "test" };
render(<TestForm field={field} />);
const inputElement = screen.getByRole("textbox");
expect(inputElement).toBeInTheDocument();
});

// it("applies the appropriate validation rules", () => {
// const field = { type: "input", name: "test", required: true };
// render(<TestForm field={field} />);
// const inputElement = screen.getByRole("textbox");
// fireEvent.change(inputElement, { target: { value: "" } });
// expect(inputElement).toBeInvalid();
// });

it("updates the form state correctly when interacted with", () => {
const field = {
type: "input",
name: "test",
value: "",
mode: "text",
} as const;
const { result } = renderHook(() => useForm());
render(
<FormProvider {...result.current}>
<InputField form={result.current} field={field} />
</FormProvider>
);
const inputElement = screen.getByRole("textbox");
fireEvent.change(inputElement, { target: { value: "Test value" } });
expect(result.current.getValues("test")).toBe("Test value");
});
});
Loading

0 comments on commit c8aebb2

Please sign in to comment.