/** * Queue store tests * * TRACES: UR-005, UR-015 | DR-005, DR-020 */ import { describe, it, expect, beforeEach, vi } from "vitest"; import { queue, currentQueueItem, queueItems } from "./queue"; import { get } from "svelte/store"; vi.mock("@tauri-apps/api/core", () => ({ invoke: vi.fn(async (command) => { if (command === "player_get_queue") { return { items: [], currentIndex: null, shuffle: false, repeat: "off", hasNext: false, hasPrevious: false, }; } return null; }), })); vi.mock("@tauri-apps/api/event", () => ({ listen: vi.fn(async () => () => {}), })); describe("queue store", () => { beforeEach(() => { vi.clearAllMocks(); }); describe("queue state structure", () => { it("should have items array", () => { const state = get(queue); expect(state).toHaveProperty("items"); expect(Array.isArray(state.items)).toBe(true); }); it("should track current index", () => { const state = get(queue); expect(state).toHaveProperty("currentIndex"); }); it("should track shuffle state", () => { const state = get(queue); expect(state).toHaveProperty("shuffle"); expect(typeof state.shuffle).toBe("boolean"); }); it("should track repeat mode", () => { const state = get(queue); expect(state).toHaveProperty("repeat"); expect(["off", "all", "one"]).toContain(state.repeat); }); it("should track navigation state", () => { const state = get(queue); expect(state).toHaveProperty("hasNext"); expect(state).toHaveProperty("hasPrevious"); expect(typeof state.hasNext).toBe("boolean"); expect(typeof state.hasPrevious).toBe("boolean"); }); }); describe("derived stores", () => { it("should provide currentQueueItem derived store", () => { const current = get(currentQueueItem); expect(current).toBeDefined(); }); it("should provide queueItems derived store", () => { const items = get(queueItems); expect(Array.isArray(items)).toBe(true); }); }); describe("subscription", () => { it("should allow subscriptions to queue changes", () => { const states: any[] = []; const unsubscribe = queue.subscribe((state) => { states.push(state); }); expect(states.length).toBeGreaterThan(0); unsubscribe(); }); it("should notify multiple subscribers", () => { const states1: any[] = []; const states2: any[] = []; const unsub1 = queue.subscribe((state) => states1.push(state)); const unsub2 = queue.subscribe((state) => states2.push(state)); expect(states1.length).toBe(states2.length); unsub1(); unsub2(); }); }); describe("initial state", () => { it("should start with empty queue", () => { const state = get(queue); expect(state.items.length).toBe(0); }); it("should start with no current track", () => { const state = get(queue); expect(state.currentIndex).toBeNull(); }); it("should start with shuffle off", () => { const state = get(queue); expect(state.shuffle).toBe(false); }); it("should start with repeat off", () => { const state = get(queue); expect(state.repeat).toBe("off"); }); }); describe("queue operations", () => { it("should support clearing queue", () => { if (typeof (queue as any).clear === "function") { (queue as any).clear?.(); const state = get(queue); expect(state.items.length).toBe(0); } }); it("should support adding items to queue", () => { if (typeof (queue as any).addItem === "function") { const mockItem = { id: "test-1", name: "Test Track" }; (queue as any).addItem?.(mockItem); const state = get(queue); expect(state.items.length).toBeGreaterThanOrEqual(0); } }); }); describe("repeat modes", () => { it("should support off repeat mode", () => { const state = get(queue); expect(["off", "all", "one"]).toContain(state.repeat); }); it("should cycle through repeat modes", () => { const state = get(queue); const validModes = ["off", "all", "one"]; expect(validModes).toContain(state.repeat); }); }); describe("shuffle", () => { it("should track shuffle state", () => { const state = get(queue); expect(typeof state.shuffle).toBe("boolean"); }); it("should toggle shuffle if method exists", () => { if (typeof (queue as any).toggleShuffle === "function") { const before = get(queue).shuffle; (queue as any).toggleShuffle?.(); const after = get(queue).shuffle; expect(typeof after).toBe("boolean"); } }); }); });