import { createRef } from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { TextAreaInput } from ".";

const CLASS_NAME = "mobius-text-area__input";

describe("TextAreaInput", () => {
  it("should render without errors", () => {
    render(<TextAreaInput />);
  });

  describe("uses correct class names", () => {
    it("uses Mobius class", () => {
      render(<TextAreaInput aria-label="test" />);
      expect(screen.getByLabelText("test")).toHaveClass("mobius");
    });

    it("uses base Mobius class", () => {
      render(<TextAreaInput aria-label="test" />);
      expect(screen.getByLabelText("test")).toHaveClass(CLASS_NAME);
    });

    it("includes disabled class name", () => {
      render(<TextAreaInput aria-label="test" isDisabled />);
      expect(screen.getByLabelText("test")).toHaveClass("--is-disabled");
    });

    it("includes selected class name", () => {
      render(<TextAreaInput aria-label="test" isSelected />);
      expect(screen.getByLabelText("test")).toHaveClass("--is-selected");
    });

    it("includes custom class name", () => {
      render(<TextAreaInput aria-label="test" className="my-class" />);
      expect(screen.getByLabelText("test")).toHaveClass("my-class");
      expect(screen.getByLabelText("test")).toHaveClass(CLASS_NAME);
    });
  });

  describe("accessibility attributes", () => {
    it("forwards aria-label", () => {
      render(<TextAreaInput aria-label="Description" />);
      expect(screen.getByRole("textbox")).toHaveAttribute(
        "aria-label",
        "Description",
      );
    });

    it("forwards aria-describedby", () => {
      render(<TextAreaInput aria-describedby="help-text" />);
      expect(screen.getByRole("textbox")).toHaveAttribute(
        "aria-describedby",
        "help-text",
      );
    });

    it("sets required when isRequired", () => {
      render(<TextAreaInput isRequired />);
      expect(screen.getByRole("textbox")).toBeRequired();
    });

    it("sets readOnly when isReadOnly", () => {
      render(<TextAreaInput isReadOnly />);
      expect(screen.getByRole("textbox")).toHaveAttribute("readOnly");
    });
  });

  describe("focus", () => {
    it("is focusable via Tab", async () => {
      render(<TextAreaInput aria-label="test" />);
      await userEvent.tab();
      expect(screen.getByRole("textbox")).toHaveFocus();
    });

    it("accepts typed input", async () => {
      render(<TextAreaInput aria-label="test" />);
      const textbox = screen.getByRole("textbox");
      await userEvent.type(textbox, "hello");
      expect(textbox).toHaveValue("hello");
    });
  });

  it("forwards ref", () => {
    const ref = createRef<HTMLTextAreaElement>();
    render(<TextAreaInput ref={ref} aria-label="test" />);
    expect(ref.current).toBeInstanceOf(HTMLTextAreaElement);
  });
});
