diff --git a/src/utils/__tests__/preferences.utils.test.ts b/src/utils/__tests__/preferences.utils.test.ts new file mode 100644 index 0000000..161c438 --- /dev/null +++ b/src/utils/__tests__/preferences.utils.test.ts @@ -0,0 +1,33 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { getPreference, setPreference } from '../preferences.utils'; + +describe('preferences.utils', () => { + beforeEach(() => { + window.localStorage.clear(); + }); + + it('returns stored value for a key that exists', () => { + window.localStorage.setItem('testKey', JSON.stringify({ theme: 'dark' })); + const result = getPreference('testKey', { theme: 'light' }); + expect(result).toEqual({ theme: 'dark' }); + }); + + it('returns default value for a missing key', () => { + const result = getPreference('missingKey', 'default-value'); + expect(result).toBe('default-value'); + }); + + it('returns default value if stored JSON is malformed', () => { + window.localStorage.setItem('malformedKey', '{ invalid json '); + const result = getPreference('malformedKey', 'default-value'); + expect(result).toBe('default-value'); + }); + + it('set and get round-trip correctly', () => { + const complexValue = { sort: 'desc', filter: ['active', 'verified'] }; + setPreference('complexKey', complexValue); + + const result = getPreference('complexKey', { sort: 'asc', filter: [] }); + expect(result).toEqual(complexValue); + }); +}); diff --git a/src/utils/preferences.utils.ts b/src/utils/preferences.utils.ts new file mode 100644 index 0000000..c8c0d23 --- /dev/null +++ b/src/utils/preferences.utils.ts @@ -0,0 +1,36 @@ +/** + * Retrieves a parsed value from localStorage. + * Handles missing keys and malformed JSON safely by returning the defaultValue. + * + * @param key The localStorage key to retrieve + * @param defaultValue The default value to return if the key is missing or parsing fails + * @returns The parsed value or the default value + */ +export function getPreference(key: string, defaultValue: T): T { + try { + const item = window.localStorage.getItem(key); + if (item === null) { + return defaultValue; + } + return JSON.parse(item) as T; + } catch (error) { + console.warn(`Error reading localStorage key "${key}":`, error); + return defaultValue; + } +} + +/** + * Serializes and stores a value in localStorage. + * Safely handles potential storage errors (e.g., quota exceeded). + * + * @param key The localStorage key to set + * @param value The value to serialize and store + */ +export function setPreference(key: string, value: T): void { + try { + const serialized = JSON.stringify(value); + window.localStorage.setItem(key, serialized); + } catch (error) { + console.warn(`Error setting localStorage key "${key}":`, error); + } +}