Skip to main content
Glama

CTS MCP Server

by EricA1019
integration.test.tsโ€ข11.3 kB
import { describe, test, expect, beforeAll } from '@jest/globals'; import { ArtifactEngine } from '../artifacts/artifact_engine'; import { D3SignalMapRenderer } from '../artifacts/renderers/d3_signal_map'; import { ReactHopDashboardRenderer } from '../artifacts/renderers/react_hop_dashboard'; import { parseGDScriptSignals } from '../artifacts/parsers/gdscript_parser'; import * as fs from 'fs'; import * as path from 'path'; describe('Integration Tests - Artifact Rendering', () => { let engine: ArtifactEngine; let sampleHopData: any; let sampleSignalData: any; beforeAll(() => { // Load test fixtures const fixturesPath = path.join(__dirname, 'fixtures'); sampleHopData = JSON.parse( fs.readFileSync(path.join(fixturesPath, 'sample_hop_plan.json'), 'utf8') ); sampleSignalData = JSON.parse( fs.readFileSync(path.join(fixturesPath, 'sample_signal_map_data.json'), 'utf8') ); // Initialize artifact engine engine = new ArtifactEngine(); engine.registerRenderer(new D3SignalMapRenderer()); engine.registerRenderer(new ReactHopDashboardRenderer()); }); describe('D3 Signal Map Rendering', () => { test('should render signal map with valid data', async () => { const result = await engine.renderArtifact('signal_map', sampleSignalData); expect(result).toBeDefined(); expect(result.html).toBeDefined(); expect(result.html).toContain('<!DOCTYPE html>'); expect(result.html).toContain('<svg'); expect(result.html).toContain('d3.forceSimulation'); }); test('should include all signals in rendered output', async () => { const result = await engine.renderArtifact('signal_map', sampleSignalData); // Check that signal names are present expect(result.html).toContain('player_health_changed'); expect(result.html).toContain('player_died'); expect(result.html).toContain('combat_started'); expect(result.html).toContain('quest_completed'); expect(result.html).toContain('item_added'); }); test('should include force-directed layout code', async () => { const result = await engine.renderArtifact('signal_map', sampleSignalData); expect(result.html).toContain('forceLink'); expect(result.html).toContain('forceManyBody'); expect(result.html).toContain('forceCenter'); }); test('should render in under 2 seconds', async () => { const start = Date.now(); await engine.renderArtifact('signal_map', sampleSignalData); const elapsed = Date.now() - start; expect(elapsed).toBeLessThan(2000); }); test('should handle empty signal data', async () => { const emptyData = { signals: [], filters: {} }; const result = await engine.renderArtifact('signal_map', emptyData); expect(result).toBeDefined(); expect(result.html).toContain('<!DOCTYPE html>'); }); test('should cache repeated renders', async () => { // First render const result1 = await engine.renderArtifact('signal_map', sampleSignalData); // Second render with same data should be cached const start = Date.now(); const result2 = await engine.renderArtifact('signal_map', sampleSignalData); const elapsed = Date.now() - start; expect(result1.html).toBe(result2.html); expect(result2.cached).toBe(true); expect(elapsed).toBeLessThan(10); // Should be near-instant from cache }); }); describe('React Hop Dashboard Rendering', () => { test('should render hop dashboard with valid data', async () => { const result = await engine.renderArtifact('hop_dashboard', sampleHopData); expect(result).toBeDefined(); expect(result.html).toContain('<!DOCTYPE html>'); expect(result.html).toContain('React'); expect(result.html).toContain('ReactDOM'); }); test('should include all phases and hops', async () => { const result = await engine.renderArtifact('hop_dashboard', sampleHopData); // Check phases expect(result.html).toContain('Phase 1: Foundation'); expect(result.html).toContain('Phase 2: Advanced Features'); // Check hops expect(result.html).toContain('5.1a'); expect(result.html).toContain('MCP Core Infrastructure'); expect(result.html).toContain('5.1b'); expect(result.html).toContain('Artifact Visualizations'); }); test('should include statistics panel', async () => { const result = await engine.renderArtifact('hop_dashboard', sampleHopData); expect(result.html).toContain('Total LOC'); expect(result.html).toContain('CTS Compliance'); expect(result.html).toContain('Completion Rate'); }); test('should include React CDN links', async () => { const result = await engine.renderArtifact('hop_dashboard', sampleHopData); expect(result.html).toContain('unpkg.com/react@18'); expect(result.html).toContain('unpkg.com/react-dom@18'); expect(result.html).toContain('babel/standalone'); }); test('should render in under 1 second', async () => { const start = Date.now(); await engine.renderArtifact('hop_dashboard', sampleHopData); const elapsed = Date.now() - start; expect(elapsed).toBeLessThan(1000); }); test('should handle empty hop data', async () => { const emptyData = { phases: [], statistics: { totalLOC: 0, plannedLOC: 0, complianceRate: 100, completionRate: 0 } }; const result = await engine.renderArtifact('hop_dashboard', emptyData); expect(result).toBeDefined(); expect(result.html).toContain('<!DOCTYPE html>'); }); }); describe('GDScript Parser', () => { test('should parse signals from EventBus fixture', async () => { const fixturesPath = path.join(__dirname, 'fixtures'); const eventBusPath = path.join(fixturesPath, 'sample_eventbus.gd'); const signals = parseGDScriptSignals(eventBusPath); expect(signals.length).toBeGreaterThan(15); expect(signals).toContainEqual( expect.objectContaining({ name: 'player_health_changed' }) ); }); test('should extract signal parameters', async () => { // Create temp file for testing const tempPath = path.join(__dirname, 'fixtures', 'temp_test.gd'); const testCode = 'signal test_signal(param1: int, param2: String)'; fs.writeFileSync(tempPath, testCode); const signals = parseGDScriptSignals(tempPath); expect(signals[0]).toEqual( expect.objectContaining({ name: 'test_signal' }) ); expect(signals[0].params.length).toBeGreaterThan(0); // Cleanup fs.unlinkSync(tempPath); }); test('should handle signals without parameters', async () => { // Create temp file for testing const tempPath = path.join(__dirname, 'fixtures', 'temp_test2.gd'); const testCode = 'signal simple_signal'; fs.writeFileSync(tempPath, testCode); const signals = parseGDScriptSignals(tempPath); expect(signals[0]).toEqual( expect.objectContaining({ name: 'simple_signal', params: [] }) ); // Cleanup fs.unlinkSync(tempPath); }); }); describe('End-to-End Workflow', () => { test('should handle complete signal scanning workflow', async () => { // This would normally scan project files, but we use test data const signals = sampleSignalData.signals; expect(signals).toBeDefined(); expect(signals.length).toBeGreaterThan(0); // Verify signal structure signals.forEach((sig: any) => { expect(sig).toHaveProperty('name'); expect(sig).toHaveProperty('file'); expect(sig).toHaveProperty('connections'); }); }); test('should render both artifact types successfully', async () => { const signalResult = await engine.renderArtifact('signal_map', sampleSignalData); const hopResult = await engine.renderArtifact('hop_dashboard', sampleHopData); expect(signalResult.html).toBeDefined(); expect(hopResult.html).toBeDefined(); expect(signalResult.html).not.toBe(hopResult.html); // Different outputs }); test('should handle unknown artifact type', async () => { await expect( engine.renderArtifact('unknown_type', {}) ).rejects.toThrow(); }); }); describe('Performance Baselines', () => { test('should render 50+ signals efficiently', async () => { // Create large dataset with 50 signals const largeData = { signals: Array.from({ length: 50 }, (_, i) => ({ name: `signal_${i}`, file: `file_${i}.gd`, line: i * 10, connections: [ { file: `consumer_${i}.gd`, line: i * 10 + 5 } ] })), filters: {} }; const start = Date.now(); const result = await engine.renderArtifact('signal_map', largeData); const elapsed = Date.now() - start; expect(result.html).toBeDefined(); expect(elapsed).toBeLessThan(2000); // Under 2s for 50 signals }); test('should handle multiple concurrent renders', async () => { const promises = Array.from({ length: 5 }, () => engine.renderArtifact('hop_dashboard', sampleHopData) ); const start = Date.now(); const results = await Promise.all(promises); const elapsed = Date.now() - start; expect(results).toHaveLength(5); results.forEach((result: any) => { expect(result).toBeDefined(); expect(result.html).toContain('<!DOCTYPE html>'); }); expect(elapsed).toBeLessThan(3000); // All 5 renders under 3s }); }); describe('Error Handling', () => { test('should handle invalid data types gracefully', async () => { // Renderers accept any data and embed it - validation happens client-side const result = await engine.renderArtifact('hop_dashboard', 'not-json-data'); expect(result).toBeDefined(); expect(result.html).toContain('<!DOCTYPE html>'); }); test('should handle missing required fields gracefully', async () => { // Renderers embed data as-is - React will handle missing fields const invalidData = { phases: 'not-an-array' }; const result = await engine.renderArtifact('hop_dashboard', invalidData); expect(result).toBeDefined(); expect(result.html).toContain('<!DOCTYPE html>'); }); test('should handle empty object data', async () => { // Provide empty but valid objects const result1 = await engine.renderArtifact('signal_map', { signals: [], filters: {} }); const result2 = await engine.renderArtifact('hop_dashboard', { phases: [], statistics: { totalLOC: 0, plannedLOC: 0, complianceRate: 100, completionRate: 0 } }); expect(result1).toBeDefined(); expect(result2).toBeDefined(); expect(result1.html).toContain('<!DOCTYPE html>'); expect(result2.html).toContain('<!DOCTYPE html>'); }); }); });

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