mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 20:03:37 +00:00
Resolves merge conflicts: - apps/server/src/routes/terminal/common.ts: Keep randomBytes import, use @automaker/utils for createLogger - apps/ui/eslint.config.mjs: Use main's explicit globals list with XMLHttpRequest and MediaQueryListEvent additions - apps/ui/src/components/views/terminal-view.tsx: Keep our terminal improvements (killAllSessions, beforeunload, better error handling) - apps/ui/src/config/terminal-themes.ts: Keep our search highlight colors for all themes - apps/ui/src/store/app-store.ts: Keep our terminal settings persistence improvements (merge function) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
239 lines
7.1 KiB
TypeScript
239 lines
7.1 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { BaseProvider } from '@/providers/base-provider.js';
|
|
import type {
|
|
ProviderConfig,
|
|
ExecuteOptions,
|
|
ProviderMessage,
|
|
InstallationStatus,
|
|
ModelDefinition,
|
|
} from '@automaker/types';
|
|
|
|
// Concrete implementation for testing the abstract class
|
|
class TestProvider extends BaseProvider {
|
|
getName(): string {
|
|
return 'test-provider';
|
|
}
|
|
|
|
async *executeQuery(_options: ExecuteOptions): AsyncGenerator<ProviderMessage> {
|
|
yield { type: 'text', text: 'test response' };
|
|
}
|
|
|
|
async detectInstallation(): Promise<InstallationStatus> {
|
|
return { installed: true };
|
|
}
|
|
|
|
getAvailableModels(): ModelDefinition[] {
|
|
return [{ id: 'test-model-1', name: 'Test Model 1', description: 'A test model' }];
|
|
}
|
|
}
|
|
|
|
describe('base-provider.ts', () => {
|
|
describe('constructor', () => {
|
|
it('should initialize with empty config when none provided', () => {
|
|
const provider = new TestProvider();
|
|
expect(provider.getConfig()).toEqual({});
|
|
});
|
|
|
|
it('should initialize with provided config', () => {
|
|
const config: ProviderConfig = {
|
|
apiKey: 'test-key',
|
|
baseUrl: 'https://test.com',
|
|
};
|
|
const provider = new TestProvider(config);
|
|
expect(provider.getConfig()).toEqual(config);
|
|
});
|
|
|
|
it('should call getName() during initialization', () => {
|
|
const provider = new TestProvider();
|
|
expect(provider.getName()).toBe('test-provider');
|
|
});
|
|
});
|
|
|
|
describe('validateConfig', () => {
|
|
it('should return valid when config exists', () => {
|
|
const provider = new TestProvider({ apiKey: 'test' });
|
|
const result = provider.validateConfig();
|
|
|
|
expect(result.valid).toBe(true);
|
|
expect(result.errors).toHaveLength(0);
|
|
expect(result.warnings).toHaveLength(0);
|
|
});
|
|
|
|
it('should return invalid when config is undefined', () => {
|
|
// Create provider without config
|
|
const provider = new TestProvider();
|
|
// Manually set config to undefined to test edge case
|
|
(provider as any).config = undefined;
|
|
|
|
const result = provider.validateConfig();
|
|
|
|
expect(result.valid).toBe(false);
|
|
expect(result.errors).toContain('Provider config is missing');
|
|
});
|
|
|
|
it('should return valid for empty config object', () => {
|
|
const provider = new TestProvider({});
|
|
const result = provider.validateConfig();
|
|
|
|
expect(result.valid).toBe(true);
|
|
expect(result.errors).toHaveLength(0);
|
|
});
|
|
|
|
it('should include warnings array in result', () => {
|
|
const provider = new TestProvider();
|
|
const result = provider.validateConfig();
|
|
|
|
expect(result).toHaveProperty('warnings');
|
|
expect(Array.isArray(result.warnings)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('supportsFeature', () => {
|
|
it("should support 'tools' feature", () => {
|
|
const provider = new TestProvider();
|
|
expect(provider.supportsFeature('tools')).toBe(true);
|
|
});
|
|
|
|
it("should support 'text' feature", () => {
|
|
const provider = new TestProvider();
|
|
expect(provider.supportsFeature('text')).toBe(true);
|
|
});
|
|
|
|
it('should not support unknown features', () => {
|
|
const provider = new TestProvider();
|
|
expect(provider.supportsFeature('vision')).toBe(false);
|
|
expect(provider.supportsFeature('mcp')).toBe(false);
|
|
expect(provider.supportsFeature('unknown')).toBe(false);
|
|
});
|
|
|
|
it('should be case-sensitive', () => {
|
|
const provider = new TestProvider();
|
|
expect(provider.supportsFeature('TOOLS')).toBe(false);
|
|
expect(provider.supportsFeature('Text')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('getConfig', () => {
|
|
it('should return current config', () => {
|
|
const config: ProviderConfig = {
|
|
apiKey: 'test-key',
|
|
model: 'test-model',
|
|
};
|
|
const provider = new TestProvider(config);
|
|
|
|
expect(provider.getConfig()).toEqual(config);
|
|
});
|
|
|
|
it('should return same reference', () => {
|
|
const config: ProviderConfig = { apiKey: 'test' };
|
|
const provider = new TestProvider(config);
|
|
|
|
const retrieved1 = provider.getConfig();
|
|
const retrieved2 = provider.getConfig();
|
|
|
|
expect(retrieved1).toBe(retrieved2);
|
|
});
|
|
});
|
|
|
|
describe('setConfig', () => {
|
|
it('should merge partial config with existing config', () => {
|
|
const provider = new TestProvider({ apiKey: 'original-key' });
|
|
|
|
provider.setConfig({ model: 'new-model' });
|
|
|
|
expect(provider.getConfig()).toEqual({
|
|
apiKey: 'original-key',
|
|
model: 'new-model',
|
|
});
|
|
});
|
|
|
|
it('should override existing fields', () => {
|
|
const provider = new TestProvider({ apiKey: 'old-key', model: 'old-model' });
|
|
|
|
provider.setConfig({ apiKey: 'new-key' });
|
|
|
|
expect(provider.getConfig()).toEqual({
|
|
apiKey: 'new-key',
|
|
model: 'old-model',
|
|
});
|
|
});
|
|
|
|
it('should accept empty object', () => {
|
|
const provider = new TestProvider({ apiKey: 'test' });
|
|
const originalConfig = provider.getConfig();
|
|
|
|
provider.setConfig({});
|
|
|
|
expect(provider.getConfig()).toEqual(originalConfig);
|
|
});
|
|
|
|
it('should handle multiple updates', () => {
|
|
const provider = new TestProvider();
|
|
|
|
provider.setConfig({ apiKey: 'key1' });
|
|
provider.setConfig({ model: 'model1' });
|
|
provider.setConfig({ baseUrl: 'https://test.com' });
|
|
|
|
expect(provider.getConfig()).toEqual({
|
|
apiKey: 'key1',
|
|
model: 'model1',
|
|
baseUrl: 'https://test.com',
|
|
});
|
|
});
|
|
|
|
it('should preserve other fields when updating one field', () => {
|
|
const provider = new TestProvider({
|
|
apiKey: 'key',
|
|
model: 'model',
|
|
baseUrl: 'https://test.com',
|
|
});
|
|
|
|
provider.setConfig({ model: 'new-model' });
|
|
|
|
expect(provider.getConfig()).toEqual({
|
|
apiKey: 'key',
|
|
model: 'new-model',
|
|
baseUrl: 'https://test.com',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('abstract methods', () => {
|
|
it('should require getName implementation', () => {
|
|
const provider = new TestProvider();
|
|
expect(typeof provider.getName).toBe('function');
|
|
expect(provider.getName()).toBe('test-provider');
|
|
});
|
|
|
|
it('should require executeQuery implementation', async () => {
|
|
const provider = new TestProvider();
|
|
expect(typeof provider.executeQuery).toBe('function');
|
|
|
|
const generator = provider.executeQuery({
|
|
prompt: 'test',
|
|
projectDirectory: '/test',
|
|
});
|
|
const result = await generator.next();
|
|
|
|
expect(result.value).toEqual({ type: 'text', text: 'test response' });
|
|
});
|
|
|
|
it('should require detectInstallation implementation', async () => {
|
|
const provider = new TestProvider();
|
|
expect(typeof provider.detectInstallation).toBe('function');
|
|
|
|
const status = await provider.detectInstallation();
|
|
expect(status).toHaveProperty('installed');
|
|
});
|
|
|
|
it('should require getAvailableModels implementation', () => {
|
|
const provider = new TestProvider();
|
|
expect(typeof provider.getAvailableModels).toBe('function');
|
|
|
|
const models = provider.getAvailableModels();
|
|
expect(Array.isArray(models)).toBe(true);
|
|
expect(models.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
});
|