import { fireEvent, render, waitFor } from "@testing-library/react";
import { ContextScope } from "@reins/utils";

import { FormAdapter } from "utils";
import { Form } from "../form";

describe("Form [ Rendering ]", () => {
  const initialValues = {
    name: "name",
    email: "email",
    password: "password",
  };
  const form = new FormAdapter(initialValues);
  const formContexts = new ContextScope("Form").createContext("FormProvider", { form });

  const [FormProvider] = formContexts.getContext("FormProvider");

  const Provider = (props: Omit<Parameters<typeof FormProvider.Provider>[0], "__context">) => (
    <FormProvider.Provider {...props} __context={formContexts} />
  );
  const onSubmit = jest.fn();
  let rerenders = 0;

  const App = () => {
    rerenders += 1;
    return (
      <Form formAdapter={form} Provider={Provider} onSubmit={onSubmit}>
        <button data-testid="submit" type="submit">
          Submit
        </button>
      </Form>
    );
  };

  beforeEach(() => {
    form.reset();
    onSubmit.mockClear();
    rerenders = 0;
  });
  it("should render Form only once when values change", async () => {
    const { getByTestId } = render(<App />);
    const submit = getByTestId("submit");
    fireEvent.click(submit);
    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalledTimes(1);
    });
    expect(rerenders).toBe(1);
  });
  it("should render Form only once", async () => {
    const { getByTestId } = render(<App />);
    form.setFieldValue("name", "new name");
    form.setFieldValue("email", "new email");
    form.setFieldValue("password", "new password");
    const submit = getByTestId("submit");
    fireEvent.click(submit);
    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalledTimes(1);
    });
    expect(rerenders).toBe(1);
  });
});
