Move account actions (Settings, Downloads, Display preferences, Sign out) out of the library-only header into a shared AccountMenu anchored in a global AppHeader, available on every authenticated non-immersive screen. Add a layoutShell helper deciding where chrome shows, expose serverName/serverUrl auth stores, and a display view-mode preference. The settings page also gains the UR-053 WiFi-only toggle. TRACES: UR-054 | DR-075, DR-076, DR-077
70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
/**
|
|
* Display preference (grid/list) is a second view onto the library `viewMode`
|
|
* store. The Settings Display section and the library page-header toggle both
|
|
* drive it via `library.setViewMode`, so verifying the store writes through and
|
|
* persists covers the shared data path for both controls.
|
|
*
|
|
* TRACES: UR-029 | DR-077 | UT-*
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, beforeAll, afterAll, vi } from "vitest";
|
|
import { get } from "svelte/store";
|
|
|
|
const STORAGE_KEY = "jellytau-view-mode";
|
|
|
|
// jsdom here doesn't expose localStorage; stand in a minimal implementation.
|
|
const backing = new Map<string, string>();
|
|
const localStorageShim = {
|
|
getItem: (key: string) => backing.get(key) ?? null,
|
|
setItem: (key: string, value: string) => void backing.set(key, value),
|
|
removeItem: (key: string) => void backing.delete(key),
|
|
clear: () => backing.clear(),
|
|
};
|
|
|
|
// The library store imports the auth store and tauri events at module load;
|
|
// neither is exercised by these tests.
|
|
vi.mock("@tauri-apps/api/event", () => ({
|
|
listen: vi.fn(async () => () => {}),
|
|
}));
|
|
vi.mock("./auth", () => ({ auth: { getUserId: vi.fn() } }));
|
|
|
|
beforeAll(() => {
|
|
vi.stubGlobal("localStorage", localStorageShim);
|
|
});
|
|
|
|
afterAll(() => {
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
describe("viewMode display preference", () => {
|
|
beforeEach(() => {
|
|
backing.clear();
|
|
vi.resetModules();
|
|
});
|
|
|
|
it("setViewMode writes through to the derived store", async () => {
|
|
const { library, viewMode } = await import("./library");
|
|
library.setViewMode("list");
|
|
expect(get(viewMode)).toBe("list");
|
|
library.setViewMode("grid");
|
|
expect(get(viewMode)).toBe("grid");
|
|
});
|
|
|
|
it("setViewMode persists the choice to localStorage", async () => {
|
|
const { library } = await import("./library");
|
|
library.setViewMode("list");
|
|
expect(backing.get(STORAGE_KEY)).toBe("list");
|
|
});
|
|
|
|
it("a persisted list preference is restored on load", async () => {
|
|
backing.set(STORAGE_KEY, "list");
|
|
const { viewMode } = await import("./library");
|
|
expect(get(viewMode)).toBe("list");
|
|
});
|
|
|
|
it("defaults to grid when nothing is persisted", async () => {
|
|
const { viewMode } = await import("./library");
|
|
expect(get(viewMode)).toBe("grid");
|
|
});
|
|
});
|