Files
cunningham/packages/react/src/components/Forms/Input/index.spec.tsx
Nathan Vasse feea284ec8 (react) add Input component
Finally the first form component of the design system. It wraps and enhance
the native input element.
2023-04-25 11:28:32 +02:00

185 lines
6.0 KiB
TypeScript

import { render, screen } from "@testing-library/react";
import React, { useRef } from "react";
import userEvent from "@testing-library/user-event";
import { expect } from "vitest";
import { Input, InputRefType } from "components/Forms/Input/index";
import { Button } from "components/Button";
describe("<Input/>", () => {
it("renders and can type", async () => {
const user = userEvent.setup();
render(<Input label="First name" />);
const input: HTMLInputElement = screen.getByRole("textbox", {
name: "First name",
});
expect(input.value).toEqual("");
await user.type(input, "John");
expect(input.value).toEqual("John");
});
it("renders with default value and can type", async () => {
const user = userEvent.setup();
render(<Input label="First name" defaultValue="John" />);
const input: HTMLInputElement = screen.getByRole("textbox", {
name: "First name",
});
expect(input.value).toEqual("John");
await user.clear(input);
expect(input.value).toEqual("");
await user.type(input, "Paul");
expect(input.value).toEqual("Paul");
});
it("renders with moving label", async () => {
const user = userEvent.setup();
render(
<div>
<Input label="First name" />
<Input label="Second name" />
</div>
);
const input: HTMLInputElement = screen.getByRole("textbox", {
name: "First name",
});
const input2: HTMLInputElement = screen.getByRole("textbox", {
name: "Second name",
});
const label = screen.getByText("First name");
expect(Array.from(label.classList)).toContain("placeholder");
// Clicking on the input should remove the placeholder class.
await user.click(input);
expect(Array.from(label.classList)).not.toContain("placeholder");
// Writing something should remove the placeholder class too.
await user.type(input, "John");
expect(Array.from(label.classList)).not.toContain("placeholder");
// Clearing the input and focus out should add the placeholder class
await user.clear(input);
await user.click(input2);
expect(Array.from(label.classList)).toContain("placeholder");
});
it("renders with state=success", async () => {
render(<Input label="First name" state="success" />);
expect(document.querySelector(".c__field--success")).toBeInTheDocument();
expect(
document.querySelector(".c__input__wrapper--success")
).toBeInTheDocument();
});
it("renders with state=error", async () => {
render(<Input label="First name" state="error" />);
expect(document.querySelector(".c__field--error")).toBeInTheDocument();
expect(
document.querySelector(".c__input__wrapper--error")
).toBeInTheDocument();
});
it("renders disabled", async () => {
const user = userEvent.setup();
render(<Input label="First name" disabled={true} />);
const input: HTMLInputElement = screen.getByRole("textbox", {
name: "First name",
});
expect(
document.querySelector(".c__input__wrapper--disabled")
).toBeInTheDocument();
expect(input.value).toEqual("");
// Disabled inputs should not be able to type.
await user.type(input, "John");
expect(input.value).toEqual("");
});
it("renders with left icon", async () => {
render(
<Input
label="First name"
icon={<span className="material-icons">apartment</span>}
/>
);
expect(document.querySelector(".material-icons")).toBeInTheDocument();
});
it("renders with right icon", async () => {
render(
<Input
label="First name"
rightIcon={<span className="material-icons">apartment</span>}
/>
);
expect(document.querySelector(".material-icons")).toBeInTheDocument();
});
it("renders with text", async () => {
render(
<Input
label="First name"
rightIcon={<span className="material-icons">apartment</span>}
text="Some text"
/>
);
screen.getByText("Some text");
});
it("renders with text and text right", async () => {
render(
<Input
label="First name"
rightIcon={<span className="material-icons">apartment</span>}
rightText="Some text right"
/>
);
screen.getByText("Some text right");
});
it("renders with char counter", async () => {
const user = userEvent.setup();
render(<Input label="First name" charCounter={true} charCounterMax={15} />);
const input: HTMLInputElement = screen.getByRole("textbox", {
name: "First name",
});
screen.getByText("0/15");
await user.type(input, "Jo");
screen.getByText("2/15");
await user.type(input, "hn");
screen.getByText("4/15");
await user.clear(input);
screen.getByText("0/15");
});
it("forwards ref", async () => {
const user = userEvent.setup();
const Wrapper = () => {
const ref = useRef<InputRefType>(null);
return (
<div>
<Input label="First name" ref={ref} />
<Button onClick={() => ref.current?.input?.focus()}>Focus</Button>
</div>
);
};
render(<Wrapper />);
const input: HTMLInputElement = screen.getByRole("textbox", {
name: "First name",
});
expect(input).not.toHaveFocus();
await user.click(screen.getByRole("button", { name: "Focus" }));
expect(input).toHaveFocus();
});
it("works controlled", async () => {
const Wrapper = () => {
const [value, setValue] = React.useState("I am controlled");
return (
<div>
<div>Value: {value}.</div>
<Input
label="First name"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<Button onClick={() => setValue("")}>Reset</Button>
</div>
);
};
const user = userEvent.setup();
render(<Wrapper />);
const input: HTMLInputElement = screen.getByRole("textbox", {
name: "First name",
});
screen.getByText("Value: I am controlled.");
await user.type(input, "John");
screen.getByText("Value: I am controlledJohn.");
await user.clear(input);
screen.getByText("Value: .");
});
});