#!/usr/bin/env node /** * API Test Script * Tester alle API endpoints for at sikre de svarer korrekt */ import { spawn } from 'child_process'; const BASE_URL = process.env.TEST_URL || 'http://localhost:3002'; let serverProcess = null; let testsPassed = 0; let testsFailed = 0; // ANSI farve koder const colors = { reset: '\x1b[0m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', cyan: '\x1b[36m', }; function log(message, color = colors.reset) { console.log(`${color}${message}${colors.reset}`); } // Start development server hvis ikke eksternt URL async function startServer() { if (process.env.TEST_URL) { log(`Using external server: ${BASE_URL}`, colors.cyan); return; } log('Starting development server...', colors.yellow); serverProcess = spawn('npm', ['run', 'dev'], { stdio: ['ignore', 'pipe', 'pipe'], shell: true }); return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('Server startup timeout')); }, 30000); serverProcess.stdout.on('data', (data) => { const output = data.toString(); if (output.includes('Ready')) { clearTimeout(timeout); log('✓ Server started', colors.green); // Vent lidt ekstra for at sikre server er klar setTimeout(resolve, 2000); } }); serverProcess.stderr.on('data', (data) => { console.error(data.toString()); }); }); } // Stop server function stopServer() { if (serverProcess) { log('Stopping server...', colors.yellow); serverProcess.kill(); } } // Test en API endpoint async function testEndpoint(name, method, path, options = {}) { const url = `${BASE_URL}${path}`; const { body, headers = {}, expectedStatus = 200, skipBodyCheck = false } = options; try { const fetchOptions = { method, headers: { 'Content-Type': 'application/json', ...headers } }; if (body) { fetchOptions.body = JSON.stringify(body); } log(`\nTesting: ${method} ${path}`, colors.cyan); const response = await fetch(url, fetchOptions); // Tjek status code if (response.status !== expectedStatus) { throw new Error(`Expected status ${expectedStatus}, got ${response.status}`); } // Tjek response body hvis ikke skippet if (!skipBodyCheck) { const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { const data = await response.json(); if (!data) { throw new Error('Empty JSON response'); } } } log(`✓ ${name}`, colors.green); testsPassed++; return true; } catch (error) { log(`✗ ${name}: ${error.message}`, colors.red); testsFailed++; return false; } } // Kør alle tests async function runTests() { log('\n=== API Test Suite ===\n', colors.blue); // GET endpoints await testEndpoint('GET /api/packages', 'GET', '/api/packages'); await testEndpoint('GET /api/menus', 'GET', '/api/menus'); await testEndpoint('GET /api/availability/weekly', 'GET', '/api/availability/weekly'); // POST endpoints (forventer fejl uden auth/data) await testEndpoint( 'POST /api/menu-generator (uden data)', 'POST', '/api/menu-generator', { body: { prompt: 'test', courses: 3 }, expectedStatus: 200 } ); await testEndpoint( 'POST /api/menu-generator (image generation)', 'POST', '/api/menu-generator', { body: { generateImage: true, menuDescription: 'Test menu with elegant dishes' }, expectedStatus: 200, skipBodyCheck: true // Kan fejle hvis ingen OPENAI_API_KEY } ); await testEndpoint( 'POST /api/contact', 'POST', '/api/contact', { body: { name: 'Test', email: 'test@test.com', message: 'Test' }, expectedStatus: 500, // Kan fejle uden email config skipBodyCheck: true } ); // Auth endpoints (forventer 400 ved invalid data) await testEndpoint( 'POST /api/auth/login (invalid)', 'POST', '/api/auth/login', { body: { email: 'invalid@test.com', password: 'wrong' }, expectedStatus: 400 // Invalid credentials } ); // Protected endpoints (kan være åbne i dev mode) await testEndpoint( 'GET /api/bookings (uden auth)', 'GET', '/api/bookings', { expectedStatus: 200, skipBodyCheck: true } // Kan være åben i dev ); await testEndpoint( 'POST /api/bookings (uden auth)', 'POST', '/api/bookings', { body: { date: '2025-12-01', guests: 10 }, expectedStatus: 400 // Invalid data format } ); await testEndpoint( 'GET /api/availability/blocked (uden auth)', 'GET', '/api/availability/blocked', { expectedStatus: 200, skipBodyCheck: true } // Kan være åben i dev ); // Vis resultater log('\n=== Test Results ===', colors.blue); log(`Passed: ${testsPassed}`, colors.green); if (testsFailed > 0) { log(`Failed: ${testsFailed}`, colors.red); } log(`Total: ${testsPassed + testsFailed}`, colors.cyan); return testsFailed === 0; } // Main async function main() { try { await startServer(); const success = await runTests(); stopServer(); process.exit(success ? 0 : 1); } catch (error) { log(`\nError: ${error.message}`, colors.red); stopServer(); process.exit(1); } } // Handle cleanup på exit process.on('SIGINT', () => { log('\nTest interrupted', colors.yellow); stopServer(); process.exit(130); }); process.on('SIGTERM', () => { stopServer(); process.exit(143); }); main();