286 lines
7.8 KiB
JavaScript
286 lines
7.8 KiB
JavaScript
#!/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 };
|