import { describe, it, expect, beforeEach, vi } from 'vitest' import { createPinia, setActivePinia } from 'pinia' import { useUi } from '../useUi' // Adjust path as necessary // Mock localStorage const localStorageMock = (() => { let store = {} return { getItem: vi.fn((key) => store[key] || null), setItem: vi.fn((key, value) => { store[key] = value.toString() }), clear: vi.fn(() => { store = {} }), removeItem: vi.fn((key) => { delete store[key] }), } })() // Define the storage key, matching the one in useUi.js const APPEARANCE_STORAGE_KEY = 'appearanceSettings'; // Apply the mock to window.localStorage BEFORE store import or usage vi.stubGlobal('localStorage', localStorageMock) describe('useUi Store', () => { beforeEach(() => { setActivePinia(createPinia()) localStorageMock.clear() localStorageMock.setItem.mockClear() localStorageMock.getItem.mockClear() // Ensure that when the store is initialized, it re-reads from the (mocked) localStorage // This is important because the store's state definition runs only once when imported. // For tests, we need to control this. Re-importing or using a factory for useUi might be needed // if the store is not re-evaluating its state function that calls loadSettingsFromLocalStorage(). // However, Pinia's setup with setActivePinia(createPinia()) should handle store isolation. }) it('initializes with default appearance settings if no local storage data exists', () => { const store = useUi() expect(store.primaryColor).toBe('#1976D2') expect(store.theme).toBe('light') expect(store.fontSize).toBe(16) // Check new accent color defaults expect(store.accentColorEmpleados).toBe('#2196F3') expect(store.accentColorTareas).toBe('#4CAF50') expect(store.accentColorPlanillas).toBe('#FF9800') expect(store.accentColorAsistencias).toBe('#E91E63') expect(store.accentColorConfiguracion).toBe('#607D8B') // Check new default view defaults expect(store.defaultViewEmpleados).toBe('table') expect(store.defaultViewTareas).toBe('table') expect(store.defaultViewPlanillas).toBe('table') expect(store.defaultViewAsistencias).toBe('table') expect(store.defaultViewConfiguracion).toBe('table') // Check other new defaults expect(store.tableBgColorEmpleados).toBe('#FFFFFF') expect(store.desktopNavbarPersistent).toBe(false) expect(localStorageMock.getItem).toHaveBeenCalledWith(APPEARANCE_STORAGE_KEY) }) it('loads settings from localStorage if present', () => { const storedSettings = { primaryColor: '#FF0000', theme: 'dark', fontSize: 20, animationsEnabled: false, accentColorEmpleados: '#0000FF', accentColorTareas: '#00FF00', accentColorPlanillas: '#FFFF00', accentColorAsistencias: '#FF00FF', accentColorConfiguracion: '#112233', tableBgColorEmpleados: '#EEEEEE', tableBgColorTareas: '#DDDDDD', tableBgColorPlanillas: '#CCCCCC', tableBgColorAsistencias: '#BBBBBB', tableBgColorConfiguracion: '#AAAAAA', desktopNavbarPersistent: true, defaultViewEmpleados: 'card', defaultViewTareas: 'card', defaultViewPlanillas: 'card', defaultViewAsistencias: 'card', defaultViewConfiguracion: 'card', } localStorageMock.getItem.mockReturnValueOnce(JSON.stringify(storedSettings)) const store = useUi() expect(localStorageMock.getItem).toHaveBeenCalledWith(APPEARANCE_STORAGE_KEY) expect(store.primaryColor).toBe('#FF0000') expect(store.theme).toBe('dark') expect(store.fontSize).toBe(20) expect(store.animationsEnabled).toBe(false) expect(store.accentColorEmpleados).toBe('#0000FF') expect(store.accentColorTareas).toBe('#00FF00') expect(store.accentColorPlanillas).toBe('#FFFF00') expect(store.accentColorAsistencias).toBe('#FF00FF') expect(store.accentColorConfiguracion).toBe('#112233') expect(store.tableBgColorEmpleados).toBe('#EEEEEE') expect(store.tableBgColorTareas).toBe('#DDDDDD') expect(store.tableBgColorPlanillas).toBe('#CCCCCC') expect(store.tableBgColorAsistencias).toBe('#BBBBBB') expect(store.tableBgColorConfiguracion).toBe('#AAAAAA') expect(store.desktopNavbarPersistent).toBe(true) expect(store.defaultViewEmpleados).toBe('card') expect(store.defaultViewTareas).toBe('card') expect(store.defaultViewPlanillas).toBe('card') expect(store.defaultViewAsistencias).toBe('card') expect(store.defaultViewConfiguracion).toBe('card') }) it('loads older settings from localStorage and uses defaults for new settings if not present', () => { const olderStoredSettings = { primaryColor: '#ABCDEF', theme: 'dark', fontSize: 18, } // Does not include new accent colors localStorageMock.getItem.mockReturnValueOnce(JSON.stringify(olderStoredSettings)) const store = useUi() expect(store.primaryColor).toBe('#ABCDEF') expect(store.theme).toBe('dark') expect(store.fontSize).toBe(18) // New accent colors should fall back to defaults expect(store.accentColorEmpleados).toBe('#2196F3') // Default expect(store.accentColorTareas).toBe('#4CAF50') // Default expect(store.accentColorPlanillas).toBe('#FF9800') // Default expect(store.accentColorAsistencias).toBe('#E91E63') // Default expect(store.accentColorConfiguracion).toBe('#607D8B') // Default // New default view keys should fall back to 'table' expect(store.defaultViewEmpleados).toBe('table') expect(store.defaultViewTareas).toBe('table') expect(store.defaultViewPlanillas).toBe('table') expect(store.defaultViewAsistencias).toBe('table') expect(store.defaultViewConfiguracion).toBe('table') // Other new keys expect(store.tableBgColorEmpleados).toBe('#FFFFFF') // Default expect(store.desktopNavbarPersistent).toBe(false) // Default }) it('falls back to default settings if localStorage data is invalid JSON', () => { localStorageMock.getItem.mockReturnValueOnce('invalid json') const store = useUi() expect(store.primaryColor).toBe('#1976D2') // Default }) it('falls back to default settings if localStorage is not available (simulated by load error)', () => { // Simulate localStorage.getItem throwing an error by making the mock throw localStorageMock.getItem.mockImplementationOnce(() => { throw new Error("Storage unavailable"); }); const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); // Suppress console.error for this test const store = useUi(); expect(store.primaryColor).toBe('#1976D2'); // Should use default expect(store.theme).toBe('light'); expect(console.error).toHaveBeenCalledWith('Error loading appearance settings from local storage:', expect.any(Error)); consoleErrorSpy.mockRestore(); // Restore console.error }) describe('Actions', () => { // Update this list to match the store's appearanceSettingKeys const appearanceSettingKeysInTest = [ 'primaryColor', 'secondaryColor', 'warningColor', 'fontFamily', 'fontSize', 'animationsEnabled', 'backgroundColor', 'theme', 'accentColorEmpleados', 'accentColorTareas', 'accentColorPlanillas', 'accentColorAsistencias', 'accentColorConfiguracion', 'tableBgColorEmpleados', 'tableBgColorTareas', 'tableBgColorPlanillas', 'tableBgColorAsistencias', 'tableBgColorConfiguracion', 'desktopNavbarPersistent', 'defaultViewEmpleados', 'defaultViewTareas', 'defaultViewPlanillas', 'defaultViewAsistencias', 'defaultViewConfiguracion', ]; it('setPrimaryColor updates state and saves to localStorage', () => { const store = useUi() store.setPrimaryColor('#00FF00') expect(store.primaryColor).toBe('#00FF00') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"primaryColor":"#00FF00"') ) }) it('setFontSize updates state and saves to localStorage', () => { const store = useUi() store.setFontSize(24) expect(store.fontSize).toBe(24) expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"fontSize":24') ) }) it('setAnimationsEnabled updates state and saves to localStorage', () => { const store = useUi() store.setAnimationsEnabled(false) expect(store.animationsEnabled).toBe(false) expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"animationsEnabled":false') ) store.setAnimationsEnabled(true) expect(store.animationsEnabled).toBe(true) expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"animationsEnabled":true') ) }) it('setTheme updates state and saves to localStorage', () => { const store = useUi() store.setTheme('dark') expect(store.theme).toBe('dark') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"theme":"dark"') ) }) it('toggleTheme switches theme and saves to localStorage', () => { const store = useUi() // default is 'light' store.toggleTheme() expect(store.theme).toBe('dark') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"theme":"dark"') ) store.toggleTheme() expect(store.theme).toBe('light') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"theme":"light"') ) }) it('saves only appearance settings to localStorage', () => { const store = useUi() // Clear any previous calls from initialization if store was already used in this describe block localStorageMock.setItem.mockClear(); store.setPrimaryColor('#ABCDEF') // This will trigger a save // Check if setItem was called expect(localStorageMock.setItem).toHaveBeenCalledTimes(1); expect(localStorageMock.setItem).toHaveBeenCalledWith(APPEARANCE_STORAGE_KEY, expect.any(String)); // Now parse the actual saved data const savedDataString = localStorageMock.setItem.mock.calls[0][1]; const savedData = JSON.parse(savedDataString); expect(Object.keys(savedData).length).toBe(appearanceSettingKeysInTest.length); expect(savedData.sidebarOpen).toBeUndefined() // Ensure non-appearance data is not saved appearanceSettingKeysInTest.forEach(key => { //This assertion needs to be robust if some keys are not initialized (e.g. undefined) //However, our store initializes all appearance keys expect(savedData.hasOwnProperty(key)).toBe(true); }) }) // Tests for new accent color actions it('setAccentColorEmpleados updates state and saves to localStorage', () => { const store = useUi() store.setAccentColorEmpleados('#FF1122') expect(store.accentColorEmpleados).toBe('#FF1122') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"accentColorEmpleados":"#FF1122"') ) }) it('setAccentColorTareas updates state and saves to localStorage', () => { const store = useUi() store.setAccentColorTareas('#33FF44') expect(store.accentColorTareas).toBe('#33FF44') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"accentColorTareas":"#33FF44"') ) }) it('setAccentColorPlanillas updates state and saves to localStorage', () => { const store = useUi() store.setAccentColorPlanillas('#5566FF') expect(store.accentColorPlanillas).toBe('#5566FF') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"accentColorPlanillas":"#5566FF"') ) }) it('setAccentColorAsistencias updates state and saves to localStorage', () => { const store = useUi() store.setAccentColorAsistencias('#FF7788') expect(store.accentColorAsistencias).toBe('#FF7788') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"accentColorAsistencias":"#FF7788"') ) }) it('setAccentColorConfiguracion updates state and saves to localStorage', () => { const store = useUi() store.setAccentColorConfiguracion('#99AABB') expect(store.accentColorConfiguracion).toBe('#99AABB') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"accentColorConfiguracion":"#99AABB"') ) }) // Tests for table background color actions it('setTableBgColorEmpleados updates state and saves to localStorage', () => { const store = useUi() store.setTableBgColorEmpleados('#EEECCC') expect(store.tableBgColorEmpleados).toBe('#EEECCC') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"tableBgColorEmpleados":"#EEECCC"') ) }) // Similar tests for Tareas, Planillas, Asistencias, Configuracion table bg colors... it('setDesktopNavbarPersistent updates state and saves to localStorage', () => { const store = useUi() store.setDesktopNavbarPersistent(true) expect(store.desktopNavbarPersistent).toBe(true) expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"desktopNavbarPersistent":true') ) store.setDesktopNavbarPersistent(false) expect(store.desktopNavbarPersistent).toBe(false) expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"desktopNavbarPersistent":false') ) }) // Tests for new default view actions it('setDefaultViewEmpleados updates state and saves to localStorage', () => { const store = useUi() store.setDefaultViewEmpleados('card') expect(store.defaultViewEmpleados).toBe('card') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"defaultViewEmpleados":"card"') ) store.setDefaultViewEmpleados('table') expect(store.defaultViewEmpleados).toBe('table') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"defaultViewEmpleados":"table"') ) }) it('setDefaultViewTareas updates state and saves to localStorage', () => { const store = useUi() store.setDefaultViewTareas('card') expect(store.defaultViewTareas).toBe('card') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"defaultViewTareas":"card"') ) }) it('setDefaultViewPlanillas updates state and saves to localStorage', () => { const store = useUi() store.setDefaultViewPlanillas('card') expect(store.defaultViewPlanillas).toBe('card') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"defaultViewPlanillas":"card"') ) }) it('setDefaultViewAsistencias updates state and saves to localStorage', () => { const store = useUi() store.setDefaultViewAsistencias('card') expect(store.defaultViewAsistencias).toBe('card') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"defaultViewAsistencias":"card"') ) }) it('setDefaultViewConfiguracion updates state and saves to localStorage', () => { const store = useUi() store.setDefaultViewConfiguracion('card') expect(store.defaultViewConfiguracion).toBe('card') expect(localStorageMock.setItem).toHaveBeenCalledWith( APPEARANCE_STORAGE_KEY, expect.stringContaining('"defaultViewConfiguracion":"card"') ) }) }) })