import { expect, test } from "bun:test"; import { Window } from "happy-dom"; import { renderToStaticMarkup } from "react-dom/server"; import type { ReactNode } from "react"; import { Card } from "./Card"; import { ContainerShowcase } from "./ContainerShowcase"; import { Field } from "./Field"; function render(content: ReactNode) { const window = new Window(); window.document.body.innerHTML = renderToStaticMarkup(content); return window.document.body; } test("Field connects its label and hint to the rendered control", () => { const body = render( {(id, describedBy) => } , ); expect(body.querySelector("label")?.htmlFor).toBe("habit"); expect(body.querySelector("input")?.getAttribute("aria-describedby")).toBe("habit-hint"); expect(body.querySelector("#habit-hint")?.textContent).toBe("Keep it short."); }); test("Field generates unique control IDs and omits absent hint references", () => { const body = render(<> {(id, describedBy) => } {(id, describedBy) => } ); const controls = [...body.querySelectorAll("input")]; expect(new Set(controls.map((control) => control.id)).size).toBe(2); expect(controls.every((control) => !control.hasAttribute("aria-describedby"))).toBe(true); expect(body.querySelectorAll("small")).toHaveLength(0); }); test("Card preserves its title styling and accessible name at each heading level", () => { for (const headingLevel of [2, 3, 4, 5, 6] as const) { const body = render(Content); const heading = body.querySelector(`h${headingLevel}.ds-card-title`); expect(heading?.textContent).toBe("A clear boundary"); expect(body.querySelector("article")?.getAttribute("aria-labelledby")).toBe(heading?.id); } expect(render().querySelector("h3")?.textContent).toBe("Default"); }); test("Layout uses subsection headings above the card titles", () => { const body = render(); expect(body.querySelectorAll("h2")).toHaveLength(1); expect(body.querySelectorAll("h3")).toHaveLength(2); expect(body.querySelectorAll("h4.ds-card-title")).toHaveLength(6); });