import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { setActivePinia, createPinia } from 'pinia' import { useDevicesStore } from '@/stores/devices' import type { Device } from '@/types' const makeDevice = (overrides: Partial = {}): Device => ({ id: 1, mac: 'AA:BB:CC:DD:EE:FF', name: 'Living Room', orientation: 'landscape', rotationIntervalMinutes: 60, wakeHour: null, timezone: 'America/Chicago', uniquenessWindow: 30, linkedAt: '2026-01-01T00:00:00Z', lastSeenAt: null, lockedImageId: null, ...overrides, }) describe('devices store', () => { beforeEach(() => { vi.unstubAllGlobals() vi.restoreAllMocks() setActivePinia(createPinia()) }) afterEach(() => { // unstubAllGlobals is handled in beforeEach so stubs don't leak // even if a test throws before afterEach runs }) // DS-01 it('fetchDevices success populates devices and clears loading', async () => { const mockDevices = [makeDevice()] vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve(mockDevices), })) const store = useDevicesStore() await store.fetchDevices() expect(store.devices).toEqual(mockDevices) expect(store.loading).toBe(false) expect(store.error).toBeNull() }) // DS-02 it('fetchDevices network error sets error state', async () => { vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('Network failure'))) const store = useDevicesStore() await store.fetchDevices() expect(store.devices).toEqual([]) expect(store.loading).toBe(false) expect(store.error).toBe('Network failure') }) // DS-02b — non-ok response it('fetchDevices non-ok response sets error state', async () => { vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: false })) const store = useDevicesStore() await store.fetchDevices() expect(store.error).toBe('Failed to load devices') expect(store.loading).toBe(false) }) // DS-03 it('updateDevice patches local array entry', async () => { const original = makeDevice({ id: 1, name: 'Old Name' }) const updated = makeDevice({ id: 1, name: 'New Name' }) const store = useDevicesStore() store.devices = [original] vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve(updated), })) const result = await store.updateDevice(1, { name: 'New Name' }) expect(result.name).toBe('New Name') expect(store.devices[0].name).toBe('New Name') }) // DS-03b — updateDevice throws on failure it('updateDevice throws on non-ok response', async () => { const store = useDevicesStore() store.devices = [makeDevice()] vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: false })) await expect(store.updateDevice(1, { name: 'x' })).rejects.toThrow('Failed to update device') }) // DS-04 it('lockImage sets lockedImageId on local device', async () => { const device = makeDevice({ id: 1, lockedImageId: null }) const locked = makeDevice({ id: 1, lockedImageId: 42 }) const store = useDevicesStore() store.devices = [device] vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve(locked), })) const result = await store.lockImage(1, 42) expect(result.lockedImageId).toBe(42) expect(store.devices[0].lockedImageId).toBe(42) }) // DS-05 it('unlockImage clears lockedImageId', async () => { const device = makeDevice({ id: 1, lockedImageId: 42 }) const unlocked = makeDevice({ id: 1, lockedImageId: null }) const store = useDevicesStore() store.devices = [device] vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve(unlocked), })) const result = await store.unlockImage(1) expect(result.lockedImageId).toBeNull() expect(store.devices[0].lockedImageId).toBeNull() }) // DS-05b — lockImage throws on failure it('lockImage throws on non-ok response', async () => { const store = useDevicesStore() store.devices = [makeDevice()] vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: false })) await expect(store.lockImage(1, 42)).rejects.toThrow('Failed to lock image') }) // DS-05c — unlockImage throws on failure it('unlockImage throws on non-ok response', async () => { const store = useDevicesStore() store.devices = [makeDevice()] vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: false })) await expect(store.unlockImage(1)).rejects.toThrow('Failed to unlock') }) })