import "@testing-library/jest-dom"; import { fireEvent, render, screen } from "@testing-library/react"; import Accordion from "./Accordion"; const items = [ { id: "one", title: "What is this?", content:

This is the first answer.

, }, { id: "two", title: "How does it work?", content:

This is the second answer.

, }, { id: "three", title: "Is it free?", content:

This is the third answer.

, }, ]; describe("Accordion", () => { test("renders all item titles", () => { render(); expect(screen.getByText("What is this?")).toBeInTheDocument(); expect(screen.getByText("How does it work?")).toBeInTheDocument(); expect(screen.getByText("Is it free?")).toBeInTheDocument(); }); test("all panels are closed by default", () => { render(); for (const { id } of items) { expect(document.getElementById(`panel-${id}`)).not.toHaveClass( "accordion-panel-open", ); } }); test("clicking a trigger opens its panel", () => { render(); fireEvent.click(screen.getByRole("button", { name: /what is this/i })); expect(document.getElementById("panel-one")).toHaveClass( "accordion-panel-open", ); }); test("clicking an open trigger closes it", () => { render(); fireEvent.click(screen.getByRole("button", { name: /what is this/i })); expect(document.getElementById("panel-one")).not.toHaveClass( "accordion-panel-open", ); }); test("trigger has aria-expanded false when closed", () => { render(); expect( screen.getByRole("button", { name: /what is this/i }), ).toHaveAttribute("aria-expanded", "false"); }); test("trigger has aria-expanded true when open", () => { render(); expect( screen.getByRole("button", { name: /what is this/i }), ).toHaveAttribute("aria-expanded", "true"); }); test("defaultOpen opens that item initially", () => { render(); expect(document.getElementById("panel-two")).toHaveClass( "accordion-panel-open", ); expect(document.getElementById("panel-one")).not.toHaveClass( "accordion-panel-open", ); }); test("opening one item closes the previously open item by default", () => { render(); fireEvent.click(screen.getByRole("button", { name: /how does it work/i })); expect(document.getElementById("panel-two")).toHaveClass( "accordion-panel-open", ); expect(document.getElementById("panel-one")).not.toHaveClass( "accordion-panel-open", ); }); test("allowMultiple lets multiple items be open simultaneously", () => { render(); fireEvent.click(screen.getByRole("button", { name: /how does it work/i })); expect(document.getElementById("panel-one")).toHaveClass( "accordion-panel-open", ); expect(document.getElementById("panel-two")).toHaveClass( "accordion-panel-open", ); }); test("calls onChange with the array of open ids when toggled", () => { const handleChange = vi.fn(); render(); fireEvent.click(screen.getByRole("button", { name: /what is this/i })); expect(handleChange).toHaveBeenCalledWith(["one"]); }); test("onChange is called with an empty array when the last open item is closed", () => { const handleChange = vi.fn(); render( , ); fireEvent.click(screen.getByRole("button", { name: /what is this/i })); expect(handleChange).toHaveBeenCalledWith([]); }); test("trigger aria-controls points to the correct panel id", () => { render(); expect( screen.getByRole("button", { name: /what is this/i }), ).toHaveAttribute("aria-controls", "panel-one"); }); test("panel aria-labelledby points to the correct trigger id", () => { render(); expect(document.getElementById("panel-one")).toHaveAttribute( "aria-labelledby", "trigger-one", ); }); test("applies an additional className to the wrapper", () => { const { container } = render( , ); expect(container.firstChild).toHaveClass("accordion", "faq-accordion"); }); });