diff --git a/client/src/lib/theme.test.ts b/client/src/lib/theme.test.ts new file mode 100644 index 0000000..0c9eda4 --- /dev/null +++ b/client/src/lib/theme.test.ts @@ -0,0 +1,25 @@ +import { describe, it, expect, beforeEach } from "vitest"; +import { nextTheme, getInitialTheme } from "./theme.js"; + +describe("nextTheme", () => { + it("bascule dark <-> light", () => { + expect(nextTheme("dark")).toBe("light"); + expect(nextTheme("light")).toBe("dark"); + }); +}); + +describe("getInitialTheme", () => { + beforeEach(() => { + // @ts-expect-error - environnement node sans localStorage + delete globalThis.localStorage; + }); + it("retombe sur dark sans localStorage", () => { + expect(getInitialTheme()).toBe("dark"); + }); + it("lit la valeur persistée si présente", () => { + const store: Record = { "su-theme": "light" }; + // @ts-expect-error - stub minimal + globalThis.localStorage = { getItem: (k: string) => store[k] ?? null }; + expect(getInitialTheme()).toBe("light"); + }); +}); diff --git a/client/src/lib/theme.ts b/client/src/lib/theme.ts new file mode 100644 index 0000000..7ee6b40 --- /dev/null +++ b/client/src/lib/theme.ts @@ -0,0 +1,25 @@ +// client/src/lib/theme.ts +export type Theme = "dark" | "light"; +const KEY = "su-theme"; + +export function nextTheme(t: Theme): Theme { + return t === "dark" ? "light" : "dark"; +} + +export function getInitialTheme(): Theme { + try { + const v = globalThis.localStorage?.getItem(KEY); + return v === "light" ? "light" : "dark"; + } catch { + return "dark"; + } +} + +export function applyTheme(t: Theme): void { + try { + document.documentElement.dataset.theme = t; + globalThis.localStorage?.setItem(KEY, t); + } catch { + /* localStorage indisponible (mode privé) : on ignore la persistance */ + } +} diff --git a/vitest.config.ts b/vitest.config.ts index ab14c0a..b4c1afa 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { globals: true, - include: ["server/**/*.test.ts", "shared/**/*.test.ts"], + include: ["server/**/*.test.ts", "shared/**/*.test.ts", "client/**/*.test.ts"], environment: "node", }, resolve: { alias: { "@shared": new URL("./shared", import.meta.url).pathname } },