Skip to main content
Glama
server-renderer-registration.test.ts7.99 kB
/** * Tests for Server Renderer Registration * * Verifies conditional renderer registration based on CTS_EXPERIMENTAL_MCP_UI flag. * Ensures backward compatibility and feature flag behavior. */ import { describe, it, expect } from '@jest/globals'; import { ArtifactEngine } from '../artifacts/artifact_engine.js'; import { InteractiveSignalMapRenderer } from '../artifacts/renderers/interactive_signal_map.js'; import { D3HopDashboardRenderer } from '../artifacts/renderers/d3_hop_dashboard.js'; import { PlaceholderSignalMapRenderer } from '../artifacts/renderers/placeholder_signal_map.js'; import { PlaceholderHopDashboardRenderer } from '../artifacts/renderers/placeholder_hop_dashboard.js'; describe('Server Renderer Registration', () => { describe('Feature Flag: CTS_EXPERIMENTAL_MCP_UI=true', () => { it('should register InteractiveSignalMapRenderer with ArtifactEngine', () => { const engine = new ArtifactEngine(); const renderer = new InteractiveSignalMapRenderer(); engine.registerRenderer(renderer); expect(engine.hasRenderer('signal_map_interactive')).toBe(true); expect(engine.getRegisteredTypes()).toContain('signal_map_interactive'); }); it('should register D3HopDashboardRenderer with ArtifactEngine', () => { const engine = new ArtifactEngine(); const renderer = new D3HopDashboardRenderer(); engine.registerRenderer(renderer); expect(engine.hasRenderer('hop_dashboard')).toBe(true); expect(engine.getRegisteredTypes()).toContain('hop_dashboard'); }); it('should support both renderers in same engine', () => { const engine = new ArtifactEngine(); engine.registerRenderer(new InteractiveSignalMapRenderer()); engine.registerRenderer(new D3HopDashboardRenderer()); expect(engine.hasRenderer('signal_map_interactive')).toBe(true); expect(engine.hasRenderer('hop_dashboard')).toBe(true); expect(engine.getRegisteredTypes()).toHaveLength(2); }); }); describe('Feature Flag: CTS_EXPERIMENTAL_MCP_UI=false (Backward Compatibility)', () => { it('should register PlaceholderSignalMapRenderer with ArtifactEngine', () => { const engine = new ArtifactEngine(); const renderer = new PlaceholderSignalMapRenderer(); engine.registerRenderer(renderer); expect(engine.hasRenderer('signal_map')).toBe(true); }); it('should register PlaceholderHopDashboardRenderer with ArtifactEngine', () => { const engine = new ArtifactEngine(); const renderer = new PlaceholderHopDashboardRenderer(); engine.registerRenderer(renderer); expect(engine.hasRenderer('hop_dashboard')).toBe(true); }); it('should support both placeholder renderers', () => { const engine = new ArtifactEngine(); engine.registerRenderer(new PlaceholderSignalMapRenderer()); engine.registerRenderer(new PlaceholderHopDashboardRenderer()); expect(engine.hasRenderer('signal_map')).toBe(true); expect(engine.hasRenderer('hop_dashboard')).toBe(true); }); }); describe('Renderer Type Registration', () => { it('should correctly identify signal_map_interactive renderer type', () => { const renderer = new InteractiveSignalMapRenderer(); expect(renderer.type).toBe('signal_map_interactive'); }); it('should correctly identify hop_dashboard renderer type', () => { const renderer = new D3HopDashboardRenderer(); expect(renderer.type).toBe('hop_dashboard'); }); it('should register renderer with correct type string', () => { const engine = new ArtifactEngine(); const renderer = new D3HopDashboardRenderer(); engine.registerRenderer(renderer); const types = engine.getRegisteredTypes(); expect(types).toContain('hop_dashboard'); }); }); describe('Backward Compatibility', () => { it('should maintain placeholder signal map functionality', async () => { const renderer = new PlaceholderSignalMapRenderer(); const html = await renderer.render({ signals: [], connections: [] }); expect(html).toContain('Signal Map'); expect(html).toContain('Placeholder'); }); it('should maintain placeholder hop dashboard functionality', async () => { const renderer = new PlaceholderHopDashboardRenderer(); const html = await renderer.render({ currentPhase: 'Phase 1', phases: [], stats: { totalLOC: 0, plannedLOC: 0, ctsComplianceRate: 0, completionRate: 0 } }); expect(html).toContain('Hop Dashboard'); expect(html).toContain('placeholder'); }); }); describe('Production Renderer Functionality', () => { it('should render signal map with D3 code', async () => { const renderer = new InteractiveSignalMapRenderer(); const html = await renderer.render({ signals: [{ name: 'test_signal', params: [], file: 'test.gd', line: 1 }], connections: [] }); expect(html).toContain('<!DOCTYPE html>'); expect(html).toContain('d3'); expect(html).toContain('test_signal'); }); it('should render hop dashboard with Gantt chart', async () => { const renderer = new D3HopDashboardRenderer(); const html = await renderer.render({ currentPhase: 'Phase 1', phases: [{ name: 'Phase 1', hops: [{ id: 'hop-1', name: 'Test Hop', status: 'completed' as const, description: 'Test', estimatedLOC: 100, ctsCompliant: true, phase: 'Phase 1', dependencies: [] }] }], stats: { totalLOC: 100, plannedLOC: 100, ctsComplianceRate: 1.0, completionRate: 1.0 } }); expect(html).toContain('<!DOCTYPE html>'); expect(html).toContain('d3'); expect(html).toContain('Test Hop'); expect(html).toContain('Dashboard Stats'); }); }); describe('Integration: Multiple Renderers', () => { it('should support registering multiple renderer types', () => { const engine = new ArtifactEngine(); engine.registerRenderer(new InteractiveSignalMapRenderer()); engine.registerRenderer(new D3HopDashboardRenderer()); const types = engine.getRegisteredTypes(); expect(types).toContain('signal_map_interactive'); expect(types).toContain('hop_dashboard'); expect(types.length).toBeGreaterThanOrEqual(2); }); it('should not conflict between renderer types', () => { const engine = new ArtifactEngine(); const signalRenderer = new InteractiveSignalMapRenderer(); const hopRenderer = new D3HopDashboardRenderer(); engine.registerRenderer(signalRenderer); engine.registerRenderer(hopRenderer); // Both should be registered expect(engine.hasRenderer('signal_map_interactive')).toBe(true); expect(engine.hasRenderer('hop_dashboard')).toBe(true); // Types should be distinct expect(signalRenderer.type).not.toBe(hopRenderer.type); }); }); describe('Renderer Type Constants', () => { it('should use distinct type strings for production vs placeholder', () => { const signalRenderer = new InteractiveSignalMapRenderer(); const hopRenderer = new D3HopDashboardRenderer(); const placeholderSignal = new PlaceholderSignalMapRenderer(); const placeholderHop = new PlaceholderHopDashboardRenderer(); // Production and placeholder signal renderers have different types expect(signalRenderer.type).toBe('signal_map_interactive'); expect(placeholderSignal.type).toBe('signal_map'); // All hop dashboard renderers share the same type expect(hopRenderer.type).toBe('hop_dashboard'); expect(placeholderHop.type).toBe('hop_dashboard'); }); }); });

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/EricA1019/CTS_MCP'

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