fix(theme): persist one canonical preference
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
resolveEffectiveThemeMode,
|
||||
setThemeModePref,
|
||||
subscribeToThemePreferenceChanges,
|
||||
THEME_MODE_KEY,
|
||||
} from "./themePrefs";
|
||||
|
||||
function setSystemDark(matches: boolean) {
|
||||
@@ -36,7 +37,7 @@ describe("deterministic theme state", () => {
|
||||
setSystemDark(false);
|
||||
});
|
||||
|
||||
it("uses user preference, then anonymous preference, then the documented System default", () => {
|
||||
it("uses one browser preference and falls back to System", () => {
|
||||
expect(getThemeModePref()).toBe("system");
|
||||
setThemeModePref("light");
|
||||
expect(getThemeModePref()).toBe("light");
|
||||
@@ -47,12 +48,12 @@ describe("deterministic theme state", () => {
|
||||
expect(getThemeModePref()).toBe("dark");
|
||||
|
||||
setAuthUserKey("user-b", false);
|
||||
expect(getThemeModePref()).toBe("light");
|
||||
window.localStorage.removeItem("themeMode:anon");
|
||||
expect(getThemeModePref()).toBe("dark");
|
||||
window.localStorage.removeItem(THEME_MODE_KEY);
|
||||
expect(getThemeModePref()).toBe("system");
|
||||
});
|
||||
|
||||
it("switches to the correct scoped preference on login and logout without a refresh", () => {
|
||||
it("does not change theme on login or logout", () => {
|
||||
window.localStorage.setItem("themeMode:anon", "light");
|
||||
window.localStorage.setItem("themeMode:user-a", "dark");
|
||||
const observed: string[] = [];
|
||||
@@ -61,11 +62,12 @@ describe("deterministic theme state", () => {
|
||||
setAuthUserKey("user-a", false);
|
||||
clearAuthClientState(false);
|
||||
|
||||
expect(observed).toEqual(["dark", "light"]);
|
||||
expect(observed).toEqual([]);
|
||||
expect(getThemeModePref()).toBe("light");
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
it("synchronizes relevant cross-tab storage changes without writing them back", () => {
|
||||
it("synchronizes only the canonical cross-tab preference", () => {
|
||||
setAuthUserKey("user-a", false);
|
||||
const sync = jest.fn();
|
||||
const unsubscribe = subscribeToThemePreferenceChanges(sync);
|
||||
@@ -73,11 +75,20 @@ describe("deterministic theme state", () => {
|
||||
window.dispatchEvent(new StorageEvent("storage", { key: "themeMode:user-a", newValue: "dark" }));
|
||||
window.dispatchEvent(new StorageEvent("storage", { key: "unrelated", newValue: "value" }));
|
||||
window.dispatchEvent(new StorageEvent("storage", { key: "authUserKey", newValue: "user-b" }));
|
||||
window.dispatchEvent(new StorageEvent("storage", { key: THEME_MODE_KEY, newValue: "dark" }));
|
||||
|
||||
expect(sync).toHaveBeenCalledTimes(2);
|
||||
expect(sync).toHaveBeenCalledTimes(1);
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
it("migrates the previous account-scoped preference", () => {
|
||||
setAuthUserKey("user-a", false);
|
||||
window.localStorage.setItem("themeMode:user-a", "light");
|
||||
|
||||
expect(getThemeModePref()).toBe("light");
|
||||
expect(window.localStorage.getItem(THEME_MODE_KEY)).toBe("light");
|
||||
});
|
||||
|
||||
it("uses system preference only for System mode", () => {
|
||||
expect(resolveEffectiveThemeMode("light", true)).toBe("light");
|
||||
expect(resolveEffectiveThemeMode("dark", false)).toBe("dark");
|
||||
@@ -86,7 +97,7 @@ describe("deterministic theme state", () => {
|
||||
});
|
||||
|
||||
it("applies the saved preference before the client application renders", () => {
|
||||
window.localStorage.setItem("themeMode:anon", "light");
|
||||
window.localStorage.setItem(THEME_MODE_KEY, "light");
|
||||
setSystemDark(true);
|
||||
|
||||
new Function(THEME_BOOTSTRAP_SCRIPT)();
|
||||
|
||||
Reference in New Issue
Block a user