import type {Theme} from "../src"; import * as React from "react"; import {render, act} from "@testing-library/react"; import {useTheme, ThemeProps} from "../src"; const TestComponent = ({defaultTheme}: {defaultTheme?: Theme}) => { const {theme, setTheme} = useTheme(defaultTheme); return (
{theme}
); }; TestComponent.displayName = "TestComponent"; const localStorageMock = (() => { let store: {[key: string]: string} = {}; return { getItem: (key: string) => store[key] || null, setItem: (key: string, value: string) => { store[key] = value; }, clear: () => { store = {}; }, }; })(); Object.defineProperty(window, "localStorage", { value: localStorageMock, }); describe("useTheme hook", () => { beforeEach(() => { jest.clearAllMocks(); localStorage.clear(); document.documentElement.className = ""; }); it("should initialize with default theme if no theme is stored in localStorage", () => { const {getByTestId} = render(); expect(getByTestId("theme-display").textContent).toBe(ThemeProps.LIGHT); expect(document.documentElement.classList.contains(ThemeProps.LIGHT)).toBe(true); }); it("should initialize with the given theme if no theme is stored in localStorage", () => { const customTheme = "purple-dark"; const {getByTestId} = render(); expect(getByTestId("theme-display").textContent).toBe(customTheme); expect(document.documentElement.classList.contains(customTheme)).toBe(true); }); it("should initialize with stored theme from localStorage", () => { localStorage.setItem(ThemeProps.KEY, ThemeProps.DARK); const {getByTestId} = render(); expect(localStorage.getItem(ThemeProps.KEY)).toBe(ThemeProps.DARK); expect(getByTestId("theme-display").textContent).toBe(ThemeProps.DARK); expect(document.documentElement.classList.contains(ThemeProps.DARK)).toBe(true); }); it("should set new theme correctly and update localStorage and DOM (dark)", () => { const {getByText, getByTestId} = render(); act(() => { getByText("Set Dark").click(); }); expect(getByTestId("theme-display").textContent).toBe(ThemeProps.DARK); expect(localStorage.getItem(ThemeProps.KEY)).toBe(ThemeProps.DARK); expect(document.documentElement.classList.contains(ThemeProps.DARK)).toBe(true); }); it("should set new theme correctly and update localStorage and DOM (light)", () => { const {getByText, getByTestId} = render(); act(() => { getByText("Set Light").click(); }); expect(getByTestId("theme-display").textContent).toBe(ThemeProps.LIGHT); expect(localStorage.getItem(ThemeProps.KEY)).toBe(ThemeProps.LIGHT); expect(document.documentElement.classList.contains(ThemeProps.LIGHT)).toBe(true); }); it("should set new theme correctly and update localStorage and DOM (system - prefers-color-scheme: light)", () => { const {getByText, getByTestId} = render(); Object.defineProperty(window, "matchMedia", { writable: true, value: jest.fn().mockImplementation((query) => ({ matches: false, media: query, onchange: null, addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })), }); act(() => { getByText("Set System").click(); }); expect(getByTestId("theme-display").textContent).toBe(ThemeProps.SYSTEM); expect(localStorage.getItem(ThemeProps.KEY)).toBe(ThemeProps.SYSTEM); expect(document.documentElement.classList.contains(ThemeProps.LIGHT)).toBe(true); }); it("should set new theme correctly and update localStorage and DOM (system - prefers-color-scheme: dark)", () => { const {getByText, getByTestId} = render(); Object.defineProperty(window, "matchMedia", { writable: true, value: jest.fn().mockImplementation((query) => ({ matches: true, media: query, onchange: null, addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })), }); act(() => { getByText("Set System").click(); }); expect(getByTestId("theme-display").textContent).toBe(ThemeProps.SYSTEM); expect(localStorage.getItem(ThemeProps.KEY)).toBe(ThemeProps.SYSTEM); expect(document.documentElement.classList.contains(ThemeProps.DARK)).toBe(true); }); });