import { describe, it, expect, beforeEach } from "vitest"; import { useFocusStore } from "@/stores/focus-store"; import { makeFocusItem } from "../helpers/fixtures"; describe("useFocusStore", () => { beforeEach(() => { // Clear persisted state before each test localStorage.clear(); // Reset store between tests useFocusStore.setState({ current: null, queue: [], isLoading: false, error: null, }); }); describe("setItems", () => { it("sets first item as current and rest as queue", () => { const items = [ makeFocusItem({ id: "a", title: "First" }), makeFocusItem({ id: "b", title: "Second" }), makeFocusItem({ id: "c", title: "Third" }), ]; useFocusStore.getState().setItems(items); const state = useFocusStore.getState(); expect(state.current?.id).toBe("a"); expect(state.queue).toHaveLength(2); expect(state.queue[0].id).toBe("b"); expect(state.queue[1].id).toBe("c"); }); it("sets current to null when empty", () => { useFocusStore.getState().setItems([]); const state = useFocusStore.getState(); expect(state.current).toBeNull(); expect(state.queue).toHaveLength(0); }); it("clears loading and error on setItems", () => { useFocusStore.setState({ isLoading: true, error: "old error" }); useFocusStore.getState().setItems([makeFocusItem()]); const state = useFocusStore.getState(); expect(state.isLoading).toBe(false); expect(state.error).toBeNull(); }); }); describe("act", () => { it("advances to next item in queue", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "a" }), makeFocusItem({ id: "b" }), makeFocusItem({ id: "c" }), ]); const next = useFocusStore.getState().act("start"); expect(next?.id).toBe("b"); expect(useFocusStore.getState().current?.id).toBe("b"); expect(useFocusStore.getState().queue).toHaveLength(1); }); it("returns null when queue is empty", () => { useFocusStore.getState().setItems([makeFocusItem({ id: "only" })]); const next = useFocusStore.getState().act("skip"); expect(next).toBeNull(); expect(useFocusStore.getState().current).toBeNull(); expect(useFocusStore.getState().queue).toHaveLength(0); }); it("works with defer_1h action", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "a" }), makeFocusItem({ id: "b" }), ]); useFocusStore.getState().act("defer_1h", "in a meeting"); expect(useFocusStore.getState().current?.id).toBe("b"); }); it("works with defer_tomorrow action", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "a" }), makeFocusItem({ id: "b" }), ]); useFocusStore.getState().act("defer_tomorrow"); expect(useFocusStore.getState().current?.id).toBe("b"); }); }); describe("setFocus", () => { it("promotes a queue item to current", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "a", title: "First" }), makeFocusItem({ id: "b", title: "Second" }), makeFocusItem({ id: "c", title: "Third" }), ]); useFocusStore.getState().setFocus("c"); const state = useFocusStore.getState(); expect(state.current?.id).toBe("c"); // Previous current and other queue items are in queue expect(state.queue.map((i) => i.id)).toEqual( expect.arrayContaining(["a", "b"]) ); expect(state.queue).toHaveLength(2); }); it("does nothing for unknown item ID", () => { useFocusStore.getState().setItems([makeFocusItem({ id: "a" })]); useFocusStore.getState().setFocus("nonexistent"); expect(useFocusStore.getState().current?.id).toBe("a"); }); }); describe("reorderQueue", () => { it("moves an item from one position to another", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "focus" }), makeFocusItem({ id: "a" }), makeFocusItem({ id: "b" }), makeFocusItem({ id: "c" }), ]); useFocusStore.getState().reorderQueue(2, 0); const ids = useFocusStore.getState().queue.map((i) => i.id); expect(ids).toEqual(["c", "a", "b"]); }); it("does nothing for same from/to index", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "focus" }), makeFocusItem({ id: "a" }), makeFocusItem({ id: "b" }), ]); useFocusStore.getState().reorderQueue(0, 0); const ids = useFocusStore.getState().queue.map((i) => i.id); expect(ids).toEqual(["a", "b"]); }); it("does nothing for out-of-bounds indices", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "focus" }), makeFocusItem({ id: "a" }), ]); useFocusStore.getState().reorderQueue(-1, 0); useFocusStore.getState().reorderQueue(0, 5); expect(useFocusStore.getState().queue.map((i) => i.id)).toEqual(["a"]); }); it("does not affect current focus", () => { useFocusStore.getState().setItems([ makeFocusItem({ id: "focus" }), makeFocusItem({ id: "a" }), makeFocusItem({ id: "b" }), ]); useFocusStore.getState().reorderQueue(1, 0); expect(useFocusStore.getState().current?.id).toBe("focus"); }); }); describe("setLoading / setError", () => { it("sets loading state", () => { useFocusStore.getState().setLoading(true); expect(useFocusStore.getState().isLoading).toBe(true); }); it("sets error state", () => { useFocusStore.getState().setError("something broke"); expect(useFocusStore.getState().error).toBe("something broke"); }); }); describe("persistence", () => { it("persists current and queue to localStorage", () => { const items = [ makeFocusItem({ id: "a", title: "First" }), makeFocusItem({ id: "b", title: "Second" }), ]; useFocusStore.getState().setItems(items); const stored = localStorage.getItem("mc-focus-store"); expect(stored).not.toBeNull(); const parsed = JSON.parse(stored!); expect(parsed.state.current.id).toBe("a"); expect(parsed.state.queue).toHaveLength(1); expect(parsed.state.queue[0].id).toBe("b"); }); it("does not persist isLoading or error", () => { useFocusStore.setState({ isLoading: true, error: "oops" }); const stored = localStorage.getItem("mc-focus-store"); expect(stored).not.toBeNull(); const parsed = JSON.parse(stored!); expect(parsed.state).not.toHaveProperty("isLoading"); expect(parsed.state).not.toHaveProperty("error"); }); }); });