import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' const updateAction = vi.fn() vi.mock('@/actions/user-settings', () => ({ updateUserSettingsAction: (...args: unknown[]) => updateAction(...args), })) import { useUserSettingsStore } from '@/stores/user-settings/store' function resetStore() { useUserSettingsStore.setState((s) => { s.entities.settings = {} s.context.hydrated = false s.context.isDemo = false s.pendingMutations = {} }) } beforeEach(() => { resetStore() updateAction.mockReset() }) afterEach(() => { resetStore() }) describe('useUserSettingsStore', () => { it('hydrate sets entities and context', () => { useUserSettingsStore.getState().hydrate( { views: { sprintBacklog: { sort: 'code' } } }, false, ) const s = useUserSettingsStore.getState() expect(s.entities.settings.views?.sprintBacklog?.sort).toBe('code') expect(s.context.hydrated).toBe(true) expect(s.context.isDemo).toBe(false) }) it('setPref updates state optimistically and settles on success', async () => { useUserSettingsStore.getState().hydrate({}, false) updateAction.mockResolvedValueOnce({ success: true, settings: { views: { sprintBacklog: { filterStatus: 'all' } } }, }) await useUserSettingsStore .getState() .setPref(['views', 'sprintBacklog', 'filterStatus'], 'all') const s = useUserSettingsStore.getState() expect(s.entities.settings.views?.sprintBacklog?.filterStatus).toBe('all') expect(Object.keys(s.pendingMutations)).toHaveLength(0) expect(updateAction).toHaveBeenCalledWith({ views: { sprintBacklog: { filterStatus: 'all' } }, }) }) it('setPref rolls back on server error', async () => { useUserSettingsStore.getState().hydrate( { views: { sprintBacklog: { sort: 'code' } } }, false, ) updateAction.mockResolvedValueOnce({ error: 'boom', code: 422 }) await useUserSettingsStore .getState() .setPref(['views', 'sprintBacklog', 'sort'], 'priority') const s = useUserSettingsStore.getState() expect(s.entities.settings.views?.sprintBacklog?.sort).toBe('code') expect(Object.keys(s.pendingMutations)).toHaveLength(0) }) it('setPref skips server-call for demo accounts', async () => { useUserSettingsStore.getState().hydrate({}, true) await useUserSettingsStore .getState() .setPref(['devTools', 'debugMode'], true) const s = useUserSettingsStore.getState() expect(s.entities.settings.devTools?.debugMode).toBe(true) expect(updateAction).not.toHaveBeenCalled() }) it('applyServerPatch merges without optimistic state', () => { useUserSettingsStore.getState().hydrate( { views: { sprintBacklog: { sort: 'code' } } }, false, ) useUserSettingsStore.getState().applyServerPatch({ views: { sprintBacklog: { sortDir: 'desc' } }, }) const s = useUserSettingsStore.getState() expect(s.entities.settings.views?.sprintBacklog).toEqual({ sort: 'code', sortDir: 'desc', }) expect(Object.keys(s.pendingMutations)).toHaveLength(0) }) })