@quantumai/quantum-cli-core
Version:
Quantum CLI Core - Multi-LLM Collaboration System
201 lines • 7.3 kB
JavaScript
/**
* @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