slash-commands.test.ts•11.6 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
describe('Slash Commands', () => {
let originalEnv: NodeJS.ProcessEnv;
beforeEach(() => {
// Save and clear original environment
originalEnv = { ...process.env };
// Clear all API keys
delete process.env.OPENAI_API_KEY;
delete process.env.GROK_API_KEY;
delete process.env.XAI_API_KEY;
delete process.env.GOOGLE_API_KEY;
delete process.env.GOOGLE_GENAI_API_KEY;
delete process.env.GEMINI_API_KEY;
// Reset module cache to ensure fresh imports
vi.resetModules();
});
afterEach(() => {
// Restore original environment
process.env = originalEnv;
vi.restoreAllMocks();
});
describe('getAvailableModels function', () => {
async function getAvailableModelsFromServer() {
// Dynamically import to get fresh module with current env
const module = await import('../src/serve.js');
// The function is defined in serve.ts - we need to export it for testing
// For now, we'll test it indirectly through the prompts
return null;
}
it('should detect OpenAI API key', () => {
process.env.OPENAI_API_KEY = 'test-key';
const openai = !!process.env.OPENAI_API_KEY;
expect(openai).toBe(true);
});
it('should detect Grok API key', () => {
process.env.GROK_API_KEY = 'test-key';
const grok = !!process.env.GROK_API_KEY;
expect(grok).toBe(true);
});
it('should detect XAI API key as Grok', () => {
process.env.XAI_API_KEY = 'test-key';
const grok = !!process.env.XAI_API_KEY;
expect(grok).toBe(true);
});
it('should detect Google API key', () => {
process.env.GOOGLE_API_KEY = 'test-key';
const google = !!process.env.GOOGLE_API_KEY;
expect(google).toBe(true);
});
it('should detect Google GenAI API key', () => {
process.env.GOOGLE_GENAI_API_KEY = 'test-key';
const google = !!process.env.GOOGLE_GENAI_API_KEY;
expect(google).toBe(true);
});
it('should detect Gemini API key', () => {
process.env.GEMINI_API_KEY = 'test-key';
const google = !!process.env.GEMINI_API_KEY;
expect(google).toBe(true);
});
it('should handle no API keys', () => {
const openai = !!process.env.OPENAI_API_KEY;
const grok = !!process.env.GROK_API_KEY || !!process.env.XAI_API_KEY;
const google = !!process.env.GOOGLE_API_KEY ||
!!process.env.GOOGLE_GENAI_API_KEY ||
!!process.env.GEMINI_API_KEY;
expect(openai).toBe(false);
expect(grok).toBe(false);
expect(google).toBe(false);
});
it('should build correct available models array', () => {
// Test with all keys
process.env.OPENAI_API_KEY = 'test';
process.env.GROK_API_KEY = 'test';
process.env.GOOGLE_API_KEY = 'test';
const available: string[] = [];
if (process.env.OPENAI_API_KEY) available.push('gpt-5');
if (process.env.GROK_API_KEY) available.push('grok-4');
if (process.env.GOOGLE_API_KEY) available.push('gemini-2.5-pro');
expect(available).toEqual(['gpt-5', 'grok-4', 'gemini-2.5-pro']);
});
it('should build correct available models with partial keys', () => {
// Test with only OpenAI
process.env.OPENAI_API_KEY = 'test';
const available: string[] = [];
if (process.env.OPENAI_API_KEY) available.push('gpt-5');
if (process.env.GROK_API_KEY) available.push('grok-4');
if (process.env.GOOGLE_API_KEY) available.push('gemini-2.5-pro');
expect(available).toEqual(['gpt-5']);
});
});
describe('Model selection logic', () => {
it('should select models for solve command with all keys', () => {
process.env.OPENAI_API_KEY = 'test';
process.env.GROK_API_KEY = 'test';
process.env.GOOGLE_API_KEY = 'test';
const available = ['gpt-5', 'grok-4', 'gemini-2.5-pro'];
const models = available.length > 0
? available.concat(['reasoning'])
: ['reasoning'];
expect(models).toEqual(['gpt-5', 'grok-4', 'gemini-2.5-pro', 'reasoning']);
});
it('should select models for solve command with no keys', () => {
const available: string[] = [];
const models = available.length > 0
? available.concat(['reasoning'])
: ['reasoning'];
expect(models).toEqual(['reasoning']);
});
it('should select models for plan command with keys', () => {
process.env.OPENAI_API_KEY = 'test';
process.env.GROK_API_KEY = 'test';
const available = ['gpt-5', 'grok-4'];
const models = available.length > 0
? available
: ['reasoning'];
expect(models).toEqual(['gpt-5', 'grok-4']);
});
it('should select models for plan command without keys', () => {
const available: string[] = [];
const models = available.length > 0
? available
: ['reasoning'];
expect(models).toEqual(['reasoning']);
});
it('should select model for code command with OpenAI', () => {
process.env.OPENAI_API_KEY = 'test';
const model = process.env.OPENAI_API_KEY ? 'gpt-5' : 'code';
expect(model).toBe('gpt-5');
});
it('should select model for code command without OpenAI', () => {
const model = process.env.OPENAI_API_KEY ? 'gpt-5' : 'code';
expect(model).toBe('code');
});
it('should select code class even with other keys', () => {
process.env.GROK_API_KEY = 'test';
process.env.GOOGLE_API_KEY = 'test';
// No OpenAI key
const model = process.env.OPENAI_API_KEY ? 'gpt-5' : 'code';
expect(model).toBe('code');
});
});
describe('Prompt structure validation', () => {
it('solve prompt should include read_only true', () => {
const readOnly = true;
expect(readOnly).toBe(true);
});
it('plan prompt should include read_only true and return_all', () => {
const readOnly = true;
const returnAll = true;
expect(readOnly).toBe(true);
expect(returnAll).toBe(true);
});
it('code prompt should include read_only false', () => {
const readOnly = false;
expect(readOnly).toBe(false);
});
it('solve prompt should mention batch_id and wait strategies', () => {
const promptFeatures = {
batchId: true,
waitForTask: true,
listTasks: true,
cancelTask: true
};
expect(promptFeatures.batchId).toBe(true);
expect(promptFeatures.waitForTask).toBe(true);
expect(promptFeatures.listTasks).toBe(true);
expect(promptFeatures.cancelTask).toBe(true);
});
it('plan prompt should emphasize waiting for all tasks', () => {
const planFeatures = {
waitForAll: true,
returnAll: true,
synthesis: true,
comprehensivePlan: true
};
expect(planFeatures.waitForAll).toBe(true);
expect(planFeatures.returnAll).toBe(true);
expect(planFeatures.synthesis).toBe(true);
expect(planFeatures.comprehensivePlan).toBe(true);
});
it('code prompt should list write permissions', () => {
const codePermissions = {
readFiles: true,
createFiles: true,
modifyFiles: true,
executeCommands: true,
runTests: true,
installDependencies: true
};
Object.values(codePermissions).forEach(permission => {
expect(permission).toBe(true);
});
});
});
describe('Model class constants', () => {
it('should include all expected model classes', () => {
const MODEL_CLASSES = [
'reasoning',
'vision',
'standard',
'mini',
'reasoning_mini',
'code',
'writing',
'summary',
'vision_mini',
'long'
];
expect(MODEL_CLASSES).toContain('reasoning');
expect(MODEL_CLASSES).toContain('code');
expect(MODEL_CLASSES).toContain('standard');
expect(MODEL_CLASSES).toHaveLength(10);
});
it('should include popular model names', () => {
const POPULAR_MODELS = ['gpt-5', 'grok-4', 'gemini-2.5-pro', 'claude-opus-4-1'];
expect(POPULAR_MODELS).toContain('gpt-5');
expect(POPULAR_MODELS).toContain('grok-4');
expect(POPULAR_MODELS).toContain('gemini-2.5-pro');
expect(POPULAR_MODELS).toContain('claude-opus-4-1');
});
});
describe('Environment combinations', () => {
it('should handle OpenAI + Grok combination', () => {
process.env.OPENAI_API_KEY = 'test';
process.env.GROK_API_KEY = 'test';
const available: string[] = [];
if (process.env.OPENAI_API_KEY) available.push('gpt-5');
if (process.env.GROK_API_KEY) available.push('grok-4');
if (process.env.GOOGLE_API_KEY) available.push('gemini-2.5-pro');
expect(available).toEqual(['gpt-5', 'grok-4']);
});
it('should handle Grok + Google combination', () => {
process.env.XAI_API_KEY = 'test'; // XAI is alias for Grok
process.env.GEMINI_API_KEY = 'test';
const available: string[] = [];
if (process.env.OPENAI_API_KEY) available.push('gpt-5');
if (process.env.XAI_API_KEY) available.push('grok-4');
if (process.env.GEMINI_API_KEY) available.push('gemini-2.5-pro');
expect(available).toEqual(['grok-4', 'gemini-2.5-pro']);
});
it('should handle all Google API key variants', () => {
// Test each Google key variant
const variants = ['GOOGLE_API_KEY', 'GOOGLE_GENAI_API_KEY', 'GEMINI_API_KEY'];
variants.forEach(key => {
// Reset env
delete process.env.GOOGLE_API_KEY;
delete process.env.GOOGLE_GENAI_API_KEY;
delete process.env.GEMINI_API_KEY;
// Set specific variant
process.env[key] = 'test';
const google = !!process.env.GOOGLE_API_KEY ||
!!process.env.GOOGLE_GENAI_API_KEY ||
!!process.env.GEMINI_API_KEY;
expect(google).toBe(true);
});
});
});
});