#!/usr/bin/env node /** * Phase 3 Testing Script * Tests the server startup and performance endpoints */ import http from 'http'; import { spawn } from 'child_process'; import path from 'path'; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const PORT = 3000; const TIMEOUT = 15000; // 15 seconds console.log('\n๐Ÿงช Phase 3 Testing Suite'); console.log('================================\n'); // Helper to make HTTP requests function makeRequest(pathname, method = 'GET') { return new Promise((resolve, reject) => { const options = { hostname: 'localhost', port: PORT, path: pathname, method: method, timeout: 5000 }; const req = http.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { resolve({ status: res.statusCode, headers: res.headers, body: data ? JSON.parse(data) : null }); } catch (e) { resolve({ status: res.statusCode, headers: res.headers, body: data }); } }); }); req.on('error', reject); req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); }); req.end(); }); } // Start server console.log('๐Ÿš€ Starting server...\n'); const serverProcess = spawn('node', ['server/index.mjs'], { cwd: __dirname, stdio: ['ignore', 'pipe', 'pipe'] }); let serverOutput = ''; let serverReady = false; let testsPassed = 0; let testsFailed = 0; // Capture server output serverProcess.stdout.on('data', (data) => { const output = data.toString(); serverOutput += output; console.log('[SERVER]', output.trim()); if (output.includes('ObsiViewer server running')) { serverReady = true; } }); serverProcess.stderr.on('data', (data) => { const output = data.toString(); console.error('[SERVER ERROR]', output.trim()); }); // Wait for server to start setTimeout(async () => { if (!serverReady) { console.error('\nโŒ Server failed to start within timeout'); serverProcess.kill(); process.exit(1); } console.log('\nโœ… Server started successfully\n'); console.log('๐Ÿงช Running tests...\n'); const tests = [ { name: 'Health check', path: '/api/health', check: (res) => res.status === 200 && res.body?.status === 'ok' }, { name: 'Performance monitoring endpoint', path: '/__perf', check: (res) => res.status === 200 && res.body?.performance }, { name: 'Metadata endpoint', path: '/api/vault/metadata', check: (res) => res.status === 200 && Array.isArray(res.body?.items) }, { name: 'Paginated metadata endpoint', path: '/api/vault/metadata/paginated?limit=10&cursor=0', check: (res) => res.status === 200 && res.body?.items !== undefined } ]; for (const test of tests) { try { console.log(`๐Ÿงช Testing: ${test.name}...`); const res = await makeRequest(test.path); if (test.check(res)) { console.log(` โœ… PASS - Status ${res.status}\n`); testsPassed++; } else { console.log(` โŒ FAIL - Unexpected response\n`); console.log(' Response:', JSON.stringify(res, null, 2), '\n'); testsFailed++; } } catch (error) { console.log(` โŒ FAIL - ${error.message}\n`); testsFailed++; } } // Test cache behavior console.log('๐Ÿงช Testing cache behavior...'); try { // First request (cache miss) console.log(' Request 1 (cache miss)...'); const res1 = await makeRequest('/api/vault/metadata'); const cached1 = res1.body?.cached; // Second request (cache hit) console.log(' Request 2 (cache hit)...'); const res2 = await makeRequest('/api/vault/metadata'); const cached2 = res2.body?.cached; if (cached1 === false && cached2 === true) { console.log(' โœ… PASS - Cache working correctly\n'); testsPassed++; } else { console.log(` โš ๏ธ Cache behavior: first=${cached1}, second=${cached2}\n`); } } catch (error) { console.log(` โŒ FAIL - ${error.message}\n`); testsFailed++; } // Print results console.log('================================'); console.log(`๐Ÿ“Š Test Results: ${testsPassed} passed, ${testsFailed} failed\n`); if (testsFailed === 0) { console.log('โœ… All tests passed! Phase 3 is working correctly.\n'); } else { console.log('โš ๏ธ Some tests failed. Check the output above.\n'); } // Cleanup console.log('๐Ÿ›‘ Shutting down server...'); serverProcess.kill(); process.exit(testsFailed > 0 ? 1 : 0); }, 3000); // Handle server process exit serverProcess.on('exit', (code) => { if (code !== 0 && code !== null) { console.error(`\nโŒ Server process exited with code ${code}`); } }); // Timeout for entire test suite setTimeout(() => { console.error('\nโŒ Test suite timeout'); serverProcess.kill(); process.exit(1); }, TIMEOUT);