feat: cover Enhancemet service by tests

This commit is contained in:
Oleg Proskurin 2025-10-09 23:37:17 +07:00
parent ff565238da
commit 2a4ba8f4ed
4 changed files with 362 additions and 0 deletions

View File

@ -0,0 +1,164 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { PromptEnhancementService } from '../PromptEnhancementService';
import type { AgentResult } from '../types';
// Mock the agents module
vi.mock('../agents', () => ({
getAgent: vi.fn(() => ({
templateType: 'general',
enhance: vi.fn(),
})),
}));
describe('PromptEnhancementService', () => {
let service: PromptEnhancementService;
const mockApiKey = 'test-gemini-api-key';
beforeEach(() => {
vi.clearAllMocks();
service = new PromptEnhancementService(mockApiKey);
});
describe('constructor', () => {
it('should throw error when API key is missing', () => {
expect(() => new PromptEnhancementService('')).toThrow('Gemini API key is required');
});
it('should create instance with valid API key', () => {
expect(service).toBeInstanceOf(PromptEnhancementService);
});
});
describe('enhancePrompt', () => {
it('should reject empty prompts', async () => {
const result = await service.enhancePrompt('');
expect(result.success).toBe(false);
expect(result.error).toBe('Prompt cannot be empty');
});
it('should reject prompts exceeding 5000 characters', async () => {
const longPrompt = 'a'.repeat(5001);
const result = await service.enhancePrompt(longPrompt);
expect(result.success).toBe(false);
expect(result.error).toContain('exceeds maximum length');
});
it('should successfully enhance valid prompt', async () => {
const { getAgent } = await import('../agents');
const mockAgent = {
templateType: 'general',
enhance: vi.fn().mockResolvedValue({
success: true,
enhancedPrompt: 'A beautiful sunset over the ocean with vibrant colors',
appliedTemplate: 'general',
enhancements: ['Added detailed descriptions'],
} as AgentResult),
};
vi.mocked(getAgent).mockReturnValue(mockAgent);
const result = await service.enhancePrompt('sunset');
expect(result.success).toBe(true);
expect(result.enhancedPrompt).toBe('A beautiful sunset over the ocean with vibrant colors');
expect(result.appliedTemplate).toBe('general');
});
it('should handle agent enhancement failure', async () => {
const { getAgent } = await import('../agents');
const mockAgent = {
templateType: 'general',
enhance: vi.fn().mockResolvedValue({
success: false,
error: 'Enhancement failed',
enhancements: [],
} as AgentResult),
};
vi.mocked(getAgent).mockReturnValue(mockAgent);
const result = await service.enhancePrompt('sunset');
expect(result.success).toBe(false);
expect(result.error).toBe('Enhancement failed');
});
it('should truncate enhanced prompt exceeding 2000 characters', async () => {
const { getAgent } = await import('../agents');
const longEnhancedPrompt = 'enhanced '.repeat(300); // > 2000 chars
const mockAgent = {
templateType: 'general',
enhance: vi.fn().mockResolvedValue({
success: true,
enhancedPrompt: longEnhancedPrompt,
appliedTemplate: 'general',
enhancements: [],
} as AgentResult),
};
vi.mocked(getAgent).mockReturnValue(mockAgent);
const result = await service.enhancePrompt('sunset');
expect(result.success).toBe(true);
expect(result.enhancedPrompt?.length).toBe(2000);
});
it('should pass options to agent', async () => {
const { getAgent } = await import('../agents');
const mockEnhance = vi.fn().mockResolvedValue({
success: true,
enhancedPrompt: 'Enhanced',
appliedTemplate: 'photorealistic',
enhancements: [],
} as AgentResult);
const mockAgent = {
templateType: 'photorealistic',
enhance: mockEnhance,
};
vi.mocked(getAgent).mockReturnValue(mockAgent);
await service.enhancePrompt('sunset', {
template: 'photorealistic',
tags: ['landscape', 'nature'],
});
expect(mockEnhance).toHaveBeenCalledWith('sunset', {
template: 'photorealistic',
tags: ['landscape', 'nature'],
});
});
it('should include detected language in result', async () => {
const { getAgent } = await import('../agents');
const mockAgent = {
templateType: 'general',
enhance: vi.fn().mockResolvedValue({
success: true,
enhancedPrompt: 'Enhanced prompt',
detectedLanguage: 'Spanish',
appliedTemplate: 'general',
enhancements: [],
} as AgentResult),
};
vi.mocked(getAgent).mockReturnValue(mockAgent);
const result = await service.enhancePrompt('hermosa puesta de sol');
expect(result.success).toBe(true);
expect(result.detectedLanguage).toBe('Spanish');
});
it('should handle exceptions gracefully', async () => {
const { getAgent } = await import('../agents');
const mockAgent = {
templateType: 'general',
enhance: vi.fn().mockRejectedValue(new Error('Network error')),
};
vi.mocked(getAgent).mockReturnValue(mockAgent);
const result = await service.enhancePrompt('sunset');
expect(result.success).toBe(false);
expect(result.error).toBe('Network error');
});
it('should return original prompt in all results', async () => {
const originalPrompt = 'test prompt';
const result = await service.enhancePrompt(originalPrompt);
expect(result.originalPrompt).toBe(originalPrompt);
});
});
});

