128 lines
4.8 KiB
TypeScript
128 lines
4.8 KiB
TypeScript
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
|
|
import { useAIStore } from './aiStore';
|
|
|
|
|
|
function mockElectronAPI() {
|
|
(window as any).electronAPI = {
|
|
encryptString: vi.fn().mockResolvedValue('encrypted-value'),
|
|
decryptString: vi.fn().mockResolvedValue('decrypted-key'),
|
|
};
|
|
}
|
|
|
|
describe('aiStore', () => {
|
|
beforeEach(() => {
|
|
mockElectronAPI();
|
|
useAIStore.setState({
|
|
providers: {
|
|
ollama: { provider: 'ollama', baseUrl: 'http://localhost:11434', model: 'llama3' },
|
|
openai: { provider: 'openai', apiKey: '', model: 'gpt-4o' },
|
|
claude: { provider: 'claude', apiKey: '', model: 'claude-sonnet-4-20250514' },
|
|
},
|
|
defaultProvider: 'ollama',
|
|
customFillerWords: '',
|
|
fillerResult: null,
|
|
clipSuggestions: [],
|
|
isProcessing: false,
|
|
processingMessage: '',
|
|
_keysHydrated: false,
|
|
});
|
|
});
|
|
|
|
describe('setProviderConfig', () => {
|
|
test('updates Ollama base URL', () => {
|
|
useAIStore.getState().setProviderConfig('ollama', { baseUrl: 'http://custom:11434' });
|
|
expect(useAIStore.getState().providers.ollama.baseUrl).toBe('http://custom:11434');
|
|
});
|
|
|
|
test('updates Ollama model', () => {
|
|
useAIStore.getState().setProviderConfig('ollama', { model: 'llama3.2' });
|
|
expect(useAIStore.getState().providers.ollama.model).toBe('llama3.2');
|
|
});
|
|
|
|
test('updates OpenAI apiKey and encrypts', async () => {
|
|
useAIStore.getState().setProviderConfig('openai', { apiKey: 'sk-test123' });
|
|
expect(useAIStore.getState().providers.openai.apiKey).toBe('sk-test123');
|
|
expect((window as any).electronAPI.encryptString).toHaveBeenCalledWith('sk-test123');
|
|
});
|
|
|
|
test('updates Claude model', () => {
|
|
useAIStore.getState().setProviderConfig('claude', { model: 'claude-opus-4-20250514' });
|
|
expect(useAIStore.getState().providers.claude.model).toBe('claude-opus-4-20250514');
|
|
});
|
|
|
|
test('preserves existing config when updating partial fields', () => {
|
|
useAIStore.getState().setProviderConfig('openai', { apiKey: 'sk-new', model: 'gpt-4o-mini' });
|
|
expect(useAIStore.getState().providers.openai.apiKey).toBe('sk-new');
|
|
expect(useAIStore.getState().providers.openai.model).toBe('gpt-4o-mini');
|
|
});
|
|
});
|
|
|
|
describe('setDefaultProvider', () => {
|
|
test('changes default provider', () => {
|
|
useAIStore.getState().setDefaultProvider('openai');
|
|
expect(useAIStore.getState().defaultProvider).toBe('openai');
|
|
});
|
|
|
|
test('can switch to claude', () => {
|
|
useAIStore.getState().setDefaultProvider('claude');
|
|
expect(useAIStore.getState().defaultProvider).toBe('claude');
|
|
});
|
|
});
|
|
|
|
describe('setCustomFillerWords', () => {
|
|
test('sets custom filler words', () => {
|
|
useAIStore.getState().setCustomFillerWords('okay, alright, anyway');
|
|
expect(useAIStore.getState().customFillerWords).toBe('okay, alright, anyway');
|
|
});
|
|
|
|
test('clears custom filler words', () => {
|
|
useAIStore.getState().setCustomFillerWords('test');
|
|
useAIStore.getState().setCustomFillerWords('');
|
|
expect(useAIStore.getState().customFillerWords).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('setFillerResult', () => {
|
|
test('sets filler result', () => {
|
|
const result = { fillers: [{ word: 'um', start: 1.0, end: 1.3 }], totalCount: 1 };
|
|
useAIStore.getState().setFillerResult(result as any);
|
|
expect(useAIStore.getState().fillerResult).toEqual(result);
|
|
});
|
|
|
|
test('clears filler result', () => {
|
|
useAIStore.getState().setFillerResult({ fillers: [], totalCount: 0 } as any);
|
|
useAIStore.getState().setFillerResult(null);
|
|
expect(useAIStore.getState().fillerResult).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('setProcessing', () => {
|
|
test('sets processing true with message', () => {
|
|
useAIStore.getState().setProcessing(true, 'Analyzing transcript...');
|
|
expect(useAIStore.getState().isProcessing).toBe(true);
|
|
expect(useAIStore.getState().processingMessage).toBe('Analyzing transcript...');
|
|
});
|
|
|
|
test('sets processing false', () => {
|
|
useAIStore.getState().setProcessing(true, 'Working...');
|
|
useAIStore.getState().setProcessing(false);
|
|
expect(useAIStore.getState().isProcessing).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('setClipSuggestions', () => {
|
|
test('sets clip suggestions', () => {
|
|
const clips = [{ title: 'Best moment', start: 10, end: 40, reason: 'Engaging' }];
|
|
useAIStore.getState().setClipSuggestions(clips as any);
|
|
expect(useAIStore.getState().clipSuggestions).toEqual(clips);
|
|
});
|
|
|
|
test('clears clip suggestions', () => {
|
|
useAIStore.getState().setClipSuggestions([{ title: 'x', start: 0, end: 10, reason: 'y' }] as any);
|
|
useAIStore.getState().setClipSuggestions([]);
|
|
expect(useAIStore.getState().clipSuggestions).toEqual([]);
|
|
});
|
|
});
|
|
});
|