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
This commit is contained in:
120
packages/design-system/lib/components/TextArea/TextArea.test.tsx
Normal file
120
packages/design-system/lib/components/TextArea/TextArea.test.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
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)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user