Skip to main content
Glama
GenreValidation.test.ts10.3 kB
import { PatternGenerator } from '../../services/PatternGenerator'; import { MusicTheory } from '../../services/MusicTheory'; import { PatternValidator } from '../../utils/PatternValidator'; describe('Genre Validation Suite', () => { let generator: PatternGenerator; let theory: MusicTheory; let validator: PatternValidator; beforeEach(() => { theory = new MusicTheory(); generator = new PatternGenerator(theory); validator = new PatternValidator(); }); describe('Techno Generation', () => { it('should generate valid techno pattern with correct BPM range', () => { const pattern = generator.generateCompletePattern('techno', 'A', 135); expect(pattern).toBeTruthy(); expect(pattern.length).toBeGreaterThan(0); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate hard techno with characteristic elements', () => { const pattern = generator.generateCompletePattern('techno', 'A', 138); // Should contain drum elements expect(pattern).toMatch(/bd|kick/i); // Should have repetitive structure expect(pattern).toMatch(/\*/); }); it('should generate minimal techno at lower BPM', () => { const pattern = generator.generateCompletePattern('techno', 'E', 125); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); describe('House Generation', () => { it('should generate valid house pattern with 4/4 groove', () => { const pattern = generator.generateCompletePattern('house', 'D', 125); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate deep house with soulful elements', () => { const pattern = generator.generateCompletePattern('house', 'D', 122); // Should contain characteristic house drums expect(pattern).toMatch(/bd|cp|hh/i); }); it('should generate tech house at correct BPM', () => { const pattern = generator.generateCompletePattern('house', 'A', 128); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); describe('Drum & Bass Generation', () => { it('should generate valid DnB pattern with fast tempo', () => { const pattern = generator.generateCompletePattern('dnb', 'E', 174); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate liquid DnB with atmospheric elements', () => { const pattern = generator.generateCompletePattern('dnb', 'C', 172); // Should have fast drum patterns expect(pattern).toMatch(/bd|sn/i); }); it('should generate neurofunk at high BPM', () => { const pattern = generator.generateCompletePattern('dnb', 'F#', 178); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); describe('Ambient Generation', () => { it('should generate valid ambient pattern with slow tempo', () => { const pattern = generator.generateCompletePattern('ambient', 'C', 70); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate dark ambient with sparse elements', () => { const pattern = generator.generateCompletePattern('ambient', 'C', 65); // Ambient patterns should exist and be valid expect(pattern.length).toBeGreaterThan(0); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate drone with minimal rhythm', () => { const pattern = generator.generateCompletePattern('ambient', 'G', 60); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); describe('Trap Generation', () => { it('should generate valid trap pattern with half-time feel', () => { const pattern = generator.generateCompletePattern('trap', 'F#', 140); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate modern trap with 808 elements', () => { const pattern = generator.generateCompletePattern('trap', 'F#', 142); // Should contain drum patterns expect(pattern).toMatch(/bd|hh/i); }); it('should generate cloud trap at lower BPM', () => { const pattern = generator.generateCompletePattern('trap', 'B', 135); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); describe('Jungle Generation', () => { it('should generate valid jungle pattern with complex breaks', () => { const pattern = generator.generateCompletePattern('jungle', 'G', 165); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate classic jungle with characteristic elements', () => { const pattern = generator.generateCompletePattern('jungle', 'G', 168); // Should have fast, complex patterns expect(pattern).toMatch(/bd|sn/i); }); it('should generate ragga jungle', () => { const pattern = generator.generateCompletePattern('jungle', 'D', 170); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); describe('Jazz Generation', () => { it('should generate valid jazz pattern with swing feel', () => { const pattern = generator.generateCompletePattern('jazz', 'A#', 120); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate bebop at fast tempo', () => { const pattern = generator.generateCompletePattern('jazz', 'A#', 180); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it('should generate modal jazz', () => { const pattern = generator.generateCompletePattern('jazz', 'D', 120); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); describe('Cross-Genre Validation', () => { const genres = ['techno', 'house', 'dnb', 'ambient', 'trap', 'jungle', 'jazz']; const keys = ['C', 'D', 'E', 'F', 'G', 'A', 'A#']; genres.forEach(genre => { it(`should generate valid ${genre} patterns across different keys`, () => { keys.forEach(key => { const bpm = genre === 'dnb' || genre === 'jungle' ? 170 : genre === 'ambient' ? 70 : 130; const pattern = generator.generateCompletePattern(genre, key, bpm); expect(pattern).toBeTruthy(); expect(pattern.length).toBeGreaterThan(0); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); }); it('should generate distinct patterns for each genre', () => { const patterns = genres.map(genre => { const bpm = genre === 'dnb' || genre === 'jungle' ? 170 : genre === 'ambient' ? 70 : 130; return generator.generateCompletePattern(genre, 'A', bpm); }); // Each pattern should be unique const uniquePatterns = new Set(patterns); expect(uniquePatterns.size).toBe(genres.length); }); }); describe('BPM Range Validation', () => { const bpmRanges: Record<string, { min: number; max: number }> = { techno: { min: 120, max: 140 }, house: { min: 120, max: 130 }, dnb: { min: 160, max: 180 }, ambient: { min: 60, max: 90 }, trap: { min: 130, max: 150 }, jungle: { min: 160, max: 180 }, jazz: { min: 100, max: 180 } }; Object.entries(bpmRanges).forEach(([genre, range]) => { it(`should generate valid ${genre} at minimum BPM (${range.min})`, () => { const pattern = generator.generateCompletePattern(genre, 'A', range.min); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); it(`should generate valid ${genre} at maximum BPM (${range.max})`, () => { const pattern = generator.generateCompletePattern(genre, 'A', range.max); expect(pattern).toBeTruthy(); const validation = validator.validate(pattern); expect(validation.valid).toBe(true); }); }); }); describe('Pattern Component Validation', () => { it('should generate patterns with drum components', () => { const pattern = generator.generateDrumPattern('techno', 1); expect(pattern).toBeTruthy(); expect(pattern).toMatch(/s\(/); }); it('should generate patterns with bassline components', () => { const pattern = generator.generateBassline('D', 'house'); expect(pattern).toBeTruthy(); expect(pattern).toMatch(/note\(/); }); it('should generate patterns with melodic components', () => { const pattern = generator.generateCompletePattern('jazz', 'A#', 120); expect(pattern).toBeTruthy(); // Should contain both rhythmic and tonal elements expect(pattern.length).toBeGreaterThan(20); }); }); describe('Pattern Safety Validation', () => { const genres = ['techno', 'house', 'dnb', 'ambient', 'trap', 'jungle', 'jazz']; genres.forEach(genre => { it(`should generate safe ${genre} patterns (no dangerous gain levels)`, () => { const pattern = generator.generateCompletePattern(genre, 'A', 130); // Should not contain dangerous gain levels expect(pattern).not.toMatch(/gain\s*\(\s*[3-9]|gain\s*\(\s*[1-9]\d/); }); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/williamzujkowski/strudel-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server