import { cleanup, createEvent, fireEvent, render, screen, } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { createRef } from "react"; import assert from "node:assert"; import { describe, test, mock, afterEach, } from "node:test"; import { Input } from "./index"; import type { IInputRef } from "./index"; describe("Input", () => { afterEach(() => { cleanup(); }); /* COMMON */ test("renders input by default without crashing", () => { render(); const element = screen.getByRole("textbox"); assert.notStrictEqual(element, null); assert.strictEqual(element.tagName, "INPUT"); }); test("renders textarea when type is 'textarea'", () => { render(); const element = screen.getByRole("textbox"); assert.notStrictEqual(element, null); assert.strictEqual(element.tagName, "TEXTAREA"); }); test("renders with initial value", () => { render(); assert.strictEqual(screen.getByRole("textbox").getAttribute("value"), "test-value"); }); test("has 'data-js-input-required' attribute when isRequired", () => { render(); const input = screen.getByRole("textbox"); assert.notStrictEqual(input.getAttribute("data-js-input-required"), null); }); test("is focused then autoFocus is true", () => { render(); assert.strictEqual(document.activeElement, screen.getByRole("textbox")); }); /* HANDLERS */ test("changes value on user input", async () => { const user = userEvent.setup(); render(); const input = screen.getByRole("textbox") as HTMLInputElement; await user.type(input, "foo-boo"); assert.strictEqual(input.value, "foo-boo"); }); test("calls onChange with stateActions when value is changed", async () => { const user = userEvent.setup(); const onChange = mock.fn(); render(); await user.type(screen.getByRole("textbox"), "val"); assert.strictEqual(onChange.mock.calls.length, 3); const args = onChange.mock.calls[0]?.arguments; assert.ok(args && typeof args[0] === "object"); assert.ok("stateActions" in args[0]); }); test("calls onFocus and onBlur with stateActions", async () => { const user = userEvent.setup(); const onFocus = mock.fn(); const onBlur = mock.fn(); render(); const input = screen.getByRole("textbox"); await user.click(input); await user.tab(); assert.strictEqual(onFocus.mock.calls.length, 1); let args = onFocus.mock.calls[0]?.arguments; assert.ok(args && typeof args[0] === "object"); assert.ok("stateActions" in args[0]); assert.strictEqual(onBlur.mock.calls.length, 1); args = onBlur.mock.calls[0]?.arguments; assert.ok(args && typeof args[0] === "object"); assert.ok("stateActions" in args[0]); }); test("does not allow typing when disabled", async () => { const user = userEvent.setup(); render(); const input = screen.getByRole("textbox") as HTMLInputElement; await user.type(input, "value"); assert.strictEqual(input.value, ""); }); test("does not change value when is readonly", async () => { const user = userEvent.setup(); render(); const input = screen.getByRole("textbox") as HTMLInputElement; await user.type(input, "value"); assert.strictEqual(input.value, "foo-"); }); test("calls onReset and resets value on reset", async () => { const user = userEvent.setup(); const onReset = mock.fn((args) => { args.stateActions.setValue(""); }); render(); const input = screen.getByRole("textbox") as HTMLInputElement; await user.type(input, "boo"); assert.strictEqual(input.value, "boo"); fireEvent(input, createEvent("reset", input, { bubbles: true })); assert.strictEqual(onReset.mock.calls.length, 1); const args = onReset.mock.calls[0]?.arguments; assert.ok(args && typeof args[0] === "object"); assert.ok("stateActions" in args[0]); assert.strictEqual(typeof args[0].stateActions.setValue, "function"); assert.strictEqual(input.value, ""); }); /* CHECKBOX */ test("supports checkbox behavior", async () => { const user = userEvent.setup(); render(); const checkbox = screen.getByRole("checkbox") as HTMLInputElement; assert.strictEqual(checkbox.checked, false); await user.click(checkbox); assert.strictEqual(checkbox.checked, true); }); /* REF */ test("exposes imperative ref API", async () => { const ref = createRef(); render(); assert.ok(ref.current?.el instanceof HTMLElement); assert.deepStrictEqual(ref.current?.getData(), { value: "hello", isChecked: false, }); }); });