Files
kandev/apps/web/lib/task-listing/view-preference.test.ts
T
2026-07-25 19:30:52 +01:00

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);
});
});