nexus/ui/src/components/ThemePreviewPanel.test.tsx

102 lines
3.6 KiB
TypeScript

// @vitest-environment jsdom
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { render } from "@testing-library/react";
import { ThemePreviewPanel } from "./ThemePreviewPanel";
const makePalette = () => [
{
name: "background",
dark: { oklch: "oklch(0.14 0.01 240)", hex: "#1e1e2e", wcagAA: true },
light: { oklch: "oklch(0.94 0.005 240)", hex: "#eff1f5", wcagAA: true },
},
{
name: "surface",
dark: { oklch: "oklch(0.18 0.01 240)", hex: "#181825", wcagAA: true },
light: { oklch: "oklch(0.90 0.006 240)", hex: "#e6e9ef", wcagAA: true },
},
{
name: "text",
dark: { oklch: "oklch(0.93 0.008 240)", hex: "#cdd6f4", wcagAA: true },
light: { oklch: "oklch(0.28 0.008 240)", hex: "#4c4f69", wcagAA: true },
},
];
describe("ThemePreviewPanel", () => {
let originalSetProperty: typeof CSSStyleDeclaration.prototype.setProperty;
let documentSetPropertySpy: ReturnType<typeof vi.spyOn>;
beforeEach(() => {
originalSetProperty = CSSStyleDeclaration.prototype.setProperty;
documentSetPropertySpy = vi.spyOn(
document.documentElement.style,
"setProperty",
);
});
afterEach(() => {
CSSStyleDeclaration.prototype.setProperty = originalSetProperty;
vi.restoreAllMocks();
});
it("renders a container with className nexus-theme-preview", () => {
const { container } = render(
<ThemePreviewPanel palette={[]} variant="dark" />,
);
const preview = container.querySelector(".nexus-theme-preview");
expect(preview).toBeTruthy();
});
it("has aria-label='Theme preview' on the container", () => {
const { container } = render(
<ThemePreviewPanel palette={[]} variant="dark" />,
);
const preview = container.querySelector(".nexus-theme-preview");
expect(preview?.getAttribute("aria-label")).toBe("Theme preview");
});
it("has an aria-live='polite' region", () => {
const { container } = render(
<ThemePreviewPanel palette={[]} variant="dark" />,
);
const liveRegion = container.querySelector('[aria-live="polite"]');
expect(liveRegion).toBeTruthy();
});
it("announces 'Palette updated' when palette is provided", () => {
const palette = makePalette();
const { container } = render(
<ThemePreviewPanel palette={palette} variant="dark" />,
);
const liveRegion = container.querySelector('[aria-live="polite"]');
expect(liveRegion?.textContent).toBe("Palette updated");
});
it("sets CSS variables on the container element for dark variant", () => {
const palette = makePalette();
const { container } = render(
<ThemePreviewPanel palette={palette} variant="dark" />,
);
const preview = container.querySelector(".nexus-theme-preview") as HTMLElement;
expect(preview).toBeTruthy();
// dark background role should set --background to dark hex
expect(preview.style.getPropertyValue("--background")).toBe("#1e1e2e");
});
it("sets CSS variables on the container element for light variant", () => {
const palette = makePalette();
const { container } = render(
<ThemePreviewPanel palette={palette} variant="light" />,
);
const preview = container.querySelector(".nexus-theme-preview") as HTMLElement;
expect(preview).toBeTruthy();
// light background role should set --background to light hex
expect(preview.style.getPropertyValue("--background")).toBe("#eff1f5");
});
it("does NOT call document.documentElement.style.setProperty", () => {
const palette = makePalette();
render(<ThemePreviewPanel palette={palette} variant="dark" />);
expect(documentSetPropertySpy).not.toHaveBeenCalled();
});
});