/** * @file laneOrderStorage.test.ts * @description Tests for the Workspace lane strip's stored card order: the * storage round-trip, and the two rules that keep a stale stored order from * losing a lane — unknown ids land at the end, vanished ids are skipped. * @author Nguyễn Ngọc Trí Vĩ */ import { describe, it, expect, beforeEach } from "vitest"; import { readLaneOrder, writeLaneOrder, sortByStoredOrder, moveLane } from "../laneOrderStorage"; const lanes = (...ids: number[]) => ids.map((id) => ({ id })); describe("laneOrderStorage", () => { beforeEach(() => localStorage.clear()); it("returns an empty order when nothing is stored", () => { expect(readLaneOrder()).toEqual([]); }); it("round-trips a written order", () => { writeLaneOrder([3, 1, 2]); expect(readLaneOrder()).toEqual([3, 1, 2]); }); it("falls back to an empty order when stored JSON is malformed", () => { localStorage.setItem("agenthub.workspace.laneOrder", "{not json"); expect(readLaneOrder()).toEqual([]); }); it("drops non-numeric entries from a stored order", () => { localStorage.setItem("agenthub.workspace.laneOrder", JSON.stringify([1, "2", null, 3])); expect(readLaneOrder()).toEqual([1, 3]); }); }); describe("sortByStoredOrder", () => { it("keeps server order when nothing is stored", () => { expect(sortByStoredOrder(lanes(1, 2, 3), [])).toEqual(lanes(1, 2, 3)); }); it("applies the stored order", () => { expect(sortByStoredOrder(lanes(1, 2, 3), [3, 1, 2])).toEqual(lanes(3, 1, 2)); }); it("appends lanes the stored order has never seen, in server order", () => { expect(sortByStoredOrder(lanes(1, 2, 3, 4), [3, 1])).toEqual(lanes(3, 1, 2, 4)); }); it("skips stored ids whose lane no longer exists", () => { expect(sortByStoredOrder(lanes(1, 3), [3, 2, 1])).toEqual(lanes(3, 1)); }); it("does not mutate the input", () => { const input = lanes(1, 2, 3); sortByStoredOrder(input, [3, 2, 1]); expect(input.map((l) => l.id)).toEqual([1, 2, 3]); }); }); describe("moveLane", () => { it("moves a card forward", () => { expect(moveLane([1, 2, 3], 0, 2)).toEqual([2, 3, 1]); }); it("moves a card backward", () => { expect(moveLane([1, 2, 3], 2, 0)).toEqual([3, 1, 2]); }); it("returns the order unchanged for a no-op or out-of-range move", () => { expect(moveLane([1, 2, 3], 1, 1)).toEqual([1, 2, 3]); expect(moveLane([1, 2, 3], 0, 3)).toEqual([1, 2, 3]); expect(moveLane([1, 2, 3], -1, 0)).toEqual([1, 2, 3]); }); });