Skip to main content
Glama
generate-harmony-palette.test.ts15.7 kB
/** * Tests for the generate_harmony_palette MCP tool */ import { generateHarmonyPaletteTool } from '../../src/tools/generate-harmony-palette'; import { ToolResponse, ErrorResponse } from '../../src/types/index'; describe('generateHarmonyPaletteTool', () => { test('should have correct tool definition', () => { expect(generateHarmonyPaletteTool.name).toBe('generate_harmony_palette'); expect(generateHarmonyPaletteTool.description).toContain( 'color theory harmony' ); expect(generateHarmonyPaletteTool.parameters).toBeDefined(); expect(generateHarmonyPaletteTool.handler).toBeDefined(); }); test('should generate complementary palette successfully', async () => { const params = { base_color: '#FF0000', harmony_type: 'complementary', count: 3, variation: 20, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); expect(result.data).toBeDefined(); expect(result.metadata).toBeDefined(); expect(result.export_formats).toBeDefined(); // Check palette data const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(3); expect(paletteData.metadata.harmonyType).toBe('complementary'); expect(paletteData.metadata.baseColor).toBe('#FF0000'); expect(paletteData.metadata.color_count).toBe(3); // Check scores expect(paletteData.scores.diversity).toBeGreaterThanOrEqual(0); expect(paletteData.scores.diversity).toBeLessThanOrEqual(100); expect(paletteData.scores.harmony).toBeGreaterThanOrEqual(0); expect(paletteData.scores.harmony).toBeLessThanOrEqual(100); expect(paletteData.scores.accessibility).toBeGreaterThanOrEqual(0); expect(paletteData.scores.accessibility).toBeLessThanOrEqual(100); // Check relationships expect(paletteData.relationships).toBeDefined(); expect(Array.isArray(paletteData.relationships)).toBe(true); // Check metadata expect(result.metadata.execution_time).toBeGreaterThan(0); expect(result.metadata.tool).toBe('generate_harmony_palette'); expect(result.metadata.color_space_used).toBe('HSL'); expect(result.metadata.timestamp).toBeDefined(); }); test('should generate triadic palette successfully', async () => { const params = { base_color: '#0066CC', harmony_type: 'triadic', count: 5, variation: 15, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(5); expect(paletteData.metadata.harmonyType).toBe('triadic'); expect(paletteData.metadata.baseColor).toBe('#0066CC'); }); test('should generate monochromatic palette successfully', async () => { const params = { base_color: 'hsl(240, 100%, 50%)', harmony_type: 'monochromatic', count: 4, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(4); expect(paletteData.metadata.harmonyType).toBe('monochromatic'); }); test('should generate analogous palette successfully', async () => { const params = { base_color: 'rgb(255, 100, 50)', harmony_type: 'analogous', count: 6, variation: 25, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(6); expect(paletteData.metadata.harmonyType).toBe('analogous'); }); test('should generate tetradic palette successfully', async () => { const params = { base_color: 'red', harmony_type: 'tetradic', count: 4, variation: 10, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(4); expect(paletteData.metadata.harmonyType).toBe('tetradic'); }); test('should generate split-complementary palette successfully', async () => { const params = { base_color: '#33AA66', harmony_type: 'split_complementary', count: 3, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(3); expect(paletteData.metadata.harmonyType).toBe('split_complementary'); }); test('should generate double-complementary palette successfully', async () => { const params = { base_color: '#FF6600', harmony_type: 'double_complementary', count: 5, variation: 30, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(5); expect(paletteData.metadata.harmonyType).toBe('double_complementary'); }); test('should use default values when optional parameters not provided', async () => { const params = { base_color: '#FF0000', harmony_type: 'complementary', }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); const paletteData = result.data as any; expect(paletteData.palette).toHaveLength(5); // Default count }); test('should include proper export formats', async () => { const params = { base_color: '#FF0000', harmony_type: 'complementary', count: 3, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); expect(result.export_formats).toBeDefined(); const exportFormats = result.export_formats!; expect(exportFormats.css).toBeDefined(); expect(exportFormats.scss).toBeDefined(); expect(exportFormats.tailwind).toBeDefined(); expect(exportFormats.json).toBeDefined(); // Check CSS format expect(exportFormats.css).toContain(':root'); expect(exportFormats.css).toContain('--color-1'); // Check SCSS format expect(exportFormats.scss).toContain('$color-1'); // Check Tailwind format expect(exportFormats.tailwind).toContain('module.exports'); expect(exportFormats.tailwind).toContain('palette-1'); // Check JSON format expect(exportFormats.json).toHaveProperty('colors'); expect(exportFormats.json).toHaveProperty('metadata'); }); test('should include accessibility notes and recommendations', async () => { const params = { base_color: '#FFFF00', // Yellow - potentially problematic for accessibility harmony_type: 'monochromatic', count: 5, variation: 10, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); expect(result.metadata.accessibility_notes).toBeDefined(); expect(result.metadata.recommendations).toBeDefined(); expect(Array.isArray(result.metadata.accessibility_notes)).toBe(true); expect(Array.isArray(result.metadata.recommendations)).toBe(true); }); test('should include harmony-specific recommendations', async () => { const harmonyTypes = [ 'complementary', 'triadic', 'analogous', 'monochromatic', ]; for (const harmonyType of harmonyTypes) { const params = { base_color: '#FF0000', harmony_type: harmonyType, count: 3, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); expect(result.metadata.recommendations).toBeDefined(); expect(result.metadata.recommendations!.length).toBeGreaterThan(0); } }); test('should meet performance requirements', async () => { const params = { base_color: '#FF0000', harmony_type: 'triadic', count: 8, variation: 30, }; const startTime = performance.now(); const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; const endTime = performance.now(); expect(result.success).toBe(true); const executionTime = endTime - startTime; expect(executionTime).toBeLessThan(500); // Should be under 500ms expect(result.metadata.execution_time).toBeLessThan(500); }); describe('error handling', () => { test('should return error for missing base_color', async () => { const params = { harmony_type: 'complementary', }; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain('base_color is required'); expect(result.error.suggestions).toBeDefined(); }); test('should return error for missing harmony_type', async () => { const params = { base_color: '#FF0000', }; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain('harmony_type is required'); }); test('should return error for invalid base_color', async () => { const params = { base_color: 'invalid-color', harmony_type: 'complementary', }; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain('Invalid base_color'); }); test('should return error for invalid harmony_type', async () => { const params = { base_color: '#FF0000', harmony_type: 'invalid-harmony', }; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain('Invalid harmony_type'); }); test('should return error for count out of range', async () => { const params = { base_color: '#FF0000', harmony_type: 'complementary', count: 2, // Too low }; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain( 'count must be a number between 3 and 10' ); }); test('should return error for variation out of range', async () => { const params = { base_color: '#FF0000', harmony_type: 'complementary', variation: 150, // Too high }; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain( 'variation must be a number between 0 and 100' ); }); test('should return error for non-object parameters', async () => { const params = 'invalid-params'; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain('Parameters must be an object'); }); test('should return error for null parameters', async () => { const params = null; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.error.code).toBe('INVALID_INPUT'); expect(result.error.message).toContain('Parameters must be an object'); }); test('should include execution time in error response', async () => { const params = { base_color: 'invalid-color', harmony_type: 'complementary', }; const result = (await generateHarmonyPaletteTool.handler( params )) as ErrorResponse; expect(result.success).toBe(false); expect(result.metadata.execution_time).toBeGreaterThanOrEqual(0); expect(result.metadata.tool).toBe('generate_harmony_palette'); expect(result.metadata.timestamp).toBeDefined(); }); }); describe('parameter validation', () => { test('should validate all harmony types', async () => { const validHarmonyTypes = [ 'monochromatic', 'analogous', 'complementary', 'triadic', 'tetradic', 'split_complementary', 'double_complementary', ]; for (const harmonyType of validHarmonyTypes) { const params = { base_color: '#FF0000', harmony_type: harmonyType, }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); } }); test('should validate count boundaries', async () => { // Test minimum valid count const minParams = { base_color: '#FF0000', harmony_type: 'complementary', count: 3, }; const minResult = (await generateHarmonyPaletteTool.handler( minParams )) as ToolResponse; expect(minResult.success).toBe(true); // Test maximum valid count const maxParams = { base_color: '#FF0000', harmony_type: 'complementary', count: 10, }; const maxResult = (await generateHarmonyPaletteTool.handler( maxParams )) as ToolResponse; expect(maxResult.success).toBe(true); }); test('should validate variation boundaries', async () => { // Test minimum valid variation const minParams = { base_color: '#FF0000', harmony_type: 'complementary', variation: 0, }; const minResult = (await generateHarmonyPaletteTool.handler( minParams )) as ToolResponse; expect(minResult.success).toBe(true); // Test maximum valid variation const maxParams = { base_color: '#FF0000', harmony_type: 'complementary', variation: 100, }; const maxResult = (await generateHarmonyPaletteTool.handler( maxParams )) as ToolResponse; expect(maxResult.success).toBe(true); }); test('should handle different color input formats', async () => { const colorFormats = [ '#FF0000', '#F00', 'rgb(255, 0, 0)', 'hsl(0, 100%, 50%)', 'red', ]; for (const color of colorFormats) { const params = { base_color: color, harmony_type: 'complementary', }; const result = (await generateHarmonyPaletteTool.handler( params )) as ToolResponse; expect(result.success).toBe(true); } }); }); });

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/keyurgolani/ColorMcp'

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