Add quick-win tests for components and hooks

Adds tests for DifficultyIndicator, Toast, RollModeMenu, OverflowMenu,
useTheme, and useRulesEdition. Covers rendering, user interactions,
auto-dismiss timers, external store sync, and localStorage persistence.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-28 19:28:58 +01:00
parent d8c8a0c44d
commit a77db0eeee
7 changed files with 385 additions and 6 deletions

View File

@@ -0,0 +1,45 @@
// @vitest-environment jsdom
import { act, renderHook } from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";
import { useRulesEdition } from "../use-rules-edition.js";
const STORAGE_KEY = "initiative:rules-edition";
describe("useRulesEdition", () => {
afterEach(() => {
// Reset to default
const { result } = renderHook(() => useRulesEdition());
act(() => result.current.setEdition("5.5e"));
localStorage.removeItem(STORAGE_KEY);
});
it("defaults to 5.5e", () => {
const { result } = renderHook(() => useRulesEdition());
expect(result.current.edition).toBe("5.5e");
});
it("setEdition updates value", () => {
const { result } = renderHook(() => useRulesEdition());
act(() => result.current.setEdition("5e"));
expect(result.current.edition).toBe("5e");
});
it("setEdition persists to localStorage", () => {
const { result } = renderHook(() => useRulesEdition());
act(() => result.current.setEdition("5e"));
expect(localStorage.getItem(STORAGE_KEY)).toBe("5e");
});
it("multiple hooks stay in sync", () => {
const { result: r1 } = renderHook(() => useRulesEdition());
const { result: r2 } = renderHook(() => useRulesEdition());
act(() => r1.current.setEdition("5e"));
expect(r2.current.edition).toBe("5e");
});
});

View File

@@ -0,0 +1,63 @@
// @vitest-environment jsdom
import { act, renderHook } from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";
import { useTheme } from "../use-theme.js";
const STORAGE_KEY = "initiative:theme";
describe("useTheme", () => {
afterEach(() => {
// Reset to default
const { result } = renderHook(() => useTheme());
act(() => result.current.setPreference("system"));
localStorage.removeItem(STORAGE_KEY);
});
it("defaults to system preference", () => {
const { result } = renderHook(() => useTheme());
expect(result.current.preference).toBe("system");
});
it("setPreference updates to light", () => {
const { result } = renderHook(() => useTheme());
act(() => result.current.setPreference("light"));
expect(result.current.preference).toBe("light");
expect(result.current.resolved).toBe("light");
});
it("setPreference updates to dark", () => {
const { result } = renderHook(() => useTheme());
act(() => result.current.setPreference("dark"));
expect(result.current.preference).toBe("dark");
expect(result.current.resolved).toBe("dark");
});
it("persists preference to localStorage", () => {
const { result } = renderHook(() => useTheme());
act(() => result.current.setPreference("light"));
expect(localStorage.getItem(STORAGE_KEY)).toBe("light");
});
it("applies theme to document element", () => {
const { result } = renderHook(() => useTheme());
act(() => result.current.setPreference("light"));
expect(document.documentElement.dataset.theme).toBe("light");
});
it("multiple hooks stay in sync", () => {
const { result: r1 } = renderHook(() => useTheme());
const { result: r2 } = renderHook(() => useTheme());
act(() => r1.current.setPreference("dark"));
expect(r2.current.preference).toBe("dark");
});
});