#!/usr/bin/env node /** * Mock Server Integration Test * * Tests the mock server functionality to ensure all endpoints work correctly */ const http = require('http'); const MOCK_SERVER_URL = 'http://localhost:3002'; const TIMEOUT = 5000; // 5 seconds function makeRequest(path, method = 'GET', body = null) { return new Promise((resolve, reject) => { const options = { hostname: 'localhost', port: 3002, path: path, method: method, headers: { 'Content-Type': 'application/json' } }; const req = http.request(options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const jsonData = JSON.parse(data); resolve({ status: res.statusCode, data: jsonData }); } catch (error) { resolve({ status: res.statusCode, data: data }); } }); }); req.on('error', (error) => { reject(error); }); req.setTimeout(TIMEOUT, () => { req.destroy(); reject(new Error('Request timeout')); }); if (body) { req.write(JSON.stringify(body)); } req.end(); }); } async function testEndpoint(name, testFn) { try { console.log(`๐Ÿงช Testing ${name}...`); const result = await testFn(); console.log(`โœ… ${name}: PASS`); return { name, status: 'PASS', result }; } catch (error) { console.log(`โŒ ${name}: FAIL - ${error.message}`); return { name, status: 'FAIL', error: error.message }; } } async function runTests() { console.log('๐Ÿš€ SPORE UI Mock Server Integration Tests'); console.log('=========================================='); console.log(''); const results = []; // Test 1: Health Check results.push(await testEndpoint('Health Check', async () => { const response = await makeRequest('/api/health'); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } if (!response.data.status) { throw new Error('Missing status field'); } if (!response.data.mock) { throw new Error('Missing mock field'); } return response.data; })); // Test 2: Discovery Nodes results.push(await testEndpoint('Discovery Nodes', async () => { const response = await makeRequest('/api/discovery/nodes'); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } if (!response.data.primaryNode) { throw new Error('Missing primaryNode field'); } if (!Array.isArray(response.data.nodes)) { throw new Error('Nodes should be an array'); } return response.data; })); // Test 3: Task Status results.push(await testEndpoint('Task Status', async () => { const response = await makeRequest('/api/tasks/status'); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } if (!response.data.summary) { throw new Error('Missing summary field'); } if (!Array.isArray(response.data.tasks)) { throw new Error('Tasks should be an array'); } return response.data; })); // Test 4: Task Control results.push(await testEndpoint('Task Control', async () => { const response = await makeRequest('/api/tasks/control', 'POST', { task: 'heartbeat', action: 'status' }); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } if (!response.data.success) { throw new Error('Task control should succeed'); } return response.data; })); // Test 5: System Status results.push(await testEndpoint('System Status', async () => { const response = await makeRequest('/api/node/status'); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } if (typeof response.data.freeHeap !== 'number') { throw new Error('freeHeap should be a number'); } if (!response.data.chipId) { throw new Error('Missing chipId field'); } return response.data; })); // Test 6: Cluster Members results.push(await testEndpoint('Cluster Members', async () => { const response = await makeRequest('/api/cluster/members'); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } if (!Array.isArray(response.data.members)) { throw new Error('Members should be an array'); } return response.data; })); // Test 7: Random Primary Selection results.push(await testEndpoint('Random Primary Selection', async () => { const response = await makeRequest('/api/discovery/random-primary', 'POST', { timestamp: new Date().toISOString() }); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } if (!response.data.success) { throw new Error('Random selection should succeed'); } return response.data; })); // Test 8: Proxy Call results.push(await testEndpoint('Proxy Call', async () => { const response = await makeRequest('/api/proxy-call', 'POST', { ip: '192.168.1.100', method: 'GET', uri: '/api/node/status' }); if (response.status !== 200) { throw new Error(`Expected status 200, got ${response.status}`); } return response.data; })); // Test 9: Error Handling results.push(await testEndpoint('Error Handling', async () => { const response = await makeRequest('/api/tasks/control', 'POST', { task: 'nonexistent', action: 'status' }); if (response.status !== 404) { throw new Error(`Expected status 404, got ${response.status}`); } return response.data; })); // Test 10: Invalid Parameters results.push(await testEndpoint('Invalid Parameters', async () => { const response = await makeRequest('/api/tasks/control', 'POST', { // Missing required fields }); if (response.status !== 400) { throw new Error(`Expected status 400, got ${response.status}`); } return response.data; })); // Print Results console.log(''); console.log('๐Ÿ“Š Test Results'); console.log('==============='); const passed = results.filter(r => r.status === 'PASS').length; const failed = results.filter(r => r.status === 'FAIL').length; const total = results.length; results.forEach(result => { const status = result.status === 'PASS' ? 'โœ…' : 'โŒ'; console.log(`${status} ${result.name}`); if (result.status === 'FAIL') { console.log(` Error: ${result.error}`); } }); console.log(''); console.log(`Total: ${total} | Passed: ${passed} | Failed: ${failed}`); if (failed === 0) { console.log(''); console.log('๐ŸŽ‰ All tests passed! Mock server is working correctly.'); } else { console.log(''); console.log('โš ๏ธ Some tests failed. Check the mock server configuration.'); } return failed === 0; } // Check if mock server is running async function checkMockServer() { try { const response = await makeRequest('/api/health'); return response.status === 200; } catch (error) { return false; } } async function main() { console.log('๐Ÿ” Checking if mock server is running...'); const isRunning = await checkMockServer(); if (!isRunning) { console.log('โŒ Mock server is not running!'); console.log(''); console.log('Please start the mock server first:'); console.log(' npm run mock:healthy'); console.log(''); process.exit(1); } console.log('โœ… Mock server is running'); console.log(''); const success = await runTests(); process.exit(success ? 0 : 1); } // Run tests if (require.main === module) { main().catch(error => { console.error('โŒ Test runner failed:', error.message); process.exit(1); }); } module.exports = { runTests, checkMockServer };