import React from "react"; import { render, screen } from "@testing-library/react"; import { describe, it, expect, vi } from "vitest"; import List from "./list"; describe("List Component", () => { describe("Basic Rendering", () => { it("renders an unordered list by default", () => { render( Item 1 Item 2 ); const list = screen.getByRole("list"); expect(list.tagName).toBe("UL"); }); it("renders an ordered list when type='ol'", () => { render( First Second ); const list = screen.getByRole("list"); expect(list.tagName).toBe("OL"); }); it("renders a definition list when type='dl'", () => { render( Term Definition ); const term = screen.getByText("Term"); const definition = screen.getByText("Definition"); expect(term.tagName).toBe("DT"); expect(definition.tagName).toBe("DD"); }); it("renders children correctly", () => { render( Test Item 1 Test Item 2 Test Item 3 ); expect(screen.getByText("Test Item 1")).toBeInTheDocument(); expect(screen.getByText("Test Item 2")).toBeInTheDocument(); expect(screen.getByText("Test Item 3")).toBeInTheDocument(); }); }); describe("ListItem Component", () => { it("renders a list item (li) by default", () => { render( Default item ); const item = screen.getByText("Default item"); expect(item.tagName).toBe("LI"); }); it("renders a definition term (dt) when type='dt'", () => { render( Term ); const item = screen.getByText("Term"); expect(item.tagName).toBe("DT"); }); it("renders a definition description (dd) when type='dd'", () => { render( Description ); const item = screen.getByText("Description"); expect(item.tagName).toBe("DD"); }); it("accepts custom id prop", () => { render( Item with ID ); const item = screen.getByText("Item with ID"); expect(item).toHaveAttribute("id", "custom-item"); }); it("accepts custom classes prop", () => { render( Styled item ); const item = screen.getByText("Styled item"); expect(item).toHaveClass("custom-class"); }); it("accepts custom styles prop", () => { render( Styled item ); const item = screen.getByText("Styled item"); expect(item).toHaveStyle({ paddingLeft: "1rem" }); }); }); describe("Props and Attributes", () => { it("applies variant via data-variant attribute", () => { render( Item ); const list = screen.getByRole("list"); expect(list).toHaveAttribute("data-variant", "inline"); }); it("applies custom CSS classes", () => { render( Item ); const list = screen.getByRole("list"); expect(list).toHaveClass("custom-list-class"); }); it("applies inline styles", () => { render( Item ); const list = screen.getByRole("list"); expect(list).toHaveStyle({ marginTop: "2rem" }); }); it("applies custom id", () => { render( Item ); const list = screen.getByRole("list"); expect(list).toHaveAttribute("id", "main-list"); }); it("supports role override for accessibility", () => { render( Item ); const list = screen.getByRole("list"); expect(list).toHaveAttribute("role", "list"); }); it("supports aria-label", () => { render( Home ); const list = screen.getByRole("list", { name: "Navigation menu" }); expect(list).toBeInTheDocument(); }); it("supports aria-labelledby", () => { render(

Features

Feature 1
); const list = screen.getByRole("list"); expect(list).toHaveAttribute("aria-labelledby", "list-heading"); }); }); describe("Nested Lists", () => { it("renders nested unordered lists", () => { render( Parent item Child item 1 Child item 2 ); const lists = screen.getAllByRole("list"); expect(lists).toHaveLength(2); // Parent and nested list }); it("renders nested ordered lists", () => { render( Step 1 Sub-step 1.1 Sub-step 1.2 ); const lists = screen.getAllByRole("list"); expect(lists).toHaveLength(2); lists.forEach((list) => { expect(list.tagName).toBe("OL"); }); }); it("renders mixed nested list types", () => { render( Parent Nested ordered ); const lists = screen.getAllByRole("list"); expect(lists).toHaveLength(2); expect(lists[0].tagName).toBe("UL"); expect(lists[1].tagName).toBe("OL"); }); }); describe("Ref Forwarding", () => { it("forwards ref to List component", () => { const ref = vi.fn(); render( Item ); expect(ref).toHaveBeenCalled(); const refValue = ref.mock.calls[0][0]; expect(refValue).toBeInstanceOf(HTMLUListElement); }); it("forwards ref to ordered list", () => { const ref = vi.fn(); render( Item ); expect(ref).toHaveBeenCalled(); const refValue = ref.mock.calls[0][0]; expect(refValue).toBeInstanceOf(HTMLOListElement); }); it("forwards ref to definition list", () => { const ref = vi.fn(); render( Term ); expect(ref).toHaveBeenCalled(); const refValue = ref.mock.calls[0][0]; expect(refValue).toBeInstanceOf(HTMLDListElement); }); it("forwards ref to ListItem", () => { const ref = vi.fn(); render( Item ); expect(ref).toHaveBeenCalled(); const refValue = ref.mock.calls[0][0]; expect(refValue).toBeInstanceOf(HTMLLIElement); }); }); describe("Compound Component Pattern", () => { it("List.ListItem is attached to List", () => { expect(List.ListItem).toBeDefined(); expect(typeof List.ListItem).toBe("object"); // forwardRef returns an object }); it("works with List.ListItem syntax", () => { render( Item 1 Item 2 ); expect(screen.getByText("Item 1")).toBeInTheDocument(); expect(screen.getByText("Item 2")).toBeInTheDocument(); }); }); describe("Display Names", () => { it("List has correct displayName", () => { expect(List.displayName).toBe("List"); }); it("ListItem has correct displayName", () => { expect(List.ListItem.displayName).toBe("ListItem"); }); }); describe("Accessibility", () => { it("renders with proper ARIA attributes", () => { render( Feature 1 ); const list = screen.getByRole("list", { name: "Product features" }); expect(list).toBeInTheDocument(); }); it("supports role override for styled lists", () => { render( Item 1 ); const list = screen.getByRole("list"); expect(list).toHaveAttribute("role", "list"); }); it("maintains semantic structure with nested lists", () => { render( Parent Nested item ); const lists = screen.getAllByRole("list"); expect(lists).toHaveLength(2); // Parent and nested list }); it("renders definition lists with proper semantics", () => { render( Term Definition ); const term = screen.getByText("Term"); const definition = screen.getByText("Definition"); expect(term.tagName).toBe("DT"); expect(definition.tagName).toBe("DD"); }); }); describe("Edge Cases", () => { it("renders with no children", () => { // @ts-expect-error - Testing edge case where children is missing render(); const list = screen.getByRole("list"); expect(list).toBeInTheDocument(); expect(list).toBeEmptyDOMElement(); }); it("renders with single child", () => { render( Single item ); expect(screen.getByText("Single item")).toBeInTheDocument(); }); it("renders with many children", () => { const items = Array.from({ length: 100 }, (_, i) => `Item ${i + 1}`); render( {items.map((item) => ( {item} ))} ); expect(screen.getByText("Item 1")).toBeInTheDocument(); expect(screen.getByText("Item 100")).toBeInTheDocument(); }); it("handles complex children", () => { render( Bold and italic text ); expect(screen.getByText("Bold")).toBeInTheDocument(); expect(screen.getByText("italic")).toBeInTheDocument(); }); it("spreads additional props to list", () => { render( Item ); const list = screen.getByTestId("custom-list"); expect(list).toHaveAttribute("data-custom", "value"); }); it("spreads additional props to list item", () => { render( Item ); const item = screen.getByTestId("custom-item"); expect(item).toHaveAttribute("data-custom", "value"); }); }); describe("Real-World Use Cases", () => { it("renders a navigation list", () => { render( ); const list = screen.getByRole("list", { name: "Main navigation" }); expect(list).toHaveAttribute("data-variant", "inline"); }); it("renders a steps list", () => { render( Download the package Extract the files Run the installer ); const list = screen.getByRole("list", { name: "Installation steps" }); expect(list.tagName).toBe("OL"); }); it("renders a glossary", () => { render( HTML HyperText Markup Language CSS Cascading Style Sheets ); expect(screen.getByText("HTML")).toBeInTheDocument(); expect(screen.getByText("HyperText Markup Language")).toBeInTheDocument(); }); it("renders a feature list with custom styling", () => { render( Feature 1 Feature 2 ); const list = screen.getByRole("list"); expect(list).toHaveAttribute("data-variant", "custom"); expect(list).toHaveStyle({ "--list-marker-color": "blue", "--list-marker-content": "'✓'", }); }); }); });