View File

@ -0,0 +1,65 @@
import { describe, it, expect } from 'vitest';
import { getAgent } from '../agents';
import {
GeneralAgent,
PhotorealisticAgent,
IllustrationAgent,
MinimalistAgent,
StickerAgent,
ProductAgent,
ComicAgent,
} from '../agents';
describe('getAgent', () => {
const mockApiKey = 'test-api-key';
it('should return GeneralAgent when no template provided', () => {
const agent = getAgent(mockApiKey);
expect(agent).toBeInstanceOf(GeneralAgent);
});
it('should return PhotorealisticAgent for photorealistic template', () => {
const agent = getAgent(mockApiKey, 'photorealistic');
expect(agent).toBeInstanceOf(PhotorealisticAgent);
});
it('should return IllustrationAgent for illustration template', () => {
const agent = getAgent(mockApiKey, 'illustration');
expect(agent).toBeInstanceOf(IllustrationAgent);
});
it('should return MinimalistAgent for minimalist template', () => {
const agent = getAgent(mockApiKey, 'minimalist');
expect(agent).toBeInstanceOf(MinimalistAgent);
});
it('should return StickerAgent for sticker template', () => {
const agent = getAgent(mockApiKey, 'sticker');
expect(agent).toBeInstanceOf(StickerAgent);
});
it('should return ProductAgent for product template', () => {
const agent = getAgent(mockApiKey, 'product');
expect(agent).toBeInstanceOf(ProductAgent);
});
it('should return ComicAgent for comic template', () => {
const agent = getAgent(mockApiKey, 'comic');
expect(agent).toBeInstanceOf(ComicAgent);
});
it('should return GeneralAgent for general template', () => {
const agent = getAgent(mockApiKey, 'general');
expect(agent).toBeInstanceOf(GeneralAgent);
});
it('should fallback to GeneralAgent for unknown template', () => {
const agent = getAgent(mockApiKey, 'unknown-template' as any);
expect(agent).toBeInstanceOf(GeneralAgent);
});
it('should return agent with correct templateType', () => {
const agent = getAgent(mockApiKey, 'photorealistic');
expect(agent.templateType).toBe('photorealistic');
});
});

View File

