import { describe, expect, test } from "bun:test"; import { getSystemPrefersDark, parseThemePreference, readThemePreference, resolveEffectiveTheme, THEME_MEDIA_QUERY, THEME_PREFERENCE_STORAGE_KEY, writeThemePreference, } from "../../../src/web/shared/hooks/use-theme-preference"; function createStorage(initial?: string): Storage { const values = new Map(); if (initial !== undefined) values.set(THEME_PREFERENCE_STORAGE_KEY, initial); return { clear: () => values.clear(), getItem: (key) => values.get(key) ?? null, key: (index) => Array.from(values.keys())[index] ?? null, get length() { return values.size; }, removeItem: (key) => values.delete(key), setItem: (key, value) => values.set(key, value), }; } describe("theme preference 纯逻辑", () => { test("解析合法和非法主题偏好", () => { expect(parseThemePreference("dark")).toBe("dark"); expect(parseThemePreference("light")).toBe("light"); expect(parseThemePreference("system")).toBe("system"); expect(parseThemePreference("unknown")).toBe("system"); }); test("读取和写入 localStorage", () => { const storage = createStorage("dark"); expect(readThemePreference(storage)).toBe("dark"); writeThemePreference("light", storage); expect(storage.getItem(THEME_PREFERENCE_STORAGE_KEY)).toBe("light"); }); test("storage 异常时回退且不抛错", () => { const brokenStorage = { getItem: () => { throw new Error("blocked"); }, setItem: () => { throw new Error("blocked"); }, } as unknown as Storage; expect(readThemePreference(brokenStorage)).toBe("system"); expect(() => writeThemePreference("dark", brokenStorage)).not.toThrow(); }); test("解析系统主题和异常回退", () => { const matchMedia = ((query: string) => { expect(query).toBe(THEME_MEDIA_QUERY); return { matches: true }; }) as Window["matchMedia"]; const brokenMatchMedia = (() => { throw new Error("blocked"); }) as Window["matchMedia"]; expect(getSystemPrefersDark(matchMedia)).toBe(true); expect(getSystemPrefersDark(brokenMatchMedia)).toBe(false); }); test("根据系统主题解析实际主题", () => { expect(resolveEffectiveTheme("dark", false)).toBe("dark"); expect(resolveEffectiveTheme("light", true)).toBe("light"); expect(resolveEffectiveTheme("system", true)).toBe("dark"); expect(resolveEffectiveTheme("system", false)).toBe("light"); }); });