/** * @file AppearanceSettings.test.tsx * @description Tests for the Settings → Appearance section: the mode switch and the per-mode theme cards write through useTheme to ``. * @author Nguyễn Ngọc Trí Vĩ */ import { describe, it, expect, beforeEach } from "vitest"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { AppearanceSettings } from "../AppearanceSettings"; const root = document.documentElement; describe("AppearanceSettings", () => { beforeEach(() => { localStorage.clear(); root.classList.remove("dark"); root.removeAttribute("data-theme"); root.removeAttribute("data-mode"); }); it("renders every theme of both modes, defaults selected", () => { render(); const pressed = screen .getAllByRole("button", { pressed: true }) .map((b) => b.getAttribute("aria-label") ?? b.textContent); expect(pressed).toHaveLength(2); // both Default cards expect(screen.getByRole("radio", { name: /Dark/ })).toHaveAttribute("aria-checked", "true"); for (const name of ["Darcula", "Apple Dark", "Apple Light", "IntelliJ Light", "Canvas"]) { expect(screen.getByText(name)).toBeInTheDocument(); } }); it("picking a dark theme applies it at once; a light pick waits for light mode", async () => { const user = userEvent.setup(); render(); await user.click(screen.getByRole("button", { name: /Darcula/ })); expect(root.dataset.theme).toBe("darcula"); await user.click(screen.getByRole("button", { name: /Canvas/ })); expect(root.dataset.theme).toBe("darcula"); await user.click(screen.getByRole("radio", { name: /^Light$/ })); expect(root.classList.contains("dark")).toBe(false); expect(root.dataset.theme).toBe("canvas"); expect(screen.getByRole("button", { name: /Canvas/ })).toHaveAttribute("aria-pressed", "true"); }); it("the System mode is checked after choosing it", async () => { const user = userEvent.setup(); render(); await user.click(screen.getByRole("radio", { name: /System/ })); expect(screen.getByRole("radio", { name: /System/ })).toHaveAttribute("aria-checked", "true"); expect(localStorage.getItem("theme")).toBe("system"); }); it("each swatch scopes its own mode and theme", () => { const { container } = render(); expect(container.querySelector('.dark[data-theme="darcula"]')).not.toBeNull(); expect(container.querySelector('[data-mode="light"][data-theme="canvas"]')).not.toBeNull(); expect(container.querySelector('[data-mode="light"]:not([data-theme])')).not.toBeNull(); }); });