Files
babymonitor/frontend/tests/unit/hooks/useSettings.test.tsx
T

124 lines
3.6 KiB
TypeScript

import { renderHook, act } from '@testing-library/react';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { useSettings } from '../../../src/hooks/useSettings';
import { SettingsProvider } from '../../../src/hooks/SettingsProvider';
describe('useSettings hook', () => {
// Mock implementation of localStorage
const localStorageMock = (() => {
let store: Record<string, string> = {};
return {
getItem: vi.fn((key: string) => store[key] || null),
setItem: vi.fn((key: string, value: string) => {
store[key] = value.toString();
}),
removeItem: vi.fn((key: string) => {
delete store[key];
}),
clear: vi.fn(() => {
store = {};
}),
};
})();
beforeEach(() => {
vi.stubGlobal('localStorage', localStorageMock);
vi.clearAllMocks();
// Clear the mock store
(localStorage as any).clear();
});
const wrapper = ({ children }: { children: React.ReactNode }) => (
<SettingsProvider>{children}</SettingsProvider>
);
it('should return default settings when wrapped in SettingsProvider', () => {
const { result } = renderHook(() => useSettings(), { wrapper });
expect(result.current.settings).toEqual({
dayStart: '07:00',
dayEnd: '20:00',
wakeupRef: '04:00',
bedtimeRef: '19:00',
statsInterval: 7,
sessionsPerPage: 10,
});
});
it('should throw an error when used outside of SettingsProvider', () => {
expect(() => renderHook(() => useSettings())).toThrow(
'useSettings must be used within a SettingsProvider'
);
});
it('should update settings correctly via the update function', () => {
const { result } = renderHook(() => useSettings(), { wrapper });
act(() => {
result.current.update('dayStart', '08:30');
});
expect(result.current.settings.dayStart).toBe('08:30');
// Verify other settings remain unchanged
expect(result.current.settings.dayEnd).toBe('20:00');
});
it('should persist updated settings to localStorage', () => {
const setItemSpy = vi.spyOn(localStorage, 'setItem');
const { result } = renderHook(() => useSettings(), { wrapper });
act(() => {
result.current.update('statsInterval', 14);
});
expect(setItemSpy).toHaveBeenCalledWith(
'baby-sleep-settings',
expect.stringContaining('"statsInterval":14')
);
});
it('should initialize with settings from localStorage if available', () => {
const storedSettings = {
dayStart: '10:00',
dayEnd: '22:00',
wakeupRef: '06:00',
bedtimeRef: '21:00',
statsInterval: 5,
sessionsPerPage: 20,
};
localStorage.setItem('baby-sleep-settings', JSON.stringify(storedSettings));
const { result } = renderHook(() => useSettings(), { wrapper });
expect(result.current.settings).toEqual(storedSettings);
});
it('should fallback to default settings if localStorage contains invalid JSON', () => {
localStorage.setItem('baby-sleep-settings', 'invalid-json');
const { result } = renderHook(() => useSettings(), { wrapper });
expect(result.current.settings).toEqual({
dayStart: '07:00',
dayEnd: '20:00',
wakeupRef: '04:00',
bedtimeRef: '19:00',
statsInterval: 7,
sessionsPerPage: 10,
});
});
it('should handle empty localStorage by using default settings', () => {
localStorage.clear();
const { result } = renderHook(() => useSettings(), { wrapper });
expect(result.current.settings).toEqual({
dayStart: '07:00',
dayEnd: '20:00',
wakeupRef: '04:00',
bedtimeRef: '19:00',
statsInterval: 7,
sessionsPerPage: 10,
});
});
});