import { spawn } from 'child_process'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; // Get current file directory (ESM equivalent of __dirname) const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); /** * Test script for the schematic generation functionality * * This script tests the KiCAD MCP server's schematic generation capabilities by: * 1. Creating a new schematic * 2. Adding components (resistors, capacitors) * 3. Adding connections between them * 4. Exporting the schematic to PDF */ // Directory for test outputs const TEST_OUTPUT_DIR = path.join(__dirname, 'schematic_test_output'); if (!fs.existsSync(TEST_OUTPUT_DIR)) { fs.mkdirSync(TEST_OUTPUT_DIR, { recursive: true }); } // Function to send a command to the KiCAD MCP server function sendCommand(serverProcess, command, params) { return new Promise((resolve, reject) => { // Create request object const request = { command, params }; // Convert to JSON and add newline const requestStr = JSON.stringify(request) + '\n'; // Write to stdin of server process console.log(`Sending request to server: ${requestStr}`); serverProcess.stdin.write(requestStr); // Set up response handler let responseData = ''; const responseHandler = (data) => { const chunk = data.toString(); console.log(`Received data: ${chunk}`); responseData += chunk; try { // Try to parse as JSON const response = JSON.parse(responseData); // Got a complete response console.log(`Parsed complete response: ${JSON.stringify(response)}`); serverProcess.stdout.removeListener('data', responseHandler); resolve(response); } catch (e) { // Not complete JSON yet, keep collecting console.log(`JSON parsing failed, continuing to collect data: ${e.message}`); } }; // Set a timeout to prevent hanging indefinitely const timeoutId = setTimeout(() => { console.log("Command timeout after 10 seconds"); serverProcess.stdout.removeListener('data', responseHandler); resolve({ success: false, message: "Timeout waiting for response from server" }); }, 10000); // 10 second timeout // Listen for response serverProcess.stdout.on('data', responseHandler); // Handle errors serverProcess.stderr.on('data', (data) => { console.error(`Server stderr: ${data.toString()}`); }); }); } async function runTest() { console.log('\n=== TESTING SCHEMATIC GENERATION ===\n'); // Start the KiCAD MCP server console.log('Starting KiCAD MCP server...'); // Use shell: true to ensure proper command execution in Windows const serverProcess = spawn('node', ['dist/kicad-server.js'], { stdio: ['pipe', 'pipe', 'pipe'], shell: true }); // Log server startup messages serverProcess.stderr.on('data', (data) => { console.log(`Server startup: ${data.toString()}`); }); // Give server time to start console.log('Waiting for server to start...'); await new Promise(resolve => setTimeout(resolve, 5000)); console.log('Server should be ready now'); try { // 1. Create a new schematic const schematicName = 'TestCircuit'; const schematicPath = path.join(TEST_OUTPUT_DIR, `${schematicName}.kicad_sch`); console.log(`Creating schematic: ${schematicName}...`); const createResult = await sendCommand(serverProcess, 'create_schematic', { projectName: schematicName, path: TEST_OUTPUT_DIR, metadata: { description: 'Test circuit schematic', author: 'KiCAD MCP Test' } }); console.log('Create schematic result:', createResult); if (!createResult.success) { throw new Error(`Failed to create schematic: ${createResult.message}`); } // 2. Add components: resistors, capacitor, and power/ground connections console.log('Adding components to schematic...'); // Add resistor R1 const addR1Result = await sendCommand(serverProcess, 'add_schematic_component', { schematicPath: schematicPath, component: { type: 'R', reference: 'R1', value: '10k', library: 'Device', x: 100, y: 100 } }); console.log('Add R1 result:', addR1Result); // Add resistor R2 const addR2Result = await sendCommand(serverProcess, 'add_schematic_component', { schematicPath: schematicPath, component: { type: 'R', reference: 'R2', value: '4.7k', library: 'Device', x: 100, y: 200 } }); console.log('Add R2 result:', addR2Result); // Add capacitor C1 const addC1Result = await sendCommand(serverProcess, 'add_schematic_component', { schematicPath: schematicPath, component: { type: 'C', reference: 'C1', value: '0.1uF', library: 'Device', x: 200, y: 150 } }); console.log('Add C1 result:', addC1Result); // 3. Add wires to connect components console.log('Adding wires to connect components...'); // Connect R1 to R2 const addWire1Result = await sendCommand(serverProcess, 'add_schematic_wire', { schematicPath: schematicPath, startPoint: [150, 100], endPoint: [150, 200] }); console.log('Add wire 1 result:', addWire1Result); // Connect R2 to C1 const addWire2Result = await sendCommand(serverProcess, 'add_schematic_wire', { schematicPath: schematicPath, startPoint: [150, 200], endPoint: [200, 200] }); console.log('Add wire 2 result:', addWire2Result); // Connect C1 to R1 const addWire3Result = await sendCommand(serverProcess, 'add_schematic_wire', { schematicPath: schematicPath, startPoint: [200, 100], endPoint: [150, 100] }); console.log('Add wire 3 result:', addWire3Result); // 4. Export to PDF console.log('Exporting schematic to PDF...'); const pdfPath = path.join(TEST_OUTPUT_DIR, `${schematicName}.pdf`); const exportResult = await sendCommand(serverProcess, 'export_schematic_pdf', { schematicPath: schematicPath, outputPath: pdfPath }); console.log('Export PDF result:', exportResult); if (exportResult.success) { console.log(`PDF successfully created at: ${pdfPath}`); } else { console.log(`Failed to create PDF: ${exportResult.message}`); } console.log('\n=== SCHEMATIC GENERATION TEST COMPLETED ===\n'); console.log(`Schematic file: ${schematicPath}`); console.log(`PDF file: ${pdfPath}`); } catch (error) { console.error('Test error:', error); } finally { // Kill the server process serverProcess.kill(); } } // Run the test runTest().catch(console.error);