Files
kokken/scripts/test-api.mjs
Alex Polo 86685da067 feat: Add menu generation enhancements and API testing script
- Updated package.json to include new test scripts for API testing.
- Modified postcss.config.mjs to correctly configure Tailwind CSS and autoprefixer.
- Enhanced MenuGeneratorPage component to accept starter, main, and dessert requests.
- Updated API route to handle new menu generation parameters and log requests.
- Created LOGIN_CREDENTIALS.md for admin login information and user management instructions.
- Implemented test-api.mjs script to automate API endpoint testing and validate responses.
2025-11-07 14:46:33 +01:00

237 lines
5.6 KiB
JavaScript
Executable File

#!/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();