80 lines
2.3 KiB
TypeScript
80 lines
2.3 KiB
TypeScript
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');
|
|
});
|
|
});
|