93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
getEffectiveTaskListingView,
|
|
getStoredTaskListingView,
|
|
parseTaskListingView,
|
|
resolveTaskListingView,
|
|
setStoredTaskListingView,
|
|
shouldRestoreHomeTaskListingView,
|
|
TASK_LISTING_VIEW_CHANGE_EVENT,
|
|
TASK_LISTING_VIEW_STORAGE_KEY,
|
|
} from "./view-preference";
|
|
|
|
let originalLocalStorage: Storage | null = null;
|
|
|
|
afterEach(() => {
|
|
if (originalLocalStorage) {
|
|
Object.defineProperty(window, "localStorage", {
|
|
configurable: true,
|
|
value: originalLocalStorage,
|
|
});
|
|
originalLocalStorage = null;
|
|
}
|
|
window.localStorage.clear();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe("task listing view preference", () => {
|
|
it("accepts the versioned List preference", () => {
|
|
expect(parseTaskListingView('"list"')).toBe("list");
|
|
});
|
|
|
|
it("ignores malformed values", () => {
|
|
expect(parseTaskListingView("pipeline")).toBeNull();
|
|
});
|
|
|
|
it("uses the legacy Pipeline mode only when no device preference exists", () => {
|
|
expect(resolveTaskListingView(null, "graph2")).toBe("pipeline");
|
|
});
|
|
|
|
it("defaults malformed device preferences to Kanban instead of using the legacy mode", () => {
|
|
window.localStorage.setItem(TASK_LISTING_VIEW_STORAGE_KEY, '"unsupported"');
|
|
|
|
expect(resolveTaskListingView(getStoredTaskListingView(), "graph2")).toBe("kanban");
|
|
});
|
|
|
|
it("defaults to Kanban when neither a device nor legacy preference exists", () => {
|
|
expect(resolveTaskListingView(null, null)).toBe("kanban");
|
|
});
|
|
|
|
it("prefers a device-local preference over the legacy mode", () => {
|
|
expect(resolveTaskListingView("kanban", "graph2")).toBe("kanban");
|
|
});
|
|
|
|
it("renders Pipeline as Kanban on phone without changing the preference", () => {
|
|
expect(getEffectiveTaskListingView("pipeline", true)).toBe("kanban");
|
|
});
|
|
|
|
it("writes the versioned local preference and notifies this document", () => {
|
|
const listener = vi.fn();
|
|
window.addEventListener(TASK_LISTING_VIEW_CHANGE_EVENT, listener);
|
|
|
|
setStoredTaskListingView("pipeline");
|
|
|
|
expect(window.localStorage.getItem(TASK_LISTING_VIEW_STORAGE_KEY)).toBe('"pipeline"');
|
|
expect(listener).toHaveBeenCalledOnce();
|
|
window.removeEventListener(TASK_LISTING_VIEW_CHANGE_EVENT, listener);
|
|
});
|
|
|
|
it("keeps the selected view for this interaction when storage rejects the write", () => {
|
|
originalLocalStorage = window.localStorage;
|
|
Object.defineProperty(window, "localStorage", {
|
|
configurable: true,
|
|
value: {
|
|
getItem: () => null,
|
|
setItem: () => {
|
|
throw new Error("storage blocked");
|
|
},
|
|
clear: () => {},
|
|
},
|
|
});
|
|
|
|
setStoredTaskListingView("pipeline");
|
|
|
|
expect(getStoredTaskListingView()).toBe("pipeline");
|
|
});
|
|
|
|
it("restores List only for the top-level Home listing", () => {
|
|
expect(shouldRestoreHomeTaskListingView("list", undefined, undefined)).toBe(true);
|
|
expect(shouldRestoreHomeTaskListingView("list", "task-1", undefined)).toBe(false);
|
|
expect(shouldRestoreHomeTaskListingView("list", undefined, "session-1")).toBe(false);
|
|
});
|
|
});
|