Files
web/packages/design-system/lib/components/TextArea/TextArea.test.tsx
Rasmus Langvad 4980cc830d Merged in feat/3685-new-textarea-component (pull request #3392)
feat(SW-3685): Add new TextArea and FormTextArea components

* Add new TextArea and FormTextArea components

* Update example form with description

* Merge branch 'master' into feat/3685-new-textarea-component

* Formatting new files with new prettier config

* Added custom controls for the text area story


Approved-by: Linus Flood
2026-01-07 17:04:30 +00:00

121 lines
3.5 KiB
TypeScript

import { describe, expect, it, vi, afterEach } from "vitest"
import { render, screen, fireEvent, cleanup } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { TextArea } from "./TextArea"
import { TextField } from "react-aria-components"
afterEach(() => {
cleanup()
})
// Wrap TextArea in TextField for proper React Aria context
const renderTextArea = (props: React.ComponentProps<typeof TextArea>) => {
return render(
<TextField>
<TextArea {...props} />
</TextField>
)
}
// Render TextArea standalone for testing its own behavior
const renderTextAreaStandalone = (
props: React.ComponentProps<typeof TextArea>
) => {
return render(<TextArea {...props} />)
}
describe("TextArea", () => {
describe("props", () => {
it("applies required attribute", () => {
renderTextArea({ label: "Description", required: true })
expect(screen.getByRole("textbox")).toHaveProperty("required", true)
})
it("applies placeholder when provided", () => {
renderTextArea({ label: "Description", placeholder: "Enter description" })
expect(screen.getByRole("textbox").getAttribute("placeholder")).toBe(
"Enter description"
)
})
it("applies empty placeholder by default", () => {
renderTextArea({ label: "Description" })
expect(screen.getByRole("textbox").getAttribute("placeholder")).toBe("")
})
it("applies custom id", () => {
renderTextAreaStandalone({ label: "Description", id: "custom-id" })
expect(screen.getByRole("textbox").getAttribute("id")).toBe("custom-id")
})
})
describe("label", () => {
it("renders label when provided", () => {
renderTextArea({ label: "Description" })
expect(screen.getByText("Description")).toBeTruthy()
})
it("does not render label when not provided", () => {
renderTextArea({})
expect(screen.queryByText("Description")).toBeNull()
})
})
describe("controlled textarea", () => {
it("displays the controlled value", () => {
renderTextArea({
label: "Description",
value: "Some text content",
onChange: vi.fn(),
})
expect(screen.getByRole("textbox")).toHaveProperty(
"value",
"Some text content"
)
})
it("calls onChange when typing", async () => {
const onChange = vi.fn()
renderTextArea({ label: "Description", value: "", onChange })
const textarea = screen.getByRole("textbox")
await userEvent.type(textarea, "a")
expect(onChange).toHaveBeenCalled()
})
it("does not change value without onChange updating it", () => {
const onChange = vi.fn()
renderTextArea({ label: "Description", value: "initial", onChange })
const textarea = screen.getByRole("textbox")
fireEvent.change(textarea, { target: { value: "changed" } })
expect(textarea).toHaveProperty("value", "initial")
})
})
describe("ref forwarding", () => {
it("forwards ref to the textarea element", () => {
const ref = { current: null as HTMLTextAreaElement | null }
render(
<TextField>
<TextArea label="Description" ref={ref} />
</TextField>
)
expect(ref.current).toBeInstanceOf(HTMLTextAreaElement)
})
it("allows focusing via ref", () => {
const ref = { current: null as HTMLTextAreaElement | null }
render(
<TextField>
<TextArea label="Description" ref={ref} />
</TextField>
)
ref.current?.focus()
expect(document.activeElement).toBe(ref.current)
})
})
})