UNPKG

@quantumai/quantum-cli-core

Version:

Quantum CLI Core - Multi-LLM Collaboration System

201 lines 7.3 kB
/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ /** * Tests for OpenAI provider */ import { describe, it, expect, beforeEach, afterEach, vi, } from 'vitest'; import { OpenAIProvider } from './openai-provider.js'; // Create mocked functions const mockCreate = vi.fn(); const mockOpenAIConstructor = vi.fn(); // Mock the OpenAI module vi.mock('openai', () => ({ default: class MockOpenAI { chat = { completions: { create: mockCreate, }, }; constructor(...args) { mockOpenAIConstructor(...args); } }, })); describe('OpenAIProvider', () => { let provider; let config; beforeEach(() => { // Clear mock function calls but not the mock implementation mockCreate.mockClear(); mockOpenAIConstructor.mockClear(); config = { id: 'openai', name: 'OpenAI', type: 'openai', enabled: true, apiKey: 'test-api-key', modelName: 'gpt-3.5-turbo', maxTokens: 2048, temperature: 0.7, capabilities: ['text-generation'], strengths: ['creativity', 'general-knowledge'], costPerToken: 0.002, }; }); afterEach(() => { vi.clearAllMocks(); }); describe('constructor', () => { it('should initialize with config', () => { provider = new OpenAIProvider(config); expect(provider.getId()).toBe('openai'); expect(provider.getType()).toBe('openai'); expect(mockOpenAIConstructor).toHaveBeenCalledWith({ apiKey: 'test-api-key', }); }); it('should get API key from environment if not in config', () => { const envConfig = { ...config, apiKey: undefined, apiKeyEnvVar: 'OPENAI_API_KEY', name: 'OpenAI', }; vi.stubEnv('OPENAI_API_KEY', 'env-key'); provider = new OpenAIProvider(envConfig); expect(provider.getId()).toBe('openai'); expect(mockOpenAIConstructor).toHaveBeenCalledWith({ apiKey: 'env-key' }); vi.unstubAllEnvs(); }); it('should throw error if no API key', () => { const noKeyConfig = { ...config, apiKey: undefined, name: 'OpenAI' }; expect(() => new OpenAIProvider(noKeyConfig)).toThrow('API key not found'); }); }); describe('generate', () => { beforeEach(() => { provider = new OpenAIProvider(config); }); it('should generate response for simple query', async () => { mockCreate.mockResolvedValue({ choices: [ { message: { content: 'This is a test response from GPT-4', }, finish_reason: 'stop', }, ], usage: { total_tokens: 50, }, }); const response = await provider.generate('Test query'); expect(response.providerId).toBe('openai'); expect(response.content).toBe('This is a test response from GPT-4'); expect(response.confidence).toBeGreaterThan(0); expect(mockCreate).toHaveBeenCalledWith({ model: 'gpt-4', messages: [ { role: 'system', content: expect.any(String) }, { role: 'user', content: 'Test query' }, ], max_tokens: 1000, temperature: 0.7, }); }); it('should handle options in query', async () => { mockCreate.mockResolvedValue({ choices: [ { message: { content: 'function test() {}' }, finish_reason: 'stop', }, ], usage: { total_tokens: 30 }, }); const response = await provider.generate('Write a function', { verify: true, }); expect(response.content).toBe('function test() {}'); expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({ messages: expect.arrayContaining([ expect.objectContaining({ role: 'system' }), expect.objectContaining({ role: 'user', content: 'Write a function', }), ]), })); }); it('should handle API errors gracefully', async () => { mockCreate.mockRejectedValue(new Error('API rate limit exceeded')); const response = await provider.generate('Test query'); expect(response.error).toBeDefined(); expect(response.error).toBe('API rate limit exceeded'); expect(response.content).toBe(''); }); }); describe('generateStream', () => { beforeEach(() => { provider = new OpenAIProvider(config); }); it('should stream response chunks', async () => { const mockStream = { async *[Symbol.asyncIterator]() { yield { choices: [ { delta: { content: 'Hello' }, }, ], }; yield { choices: [ { delta: { content: ' world' }, }, ], }; yield { choices: [ { delta: { content: '!' }, }, ], }; }, }; mockCreate.mockResolvedValue(mockStream); const chunks = []; for await (const chunk of provider.generateStream('Test')) { chunks.push(chunk); } expect(chunks).toEqual(['Hello', ' world', '!']); expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({ stream: true, })); }); }); describe('validateConfiguration', () => { beforeEach(() => { provider = new OpenAIProvider(config); }); it('should validate with correct API key', async () => { mockCreate.mockResolvedValue({ choices: [{ message: { content: 'test' } }], }); const isValid = await provider.validateCredentials(); expect(isValid).toBe(true); }); it('should return false for invalid API key', async () => { mockCreate.mockRejectedValue(new Error('Invalid API key')); const isValid = await provider.validateCredentials(); expect(isValid).toBe(false); }); }); }); //# sourceMappingURL=openai-provider.test.js.map