import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { Field } from "../../../data/pfa-fields"; import { RadioGroupInput } from "../radioGroup"; describe("RadioGroupInput", () => { const mockField: Field = { id: "contentRank", label: "Content Rank", description: "Select the ranking strategy", type: "string", method: "radio", required: false, hidden: false, render: "config.recommend.rank", defaultValue: "affinity", options: [ { label: "Highest Affinity", value: "affinity" }, { label: "Most Popular", value: "popular" }, { label: "Most Recently Published", value: "recent" }, { label: "Most Recent Interaction", value: "last_interaction" }, ], }; describe("rendering", () => { it("should render all radio options when visible", () => { const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; render( , ); expect(screen.getByText("Content Rank")).toBeInTheDocument(); expect(screen.getByLabelText("Highest Affinity")).toBeInTheDocument(); expect(screen.getByLabelText("Most Popular")).toBeInTheDocument(); expect( screen.getByLabelText("Most Recently Published"), ).toBeInTheDocument(); expect( screen.getByLabelText("Most Recent Interaction"), ).toBeInTheDocument(); }); it("should not render when not visible", () => { const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; const { container } = render( , ); expect(container.firstChild).toBeNull(); }); it("should display description when provided", () => { const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; render( , ); expect( screen.getByText("Select the ranking strategy"), ).toBeInTheDocument(); }); it("should render horizontally when row prop is true", () => { const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; const { container } = render( , ); const radioGroup = container.querySelector(".MuiRadioGroup-root"); expect(radioGroup).toHaveClass("MuiRadioGroup-row"); }); }); describe("selection", () => { it("should show the correct option as selected", () => { const handleChange = vi.fn(); const formValues = { contentRank: "popular" }; render( , ); const popularRadio = screen.getByLabelText( "Most Popular", ) as HTMLInputElement; expect(popularRadio.checked).toBe(true); const affinityRadio = screen.getByLabelText( "Highest Affinity", ) as HTMLInputElement; expect(affinityRadio.checked).toBe(false); }); it("should handle no selection (empty string)", () => { const handleChange = vi.fn(); const formValues = { contentRank: "" }; render( , ); const radios = screen.getAllByRole("radio") as HTMLInputElement[]; radios.forEach((radio) => { expect(radio.checked).toBe(false); }); }); }); describe("interaction", () => { it("should call handleChange when selecting a different option", () => { const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; render( , ); const popularRadio = screen.getByLabelText("Most Popular"); fireEvent.click(popularRadio); expect(handleChange).toHaveBeenCalledWith("contentRank", "popular"); }); it("should call handleChange with correct field ID and value", () => { const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; render( , ); const recentRadio = screen.getByLabelText("Most Recently Published"); fireEvent.click(recentRadio); expect(handleChange).toHaveBeenCalledTimes(1); expect(handleChange).toHaveBeenCalledWith("contentRank", "recent"); }); it("should not call handleChange when clicking already selected option", () => { const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; render( , ); const affinityRadio = screen.getByLabelText("Highest Affinity"); fireEvent.click(affinityRadio); // Material-UI radio buttons don't trigger onChange when clicking already selected option expect(handleChange).not.toHaveBeenCalled(); }); }); describe("edge cases", () => { it("should handle field with no options", () => { const fieldWithNoOptions: Field = { ...mockField, options: [], }; const handleChange = vi.fn(); const formValues = {}; render( , ); expect(screen.getByText("Content Rank")).toBeInTheDocument(); expect(screen.queryAllByRole("radio")).toHaveLength(0); }); it("should handle field with no description", () => { const fieldWithNoDescription: Field = { ...mockField, description: undefined, }; const handleChange = vi.fn(); const formValues = { contentRank: "affinity" }; render( , ); expect(screen.getByText("Content Rank")).toBeInTheDocument(); expect( screen.queryByText("Select the ranking strategy"), ).not.toBeInTheDocument(); }); it("should handle missing form value", () => { const handleChange = vi.fn(); const formValues = {}; // No contentRank value render( , ); const radios = screen.getAllByRole("radio") as HTMLInputElement[]; radios.forEach((radio) => { expect(radio.checked).toBe(false); }); }); }); });