2a14080b5b
Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
3.0 KiB
TypeScript
97 lines
3.0 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
fetchAppearancePrefs,
|
|
saveAppearancePrefsToServer,
|
|
syncAppearancePrefs
|
|
} from './appearancePrefs.js'
|
|
import { setThemePreference } from './userPreferences.js'
|
|
|
|
const USER_ID = 'appearance-sync-user'
|
|
|
|
vi.mock('./api.js', () => ({
|
|
apiJson: vi.fn()
|
|
}))
|
|
|
|
import { apiJson } from './api.js'
|
|
|
|
const mockedApiJson = vi.mocked(apiJson)
|
|
|
|
describe('appearancePrefs', () => {
|
|
beforeEach(() => {
|
|
localStorage.clear()
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
it('fetchAppearancePrefs returns defaults when not authenticated', async () => {
|
|
await expect(fetchAppearancePrefs()).resolves.toEqual({
|
|
theme: 'auto',
|
|
colorScheme: 'auto',
|
|
persisted: false
|
|
})
|
|
expect(mockedApiJson).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('syncAppearancePrefs applies server prefs after cache wipe', async () => {
|
|
localStorage.setItem('active_userid', USER_ID)
|
|
mockedApiJson.mockResolvedValueOnce({
|
|
theme: 'ocean',
|
|
colorScheme: 'dark',
|
|
persisted: true
|
|
})
|
|
|
|
const changed = vi.fn()
|
|
window.addEventListener('appearance-changed', changed)
|
|
|
|
await syncAppearancePrefs(USER_ID)
|
|
|
|
expect(localStorage.getItem(`user_pref_theme_${USER_ID}`)).toBe('ocean')
|
|
expect(localStorage.getItem(`user_pref_color_scheme_${USER_ID}`)).toBe('dark')
|
|
expect(changed).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('syncAppearancePrefs uploads local prefs when server has none', async () => {
|
|
localStorage.setItem('active_userid', USER_ID)
|
|
setThemePreference(USER_ID, 'material')
|
|
mockedApiJson
|
|
.mockResolvedValueOnce({ theme: 'auto', colorScheme: 'auto', persisted: false })
|
|
.mockResolvedValueOnce({ theme: 'material', colorScheme: 'auto', persisted: true })
|
|
|
|
await syncAppearancePrefs(USER_ID)
|
|
|
|
expect(mockedApiJson).toHaveBeenCalledTimes(2)
|
|
expect(mockedApiJson).toHaveBeenLastCalledWith('/api/auth/appearance-prefs', {
|
|
method: 'PUT',
|
|
body: JSON.stringify({ theme: 'material', colorScheme: 'auto' })
|
|
})
|
|
})
|
|
|
|
it('saveAppearancePrefsToServer skips when not authenticated', async () => {
|
|
await saveAppearancePrefsToServer('ocean', 'light')
|
|
expect(mockedApiJson).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('syncAppearancePrefs skips server sync when userId does not match active session', async () => {
|
|
localStorage.setItem('active_userid', 'session-user')
|
|
setThemePreference('other-user', 'ocean')
|
|
mockedApiJson.mockResolvedValue({
|
|
theme: 'material',
|
|
colorScheme: 'dark',
|
|
persisted: true
|
|
})
|
|
|
|
await syncAppearancePrefs('other-user')
|
|
|
|
expect(mockedApiJson).not.toHaveBeenCalled()
|
|
expect(localStorage.getItem('user_pref_theme_other-user')).toBe('ocean')
|
|
})
|
|
|
|
it('syncAppearancePrefs skips server sync when active session is missing', async () => {
|
|
setThemePreference(USER_ID, 'ocean')
|
|
|
|
await syncAppearancePrefs(USER_ID)
|
|
|
|
expect(mockedApiJson).not.toHaveBeenCalled()
|
|
expect(localStorage.getItem(`user_pref_theme_${USER_ID}`)).toBe('ocean')
|
|
})
|
|
})
|