diff --git a/src/components/__tests__/SettingsTab.test.tsx b/src/components/__tests__/SettingsTab.test.tsx new file mode 100644 index 0000000..08876dc --- /dev/null +++ b/src/components/__tests__/SettingsTab.test.tsx @@ -0,0 +1,107 @@ +// @vitest-environment jsdom +import { render, screen, fireEvent } from "@testing-library/react"; +import { describe, expect, it, vi, beforeEach } from "vitest"; +import { SettingsTab } from "../SettingsTab"; +import { MAIN_BLOCKS, DETAIL_OPTIONS } from "@/lib/cardGeneratorConstants"; +import type { CardDisplayOptions, CardBlockId } from "@/lib/types"; +import "@testing-library/jest-dom"; + +describe("SettingsTab", () => { + const mockIsBlockVisible = vi.fn(); + const mockToggleMainBlockVisibility = vi.fn(); + const mockToggleDisplayOption = vi.fn(); + + const defaultProps = { + isBlockVisible: mockIsBlockVisible, + toggleMainBlockVisibility: mockToggleMainBlockVisibility, + displayOptions: {} as CardDisplayOptions, + toggleDisplayOption: mockToggleDisplayOption, + }; + + beforeEach(() => { + vi.resetAllMocks(); + }); + + it("renders all MAIN_BLOCKS checkboxes", () => { + mockIsBlockVisible.mockReturnValue(false); + render(); + + MAIN_BLOCKS.forEach(({ label }) => { + const checkbox = screen.getByLabelText(label); + expect(checkbox).toBeInTheDocument(); + expect(checkbox).toHaveAttribute("type", "checkbox"); + expect(checkbox).not.toBeChecked(); + }); + }); + + it("renders all DETAIL_OPTIONS checkboxes", () => { + render(); + + DETAIL_OPTIONS.forEach(({ label }) => { + const checkbox = screen.getByLabelText(label); + expect(checkbox).toBeInTheDocument(); + expect(checkbox).toHaveAttribute("type", "checkbox"); + expect(checkbox).not.toBeChecked(); + }); + }); + + it("sets MAIN_BLOCKS checkbox checked state based on isBlockVisible prop", () => { + // Mock that 'profile' and 'skills' are visible, others are not + mockIsBlockVisible.mockImplementation((id: CardBlockId) => id === "profile" || id === "skills"); + + render(); + + MAIN_BLOCKS.forEach(({ id, label }) => { + const checkbox = screen.getByLabelText(label); + if (id === "profile" || id === "skills") { + expect(checkbox).toBeChecked(); + } else { + expect(checkbox).not.toBeChecked(); + } + }); + }); + + it("sets DETAIL_OPTIONS checkbox checked state based on displayOptions prop", () => { + const displayOptions: CardDisplayOptions = { + showAvatar: true, + showLocation: true, + // Others are implicitly false or undefined + }; + + render(); + + DETAIL_OPTIONS.forEach(({ key, label }) => { + const checkbox = screen.getByLabelText(label); + if (key === "showAvatar" || key === "showLocation") { + expect(checkbox).toBeChecked(); + } else { + expect(checkbox).not.toBeChecked(); + } + }); + }); + + it("calls toggleMainBlockVisibility with correct id when MAIN_BLOCKS checkbox is clicked", () => { + mockIsBlockVisible.mockReturnValue(false); + render(); + + const firstMainBlock = MAIN_BLOCKS[0]; + const checkbox = screen.getByLabelText(firstMainBlock.label); + + fireEvent.click(checkbox); + + expect(mockToggleMainBlockVisibility).toHaveBeenCalledTimes(1); + expect(mockToggleMainBlockVisibility).toHaveBeenCalledWith(firstMainBlock.id); + }); + + it("calls toggleDisplayOption with correct key when DETAIL_OPTIONS checkbox is clicked", () => { + render(); + + const firstDetailOption = DETAIL_OPTIONS[0]; + const checkbox = screen.getByLabelText(firstDetailOption.label); + + fireEvent.click(checkbox); + + expect(mockToggleDisplayOption).toHaveBeenCalledTimes(1); + expect(mockToggleDisplayOption).toHaveBeenCalledWith(firstDetailOption.key); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 9404856..eaff66e 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -21,7 +21,9 @@ export default defineConfig({ "src/components/LanguageChart.tsx", "src/components/SkillsCard.tsx", "src/components/LayoutEditor.tsx", + "src/components/SettingsTab.tsx", "src/lib/rateLimit.ts", + "src/app/api/og/[username]/route.tsx" ], thresholds: {