import { cleanup, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import assert from "node:assert"; import { describe, test, mock, afterEach, } from "node:test"; import type { IChecker } from "../checker"; import { CheckerGroup } from "./index"; import type { ICheckerGroup, ICheckerGroupItemsGroup } from "./index"; describe("CheckerGroup", () => { const mockItems: ICheckerGroup["items"] = [ { name: "option1", value: "1", label: "Option 1", isChecked: false, }, { name: "option2", value: "2", label: "Option 2", isChecked: true, }, { name: "option3", value: "3", label: "Option 3", isChecked: false, }, ]; const mockNestedItems: ICheckerGroup["items"] = [ { label: "Group A", items: [ { name: "a1", value: "a1", label: "A1", isChecked: false, }, { name: "a2", value: "a2", label: "A2", isChecked: true, }, ], }, { label: "Group B", items: [ { name: "b1", value: "b1", label: "B1", isChecked: false, }, ], }, ]; const radioItems: ICheckerGroup["items"] = [ { name: "group1", value: "opt1", label: "Option 1", isChecked: true, }, { name: "group1", value: "opt2", label: "Option 2", isChecked: false, }, ]; /* COMMON */ afterEach(() => { cleanup(); }); test("renders empty placeholder when items array is empty", () => { render(); assert.notStrictEqual(screen.queryByText("No items available"), null); const listItem = screen.getByRole("listitem"); assert.ok(listItem.className.includes("isEmpty")); // adjust if actual class name differs }); test("renders checkboxes by default", () => { render(); const checkboxes = screen.getAllByRole("checkbox"); assert.strictEqual(checkboxes.length, mockItems.length); checkboxes.forEach((checker) => { assert.strictEqual(checker.getAttribute("type"), "checkbox"); }); }); test("renders radio when type is 'radio'", () => { render(); const radios = screen.getAllByRole("radio"); assert.strictEqual(radios.length, mockItems.length); radios.forEach((radio) => { assert.strictEqual(radio.getAttribute("type"), "radio"); }); }); test("renders nested groups with labels", () => { render(); assert.notStrictEqual(screen.queryByText("Group A"), null); assert.notStrictEqual(screen.queryByText("Group B"), null); const checkboxes = screen.getAllByRole("checkbox"); const expectedLength = mockNestedItems.reduce((sum, currentGroup) => { return sum + (currentGroup as ICheckerGroupItemsGroup).items.length; }, 0); assert.strictEqual(checkboxes.length, expectedLength); }); /* HANDLERS */ test("calls onChange when checker is changed", async () => { const user = userEvent.setup(); const onChange = mock.fn(); render(); const firstCheckbox = screen.getAllByRole("checkbox")[0]; await user.click(firstCheckbox); assert.strictEqual(onChange.mock.calls.length, 1); const args = onChange.mock.calls[0]?.arguments; assert.ok(args); const [ firstArg, secondArg ] = args; assert.ok(firstArg && typeof firstArg === "object"); assert.ok("event" in firstArg); assert.strictEqual(typeof secondArg, "function"); }); test("updates checkers state when onChange is not provided", async () => { const user = userEvent.setup(); render(); const checkboxes = screen.getAllByRole("checkbox") as HTMLInputElement[]; assert.strictEqual(checkboxes[0].checked, false); assert.strictEqual(checkboxes[1].checked, true); await user.click(checkboxes[0]); assert.strictEqual(checkboxes[0].checked, true); assert.strictEqual(checkboxes[1].checked, true); }); test("handles radio group behaviour correctly", async () => { const user = userEvent.setup(); render(); const radios = screen.getAllByRole("radio") as HTMLInputElement[]; assert.strictEqual(radios[0].checked, true); assert.strictEqual(radios[1].checked, false); await user.click(radios[1]); assert.strictEqual(radios[0].checked, false); assert.strictEqual(radios[1].checked, true); }); /* CHILDREN */ test("uses custom getItem function for rendering", () => { const getItem = mock.fn>(({ item, checker }) => (
{checker} Custom wrapper
)); render(); assert.strictEqual(getItem.mock.calls.length, 3); mockItems.forEach((checker) => { const testId = `custom-${(checker as IChecker).value}`; assert.notStrictEqual(screen.queryByTestId(testId), null); }); const wrappers = screen.getAllByText("Custom wrapper"); assert.strictEqual(wrappers.length, 3); }); test("updates list when 'items' prop is changed", () => { const { rerender } = render(); let checkboxes = screen.getAllByRole("checkbox"); assert.strictEqual(checkboxes.length, 1); rerender(); checkboxes = screen.getAllByRole("checkbox"); assert.strictEqual(checkboxes.length, mockItems.length); }); test("renders children instead of default content", () => { render(
Custom content
); assert.notStrictEqual(screen.queryByTestId("customContent"), null); assert.strictEqual(screen.queryByRole("checkbox"), null); }); });