import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { __resetForTests, clearDraft, getDraftSync, hasDraft, hydrateDrafts, setDraft, } from './composerDraftStore'; const sqlExecuteMock = vi.fn().mockResolvedValue(undefined); const sqlSelectMock = vi.fn().mockResolvedValue([]); const sqlLoadMock = vi.fn().mockResolvedValue('mock-handle'); vi.stubGlobal('window', { electronAPI: { platform: 'electron-chatapp-v1', sqlLoad: sqlLoadMock, sqlExecute: sqlExecuteMock, sqlSelect: sqlSelectMock, }, }); describe('composerDraftStore', () => { beforeEach(() => { sqlExecuteMock.mockClear(); sqlSelectMock.mockClear(); sqlLoadMock.mockClear(); __resetForTests(); }); afterEach(() => { __resetForTests(); }); it('returns null for an unknown conversation', () => { expect(getDraftSync('unknown')).toBeNull(); expect(hasDraft('unknown')).toBe(false); }); it('stores and returns a draft synchronously after set', () => { setDraft('a', { text: 'hi', replyToId: null }); const draft = getDraftSync('a'); expect(draft).not.toBeNull(); expect(draft?.text).toBe('hi'); expect(draft?.replyToId).toBeNull(); expect(hasDraft('a')).toBe(true); }); it('isolates drafts per conversation', () => { setDraft('a', { text: 'one', replyToId: null }); setDraft('b', { text: 'two', replyToId: 'msg-9' }); expect(getDraftSync('a')?.text).toBe('one'); expect(getDraftSync('b')?.replyToId).toBe('msg-9'); }); it('clearDraft removes the draft from memory', () => { setDraft('a', { text: 'one', replyToId: null }); clearDraft('a'); expect(getDraftSync('a')).toBeNull(); expect(hasDraft('a')).toBe(false); }); it('treats an empty-string text + null reply as "no draft"', () => { setDraft('a', { text: '', replyToId: null }); expect(getDraftSync('a')).toBeNull(); expect(hasDraft('a')).toBe(false); }); it('hydrateDrafts populates the in-memory map from SQLite rows', async () => { sqlSelectMock.mockResolvedValueOnce([ { conversation_id: 'a', text: 'persisted', reply_to_id: 'msg-1', updated_at: '2026-05-17T00:00:00Z' }, ]); await hydrateDrafts(); expect(getDraftSync('a')?.text).toBe('persisted'); expect(getDraftSync('a')?.replyToId).toBe('msg-1'); }); });