@ -0,0 +1,90 @@
import { describe, it, expect } from 'vitest';
import { detectLanguage, detectEnhancements } from '../utils';
describe('detectLanguage', () => {
it('should detect English', () => {
expect(detectLanguage('a sunset over the ocean')).toBe('English');
});
it('should detect Chinese', () => {
expect(detectLanguage('美丽的日落')).toBe('Chinese');
});
it('should detect Japanese', () => {
expect(detectLanguage('こんにちは')).toBe('Japanese');
});
it('should detect Korean', () => {
expect(detectLanguage('아름다운 일몰')).toBe('Korean');
});
it('should detect Romance Language', () => {
expect(detectLanguage('hermosa puesta de sól')).toBe('Romance Language');
expect(detectLanguage('beau coucher de soléil')).toBe('Romance Language');
});
it('should detect Russian', () => {
expect(detectLanguage('красивый закат')).toBe('Russian');
});
it('should detect Greek', () => {
expect(detectLanguage('όμορφο ηλιοβασίλεμα')).toBe('Greek');
});
it('should detect Arabic', () => {
expect(detectLanguage('غروب جميل')).toBe('Arabic');
});
it('should detect Hebrew', () => {
expect(detectLanguage('שקיעה יפה')).toBe('Hebrew');
});
it('should default to English for unknown scripts', () => {
expect(detectLanguage('123')).toBe('English');
});
});
describe('detectEnhancements', () => {
it('should detect added detailed descriptions', () => {
const original = 'sunset';
const enhanced = 'A breathtaking sunset over the ocean with vibrant orange and pink hues';
const enhancements = detectEnhancements(original, enhanced);
expect(enhancements).toContain('Added detailed descriptions');
});
it('should detect photography terminology', () => {
const original = 'sunset';
const enhanced = 'A photorealistic sunset shot with 50mm lens';
const enhancements = detectEnhancements(original, enhanced);
expect(enhancements).toContain('Applied photography terminology');
});
it('should detect lighting descriptions', () => {
const original = 'room';
const enhanced = 'A room with soft lighting and warm illuminated corners';
const enhancements = detectEnhancements(original, enhanced);
expect(enhancements).toContain('Enhanced lighting description');
});
it('should detect texture details', () => {
const original = 'wall';
const enhanced = 'A wall with rough texture and weathered surface';
const enhancements = detectEnhancements(original, enhanced);
expect(enhancements).toContain('Added texture details');
});
it('should detect multiple enhancements', () => {
const original = 'sunset';
const enhanced =
'A photorealistic sunset with dramatic lighting, beautiful texture in the clouds, and soft illuminated sky';
const enhancements = detectEnhancements(original, enhanced);
expect(enhancements.length).toBeGreaterThan(1);
});
it('should return empty array when no enhancements detected', () => {
const original = 'sunset';
const enhanced = 'sunset';
const enhancements = detectEnhancements(original, enhanced);
expect(enhancements).toEqual([]);
});
});

View File

@ -0,0 +1,43 @@
import { describe, it, expect } from 'vitest';
import { validatePromptLength } from '../validators';
describe('validatePromptLength', () => {
it('should reject empty prompts', () => {
const result = validatePromptLength('');
expect(result.valid).toBe(false);
expect(result.error).toBe('Prompt cannot be empty');
});
it('should reject whitespace-only prompts', () => {
const result = validatePromptLength(' ');
expect(result.valid).toBe(false);
expect(result.error).toBe('Prompt cannot be empty');
});
it('should accept valid prompt within max length', () => {
const result = validatePromptLength('a sunset over the ocean', 2000);
expect(result.valid).toBe(true);
expect(result.error).toBeUndefined();
});
it('should reject prompts exceeding max length', () => {
const longPrompt = 'a'.repeat(2001);
const result = validatePromptLength(longPrompt, 2000);
expect(result.valid).toBe(false);
expect(result.error).toContain('exceeds maximum length');
expect(result.error).toContain('2000');
});
it('should use custom max length', () => {
const prompt = 'a'.repeat(150);
const result = validatePromptLength(prompt, 100);
expect(result.valid).toBe(false);
expect(result.error).toContain('100');
});
it('should accept prompt at exact max length', () => {
const prompt = 'a'.repeat(100);
const result = validatePromptLength(prompt, 100);
expect(result.valid).toBe(true);
});
});