UNPKG

claude-flow-multilang

Version:

Revolutionary multilingual AI orchestration framework with cultural awareness and DDD architecture

376 lines (298 loc) 11.5 kB
import { getErrorMessage } from '../utils/error-handler.js'; import * as fs from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; import { PromptCopier, copyPrompts } from '../prompt-copier.js'; import { EnhancedPromptCopier, copyPromptsEnhanced } from '../prompt-copier-enhanced.js'; import { PromptConfigManager, PromptValidator } from '../prompt-utils.js'; describe('PromptCopier', () => { let tempDir: string; let sourceDir: string; let destDir: string; beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'prompt-test-')); sourceDir = path.join(tempDir, 'source'); destDir = path.join(tempDir, 'dest'); await fs.mkdir(sourceDir, { recursive: true }); await fs.mkdir(destDir, { recursive: true }); // Create test files await createTestFiles(); }); afterEach(async () => { await fs.rm(tempDir, { recursive: true, force: true }); }); async function createTestFiles() { const testFiles = [ { path: 'test1.md', content: '# Test Prompt 1\nThis is a test prompt.' }, { path: 'test2.txt', content: 'Test prompt content' }, { path: 'subdir/test3.md', content: '## Nested Prompt\nNested content' }, { path: 'large.md', content: 'Large content\n'.repeat(1000) }, { path: 'empty.md', content: '' }, { path: 'rules.md', content: '# Rules\nYou are an AI assistant.' }, ]; for (const file of testFiles) { const filePath = path.join(sourceDir, file.path); const dir = path.dirname(filePath); await fs.mkdir(dir, { recursive: true }); await fs.writeFile(filePath, file.content); } } describe('Basic copying functionality', () => { test('should copy all matching files', async () => { const result = await copyPrompts({ source: sourceDir, destination: destDir, }); expect(result.success).toBe(true); expect(result.copiedFiles).toBe(6); expect(result.failedFiles).toBe(0); // Verify files exist const destFiles = await fs.readdir(destDir, { recursive: true }); expect(destFiles).toHaveLength(6); }); test('should respect include patterns', async () => { const result = await copyPrompts({ source: sourceDir, destination: destDir, includePatterns: ['*.md'], }); expect(result.success).toBe(true); expect(result.copiedFiles).toBe(5); // Only .md files }); test('should respect exclude patterns', async () => { const result = await copyPrompts({ source: sourceDir, destination: destDir, excludePatterns: ['**/subdir/**'], }); expect(result.success).toBe(true); expect(result.copiedFiles).toBe(5); // Excluding subdir files }); }); describe('Conflict resolution', () => { test('should skip existing files when conflict resolution is skip', async () => { // Create existing file await fs.writeFile(path.join(destDir, 'test1.md'), 'Existing content'); const result = await copyPrompts({ source: sourceDir, destination: destDir, conflictResolution: 'skip', }); expect(result.success).toBe(true); expect(result.skippedFiles).toBeGreaterThan(0); // Verify original content preserved const content = await fs.readFile(path.join(destDir, 'test1.md'), 'utf-8'); expect(content).toBe('Existing content'); }); test('should backup existing files when conflict resolution is backup', async () => { // Create existing file await fs.writeFile(path.join(destDir, 'test1.md'), 'Existing content'); const result = await copyPrompts({ source: sourceDir, destination: destDir, conflictResolution: 'backup', }); expect(result.success).toBe(true); expect(result.backupLocation).toBeDefined(); // Verify backup directory exists const backupDir = path.join(destDir, '.prompt-backups'); const backupExists = await fs .access(backupDir) .then(() => true) .catch(() => false); expect(backupExists).toBe(true); }); test('should merge files when conflict resolution is merge', async () => { // Create existing file await fs.writeFile(path.join(destDir, 'test1.md'), 'Existing content'); const result = await copyPrompts({ source: sourceDir, destination: destDir, conflictResolution: 'merge', }); expect(result.success).toBe(true); // Verify merged content const content = await fs.readFile(path.join(destDir, 'test1.md'), 'utf-8'); expect(content).toContain('Existing content'); expect(content).toContain('MERGED CONTENT'); expect(content).toContain('# Test Prompt 1'); }); }); describe('Verification', () => { test('should verify copied files when verification is enabled', async () => { const result = await copyPrompts({ source: sourceDir, destination: destDir, verify: true, }); expect(result.success).toBe(true); expect(result.failedFiles).toBe(0); }); test('should detect verification failures', async () => { // Mock fs.stat to simulate size mismatch const originalStat = fs.stat; jest.spyOn(fs, 'stat').mockImplementation(async (filePath: any) => { const stats = await originalStat(filePath); if (filePath.includes('dest') && filePath.includes('test1.md')) { return { ...stats, size: stats.size + 1 }; } return stats; }); const result = await copyPrompts({ source: sourceDir, destination: destDir, verify: true, }); expect(result.errors.length).toBeGreaterThan(0); expect(result.errors[0].phase).toBe('verify'); (fs.stat as jest.Mock).mockRestore(); }); }); describe('Dry run mode', () => { test('should not create files in dry run mode', async () => { const result = await copyPrompts({ source: sourceDir, destination: destDir, dryRun: true, }); expect(result.success).toBe(true); expect(result.totalFiles).toBe(6); // Verify no files were actually copied const destFiles = await fs.readdir(destDir); expect(destFiles).toHaveLength(0); }); }); describe('Progress reporting', () => { test('should report progress during copy', async () => { const progressUpdates: any[] = []; await copyPrompts({ source: sourceDir, destination: destDir, progressCallback: (progress) => { progressUpdates.push(progress); }, }); expect(progressUpdates.length).toBeGreaterThan(0); expect(progressUpdates[progressUpdates.length - 1].percentage).toBe(100); }); }); }); describe('EnhancedPromptCopier', () => { let tempDir: string; let sourceDir: string; let destDir: string; beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'enhanced-test-')); sourceDir = path.join(tempDir, 'source'); destDir = path.join(tempDir, 'dest'); await fs.mkdir(sourceDir, { recursive: true }); await fs.mkdir(destDir, { recursive: true }); // Create test files for (let i = 0; i < 20; i++) { await fs.writeFile(path.join(sourceDir, `test${i}.md`), `# Test ${i}\nContent for test ${i}`); } }); afterEach(async () => { await fs.rm(tempDir, { recursive: true, force: true }); }); test('should copy files using worker threads', async () => { const result = await copyPromptsEnhanced({ source: sourceDir, destination: destDir, parallel: true, maxWorkers: 4, }); expect(result.success).toBe(true); expect(result.copiedFiles).toBe(20); expect(result.failedFiles).toBe(0); // Verify all files were copied const destFiles = await fs.readdir(destDir); expect(destFiles).toHaveLength(20); }, 10000); }); describe('PromptConfigManager', () => { let tempDir: string; let configPath: string; beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'config-test-')); configPath = path.join(tempDir, '.prompt-config.json'); }); afterEach(async () => { await fs.rm(tempDir, { recursive: true, force: true }); }); test('should load default config when file does not exist', async () => { const manager = new PromptConfigManager(configPath); const config = await manager.loadConfig(); expect(config).toBeDefined(); expect(config.defaultOptions).toBeDefined(); expect(config.profiles).toBeDefined(); }); test('should save and load custom config', async () => { const manager = new PromptConfigManager(configPath); await manager.saveConfig({ destinationDirectory: './custom-prompts', }); const config = await manager.loadConfig(); expect(config.destinationDirectory).toBe('./custom-prompts'); }); test('should get profile options', async () => { const manager = new PromptConfigManager(configPath); await manager.loadConfig(); const sparcProfile = manager.getProfile('sparc'); expect(sparcProfile).toBeDefined(); expect(sparcProfile.includePatterns).toContain('*.md'); }); test('should list available profiles', async () => { const manager = new PromptConfigManager(configPath); await manager.loadConfig(); const profiles = manager.listProfiles(); expect(profiles).toContain('sparc'); expect(profiles).toContain('templates'); expect(profiles).toContain('safe'); expect(profiles).toContain('fast'); }); }); describe('PromptValidator', () => { let tempDir: string; beforeEach(async () => { tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'validator-test-')); }); afterEach(async () => { await fs.rm(tempDir, { recursive: true, force: true }); }); test('should validate valid prompt file', async () => { const filePath = path.join(tempDir, 'valid.md'); await fs.writeFile(filePath, '# Test Prompt\nYou are an AI assistant.'); const result = await PromptValidator.validatePromptFile(filePath); expect(result.valid).toBe(true); expect(result.issues).toHaveLength(0); }); test('should detect empty files', async () => { const filePath = path.join(tempDir, 'empty.md'); await fs.writeFile(filePath, ''); const result = await PromptValidator.validatePromptFile(filePath); expect(result.valid).toBe(false); expect(result.issues).toContain('File is empty'); }); test('should extract front matter metadata', async () => { const filePath = path.join(tempDir, 'with-metadata.md'); const content = `--- title: Test Prompt version: 1.0 --- # Test Prompt Content here`; await fs.writeFile(filePath, content); const result = await PromptValidator.validatePromptFile(filePath); expect(result.metadata).toBeDefined(); expect(result.metadata.title).toBe('Test Prompt'); expect(result.metadata.version).toBe('1.0'); }); test('should warn about large files', async () => { const filePath = path.join(tempDir, 'large.md'); const largeContent = '# Large Prompt\n' + 'x'.repeat(200 * 1024); // 200KB await fs.writeFile(filePath, largeContent); const result = await PromptValidator.validatePromptFile(filePath); expect(result.issues).toContain('File is unusually large for a prompt'); }); });