Files
tilbudgivern/archive/test-files/comprehensive-api-test.js

288 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Comprehensive API Endpoint Test Suite
* Tests all endpoints in unified-server.js
*/
const axios = require('axios');
const BASE_URL = 'http://localhost:4031';
const AUTH = { username: 'toemrer', password: process.env.TEST_PASSWORD };
// Test results tracking
const results = {
total: 0,
passed: 0,
failed: 0,
skipped: 0,
errors: []
};
// Color output
const colors = {
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
reset: '\x1b[0m'
};
function log(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
async function testEndpoint(method, path, options = {}) {
results.total++;
const testName = `${method.toUpperCase()} ${path}`;
try {
const config = {
method,
url: `${BASE_URL}${path}`,
auth: AUTH,
timeout: 5000,
validateStatus: () => true, // Don't throw on any status
...options
};
const response = await axios(config);
if (response.status >= 200 && response.status < 300) {
results.passed++;
log(`${testName} - ${response.status}`, 'green');
return { success: true, status: response.status, data: response.data };
} else if (response.status === 404) {
results.failed++;
log(`${testName} - 404 NOT FOUND (REMOVE THIS ENDPOINT)`, 'red');
results.errors.push({ endpoint: testName, error: '404 - Endpoint should be removed' });
return { success: false, status: 404 };
} else if (response.status === 400 || response.status === 422) {
results.passed++;
log(`⚠️ ${testName} - ${response.status} (Expected validation error)`, 'yellow');
return { success: true, status: response.status };
} else {
results.failed++;
log(`${testName} - ${response.status}`, 'red');
results.errors.push({ endpoint: testName, status: response.status, error: response.data });
return { success: false, status: response.status };
}
} catch (error) {
results.failed++;
log(`${testName} - ${error.message}`, 'red');
results.errors.push({ endpoint: testName, error: error.message });
return { success: false, error: error.message };
}
}
async function runTests() {
log('\n🔍 COMPREHENSIVE API ENDPOINT TEST\n', 'blue');
log('Testing all 180+ endpoints in unified-server.js\n', 'blue');
// ============================================
// HEALTH & ANALYTICS
// ============================================
log('\n📊 HEALTH & ANALYTICS ENDPOINTS', 'blue');
await testEndpoint('get', '/health');
await testEndpoint('get', '/api/health');
await testEndpoint('get', '/api/analytics/kpis');
await testEndpoint('get', '/api/analytics/employees');
await testEndpoint('get', '/api/analytics/customers');
await testEndpoint('get', '/api/analytics/materials');
await testEndpoint('get', '/api/analytics/projects');
await testEndpoint('get', '/api/analytics/search?q=test');
// ============================================
// AUTHENTICATION
// ============================================
log('\n🔐 AUTHENTICATION ENDPOINTS', 'blue');
await testEndpoint('post', '/api/auth/login', {
data: { username: 'toemrer', password: process.env.TEST_PASSWORD }
});
await testEndpoint('post', '/api/auth', {
data: { username: 'toemrer', password: process.env.TEST_PASSWORD }
});
// ============================================
// QUOTES
// ============================================
log('\n📄 QUOTES ENDPOINTS', 'blue');
await testEndpoint('get', '/api/quotes/completed');
await testEndpoint('get', '/api/quotes/openai/stats');
await testEndpoint('post', '/api/quotes/openai/stats/update', {
data: { prompt_tokens: 100, completion_tokens: 50, cost: 0.01 }
});
await testEndpoint('post', '/api/quotes/generate', {
data: {
projectId: 1,
customerName: 'Test Customer',
projectType: 'Tagkonstruktion'
}
});
await testEndpoint('post', '/api/quotes/carpenter-hours', {
data: { projectType: 'Tagkonstruktion', area: 100 }
});
// ============================================
// PRICING & MATERIALS
// ============================================
log('\n💰 PRICING & MATERIALS ENDPOINTS', 'blue');
await testEndpoint('get', '/api/pricing/health');
await testEndpoint('get', '/api/pricing/materials');
await testEndpoint('get', '/api/pricing/categories');
await testEndpoint('get', '/api/pricing/materials/stats');
await testEndpoint('get', '/api/pricing/search?query=spær');
await testEndpoint('get', '/api/prices/suggestions');
await testEndpoint('get', '/api/prices/template');
await testEndpoint('get', '/api/materials/dynamic');
// ============================================
// BYGMA INTEGRATION
// ============================================
log('\n🏗 BYGMA INTEGRATION ENDPOINTS', 'blue');
await testEndpoint('get', '/api/pricing/bygma-imports');
await testEndpoint('get', '/api/pricing/bygma-prices?search=spær');
await testEndpoint('get', '/api/pricing/bygma-stats');
await testEndpoint('get', '/api/material-categories/bygma');
// ============================================
// WEB PRICES
// ============================================
log('\n🌐 WEB PRICES ENDPOINTS', 'blue');
await testEndpoint('post', '/api/web-prices/search', {
data: { query: 'spær', limit: 10 }
});
await testEndpoint('post', '/api/web-prices/carpenter-rates', {
data: { projectType: 'Tagkonstruktion' }
});
await testEndpoint('get', '/api/web-prices/suggestions/roof');
// ============================================
// CATEGORIES
// ============================================
log('\n📁 CATEGORIES ENDPOINTS', 'blue');
await testEndpoint('get', '/api/categories');
await testEndpoint('get', '/api/categories/list');
// ============================================
// MATERIAL PACKAGES
// ============================================
log('\n📦 MATERIAL PACKAGES ENDPOINTS', 'blue');
await testEndpoint('get', '/api/material-packages');
await testEndpoint('post', '/api/material-packages', {
data: {
name: 'Test Package',
description: 'Test',
materials: []
}
});
// ============================================
// CUSTOMER PROJECTS
// ============================================
log('\n🏠 CUSTOMER PROJECTS ENDPOINTS', 'blue');
await testEndpoint('get', '/api/customer-projects/projects');
await testEndpoint('get', '/api/customer-projects/similar?projectType=Tagkonstruktion');
await testEndpoint('get', '/api/customer-projects/material-categories');
await testEndpoint('get', '/api/customer-projects/tag-experience-suggestions');
await testEndpoint('get', '/api/tag-geometry-estimates');
await testEndpoint('get', '/api/real-project-types');
await testEndpoint('post', '/api/real-project-suggestions', {
data: { projectType: 'Tagkonstruktion', area: 100 }
});
// Test creating a project
const createResult = await testEndpoint('post', '/api/customer-projects/projects', {
data: {
customer_name: 'API Test Customer',
project_type: 'Tagkonstruktion',
project_description: 'Test project for API validation'
}
});
if (createResult.success && createResult.data && createResult.data.projectId) {
const projectId = createResult.data.projectId;
log(`\n🔍 Testing project-specific endpoints for project ${projectId}`, 'blue');
await testEndpoint('get', `/api/customer-projects/${projectId}`);
await testEndpoint('get', `/api/customer-projects/${projectId}/breakdown`);
await testEndpoint('get', `/api/customer-projects/${projectId}/quotes`);
await testEndpoint('get', `/api/customer-projects/${projectId}/geometry`);
await testEndpoint('get', `/api/customer-projects/${projectId}/labor`);
await testEndpoint('get', `/api/customer-projects/${projectId}/materials`);
await testEndpoint('get', `/api/customer-projects/${projectId}/packages`);
await testEndpoint('get', `/api/customer-projects/${projectId}/calculation`);
await testEndpoint('get', `/api/customer-projects/${projectId}/tasks`);
// Update geometry
await testEndpoint('post', `/api/customer-projects/${projectId}/geometry`, {
data: {
area_m2: 100,
vindskede_lbm: 50
}
});
// Update project
await testEndpoint('put', `/api/customer-projects/${projectId}`, {
data: {
project_description: 'Updated description'
}
});
// Clean up: delete test project
await testEndpoint('delete', `/api/customer-projects/${projectId}`);
}
// ============================================
// INSTALLATION MANUALS
// ============================================
log('\n📖 INSTALLATION MANUALS ENDPOINTS', 'blue');
await testEndpoint('get', '/api/customer/installation-manual/search?product_name=280');
// ============================================
// ORDERS (if implemented)
// ============================================
log('\n📋 ORDERS ENDPOINTS', 'blue');
await testEndpoint('get', '/api/orders');
await testEndpoint('get', '/api/orders/status-summary');
// ============================================
// UPLOADS
// ============================================
log('\n📤 UPLOADS ENDPOINTS', 'blue');
await testEndpoint('get', '/api/uploads/recent');
// ============================================
// SUMMARY
// ============================================
log('\n' + '='.repeat(60), 'blue');
log('📊 TEST SUMMARY', 'blue');
log('='.repeat(60), 'blue');
log(`Total Tests: ${results.total}`);
log(`✅ Passed: ${results.passed}`, 'green');
log(`❌ Failed: ${results.failed}`, results.failed > 0 ? 'red' : 'green');
log(`⏭️ Skipped: ${results.skipped}`, 'yellow');
const successRate = ((results.passed / results.total) * 100).toFixed(1);
log(`\n📈 Success Rate: ${successRate}%`, successRate > 90 ? 'green' : 'yellow');
if (results.errors.length > 0) {
log('\n❌ ERRORS FOUND:', 'red');
results.errors.forEach((error, index) => {
log(`${index + 1}. ${error.endpoint}`, 'red');
log(` ${JSON.stringify(error.error || error.status)}`, 'red');
});
}
log('\n✨ Test completed!\n', 'blue');
// Exit with error code if tests failed
process.exit(results.failed > 0 ? 1 : 0);
}
// Run tests
runTests().catch(error => {
log(`\n💥 Fatal error: ${error.message}`, 'red');
console.error(error);
process.exit(1);
});