import { RadioButton } from "./index";
import { fireEvent, render, screen } from "@testing-library/react";
describe("RadioButton", () => {
const defaultProps = {
name: "plan",
label: "Option A",
};
it("renders with label text", () => {
render();
expect(screen.getByText("Option A")).toBeInTheDocument();
});
it("renders a hidden radio input", () => {
const { container } = render();
const input = container.querySelector('input[type="radio"]');
expect(input).toBeInTheDocument();
expect(input).toHaveClass("hidden");
});
it("sets name and value on the input", () => {
const { container } = render(
);
const input = container.querySelector('input[type="radio"]');
expect(input).toHaveAttribute("name", "plan");
expect(input).toHaveAttribute("value", "optA");
});
it("calls onChange with value when clicked", () => {
const onChange = jest.fn();
render();
const buttons = screen.getAllByRole("button");
fireEvent.click(buttons[0]);
expect(onChange).toHaveBeenCalledWith("optA");
});
it("calls onChange with name when no value is provided", () => {
const onChange = jest.fn();
render();
const buttons = screen.getAllByRole("button");
fireEvent.click(buttons[0]);
expect(onChange).toHaveBeenCalledWith("plan");
});
it("calls onChange when label button is clicked", () => {
const onChange = jest.fn();
render();
const buttons = screen.getAllByRole("button");
fireEvent.click(buttons[1]);
expect(onChange).toHaveBeenCalledWith("optA");
});
it("does not throw when onChange is not provided", () => {
render();
const buttons = screen.getAllByRole("button");
expect(() => fireEvent.click(buttons[0])).not.toThrow();
});
it("shows checked indicator when checked", () => {
const { container } = render(
);
const indicator = container.querySelector(".bg-bg-fill-brand");
expect(indicator).toBeInTheDocument();
});
it("does not show checked indicator when unchecked", () => {
const { container } = render(
);
const indicator = container.querySelector(".bg-bg-fill-brand");
expect(indicator).not.toBeInTheDocument();
});
it("applies border-brand class to outer button when checked", () => {
render();
const buttons = screen.getAllByRole("button");
expect(buttons[0].className).toContain("border-border-brand");
});
it("renders subText", () => {
render();
expect(screen.getByText("Extra info")).toBeInTheDocument();
});
it("applies custom className to the label wrapper", () => {
const { container } = render(
);
const label = container.querySelector("label");
expect(label?.className).toContain("custom-wrapper");
});
it("applies custom labelClassName", () => {
render();
const labelDiv = screen.getByText("Option A");
expect(labelDiv.className).toContain("text-bold");
});
it("passes data-cy to the label", () => {
const { container } = render(
);
const label = container.querySelector('[data-cy="radio-cy"]');
expect(label).toBeInTheDocument();
});
it("passes labelProps to the label element", () => {
const { container } = render(
);
const label = container.querySelector("#custom-label-id");
expect(label).toBeInTheDocument();
});
it("disables buttons and input when disabled", () => {
const { container } = render(
);
const input = container.querySelector('input[type="radio"]');
const buttons = screen.getAllByRole("button");
expect(input).toBeDisabled();
expect(buttons[0]).toBeDisabled();
expect(buttons[1]).toBeDisabled();
});
it("applies opacity-50 class when disabled", () => {
render();
const buttons = screen.getAllByRole("button");
expect(buttons[0].className).toContain("opacity-50");
});
it("sets tabIndex -1 on label button when no label is provided", () => {
render();
const buttons = screen.getAllByRole("button");
expect(buttons[1]).toHaveAttribute("tabindex", "-1");
});
it("sets tabIndex 0 on label button when label is provided", () => {
render();
const buttons = screen.getAllByRole("button");
expect(buttons[1]).toHaveAttribute("tabindex", "0");
});
it("has the correct displayName", () => {
expect(RadioButton.displayName).toBe("RadioButton");
});
});