import { DEFAULT_AVATAR_COLOR_KEY } from '../../../components/display/utils/avatar_gradient_colors' import type { AvatarUpdatePayload } from '../../../hooks/use_conversation_avatar_update' import type { ConversationResource } from '../../../types' import { avatarPickerReducer, initAvatarPickerState, initAvatarPickerStateFromPayload, initEmptyAvatarPickerState, } from '../avatar_picker_state' const emptyState = initEmptyAvatarPickerState() describe('initEmptyAvatarPickerState', () => { it('starts clean', () => { expect(emptyState).toMatchObject({ activeTab: 'icon', selectedType: null, selectedKey: null, selectedColor: DEFAULT_AVATAR_COLOR_KEY, imagePreviewUri: null, imageAsset: null, isDirty: false, }) }) }) describe('initAvatarPickerState', () => { it('seeds from icon avatar', () => { const conversation = { customAvatarType: 'icon' as const, customAvatarKey: 'guitar', customAvatarColor: 'cosmic', customAvatarImageUrl: null, } as Pick< ConversationResource, 'customAvatarType' | 'customAvatarKey' | 'customAvatarColor' | 'customAvatarImageUrl' > const state = initAvatarPickerState(conversation) expect(state).toMatchObject({ activeTab: 'icon', selectedType: 'icon', selectedKey: 'guitar', selectedColor: 'cosmic', isDirty: false, }) }) it('seeds from image avatar — active tab is upload', () => { const conversation = { customAvatarType: 'image' as const, customAvatarKey: null, customAvatarColor: 'rose-gold', customAvatarImageUrl: 'https://example.com/avatar.jpg', } as Pick< ConversationResource, 'customAvatarType' | 'customAvatarKey' | 'customAvatarColor' | 'customAvatarImageUrl' > const state = initAvatarPickerState(conversation) expect(state).toMatchObject({ activeTab: 'upload', selectedType: 'image', imagePreviewUri: 'https://example.com/avatar.jpg', imageAsset: null, isDirty: false, }) }) it('falls back to icon tab and default color when no avatar', () => { const conversation = { customAvatarType: null, customAvatarKey: null, customAvatarColor: null, customAvatarImageUrl: null, } as Pick< ConversationResource, 'customAvatarType' | 'customAvatarKey' | 'customAvatarColor' | 'customAvatarImageUrl' > const state = initAvatarPickerState(conversation) expect(state).toMatchObject({ activeTab: 'icon', selectedType: null, selectedColor: DEFAULT_AVATAR_COLOR_KEY, isDirty: false, }) }) }) describe('initAvatarPickerStateFromPayload', () => { it('restores icon payload', () => { const payload: AvatarUpdatePayload = { kind: 'icon', key: 'dove', color: 'twilight' } const state = initAvatarPickerStateFromPayload(payload) expect(state).toMatchObject({ activeTab: 'icon', selectedType: 'icon', selectedKey: 'dove', selectedColor: 'twilight', isDirty: false, }) }) it('restores emoji payload', () => { const payload: AvatarUpdatePayload = { kind: 'emoji', key: '🎸', color: 'garden' } const state = initAvatarPickerStateFromPayload(payload) expect(state).toMatchObject({ activeTab: 'emoji', selectedType: 'emoji', selectedKey: '🎸', isDirty: false, }) }) it('falls back to empty state for clear payload', () => { const payload: AvatarUpdatePayload = { kind: 'clear' } const state = initAvatarPickerStateFromPayload(payload) expect(state).toMatchObject(emptyState) }) }) describe('avatarPickerReducer', () => { it('SELECT_ICON sets type, key, isDirty', () => { const state = avatarPickerReducer(emptyState, { type: 'SELECT_ICON', payload: 'guitar' }) expect(state).toMatchObject({ selectedType: 'icon', selectedKey: 'guitar', isDirty: true }) }) it('SELECT_EMOJI sets type, key, isDirty', () => { const state = avatarPickerReducer(emptyState, { type: 'SELECT_EMOJI', payload: '🎵' }) expect(state).toMatchObject({ selectedType: 'emoji', selectedKey: '🎵', isDirty: true }) }) it('SELECT_COLOR updates color and sets isDirty', () => { const state = avatarPickerReducer(emptyState, { type: 'SELECT_COLOR', payload: 'cosmic' }) expect(state).toMatchObject({ selectedColor: 'cosmic', isDirty: true }) }) it('SELECT_TAB switches tab without setting isDirty', () => { const state = avatarPickerReducer(emptyState, { type: 'SELECT_TAB', payload: 'emoji' }) expect(state.activeTab).toBe('emoji') expect(state.isDirty).toBe(false) }) it('CLEAR resets selection, color, and sets isDirty', () => { const withIcon = avatarPickerReducer(emptyState, { type: 'SELECT_ICON', payload: 'dove' }) const withColor = avatarPickerReducer(withIcon, { type: 'SELECT_COLOR', payload: 'cosmic' }) const cleared = avatarPickerReducer(withColor, { type: 'CLEAR' }) expect(cleared).toMatchObject({ selectedType: null, selectedKey: null, selectedColor: DEFAULT_AVATAR_COLOR_KEY, imagePreviewUri: null, imageAsset: null, isDirty: true, }) }) })