Files
filezzy-staging/backend/scripts/test-all-endpoints.ts
2026-02-04 14:16:04 +01:00

315 lines
8.6 KiB
TypeScript

#!/usr/bin/env ts-node
import axios from 'axios';
import jwt from 'jsonwebtoken';
import * as fs from 'fs';
import * as path from 'path';
/**
* Comprehensive API endpoint tester
* Tests all major endpoints and reports results
*/
const BASE_URL = process.env.API_URL || 'http://localhost:4000';
// Generate test tokens
const freeToken = jwt.sign(
{
sub: 'test-free-user-api',
email: 'api-test-free@test.com',
preferred_username: 'apitestfree',
realm_access: { roles: [] },
},
'test-secret',
{ expiresIn: '1h' }
);
const premiumToken = jwt.sign(
{
sub: 'test-premium-user-api',
email: 'api-test-premium@test.com',
preferred_username: 'apitestpremium',
realm_access: { roles: ['premium-user'] },
},
'test-secret',
{ expiresIn: '1h' }
);
interface TestResult {
endpoint: string;
method: string;
status: number;
success: boolean;
message: string;
duration: number;
}
const results: TestResult[] = [];
async function testEndpoint(
name: string,
method: string,
endpoint: string,
options: {
token?: string;
data?: any;
expectedStatus?: number;
headers?: any;
} = {}
): Promise<void> {
const startTime = Date.now();
try {
const config: any = {
method,
url: `${BASE_URL}${endpoint}`,
headers: {
...options.headers,
},
validateStatus: () => true, // Don't throw on any status
};
if (options.token) {
config.headers['Authorization'] = `Bearer ${options.token}`;
}
if (options.data) {
config.data = options.data;
config.headers['Content-Type'] = 'application/json';
}
const response = await axios(config);
const duration = Date.now() - startTime;
const expectedStatus = options.expectedStatus || 200;
const success = response.status === expectedStatus ||
(response.status >= 200 && response.status < 300);
results.push({
endpoint: `${method} ${endpoint}`,
method,
status: response.status,
success,
message: success ? '✅ PASS' : `❌ FAIL (expected ${expectedStatus}, got ${response.status})`,
duration,
});
console.log(`${success ? '✅' : '❌'} ${name}: ${response.status} (${duration}ms)`);
} catch (error: any) {
const duration = Date.now() - startTime;
results.push({
endpoint: `${method} ${endpoint}`,
method,
status: 0,
success: false,
message: `❌ ERROR: ${error.message}`,
duration,
});
console.log(`${name}: ERROR - ${error.message}`);
}
}
async function runTests() {
console.log('\n=================================================');
console.log('🧪 Testing All API Endpoints');
console.log('=================================================\n');
console.log(`Base URL: ${BASE_URL}\n`);
// Health Endpoints
console.log('📊 Testing Health Endpoints...');
await testEndpoint('Basic Health Check', 'GET', '/health');
await testEndpoint('Detailed Health Check', 'GET', '/health/detailed');
console.log('');
// User Endpoints
console.log('👤 Testing User Endpoints...');
await testEndpoint('Get User Profile (FREE)', 'GET', '/api/v1/user/profile', {
token: freeToken,
});
await testEndpoint('Get User Limits (FREE)', 'GET', '/api/v1/user/limits', {
token: freeToken,
});
await testEndpoint('Get User Profile (PREMIUM)', 'GET', '/api/v1/user/profile', {
token: premiumToken,
});
await testEndpoint('Get User Limits (PREMIUM)', 'GET', '/api/v1/user/limits', {
token: premiumToken,
});
await testEndpoint('Get User Profile (No Auth)', 'GET', '/api/v1/user/profile', {
expectedStatus: 401,
});
console.log('');
// Job Endpoints
console.log('📋 Testing Job Endpoints...');
await testEndpoint('Get User Jobs (FREE)', 'GET', '/api/v1/jobs', {
token: freeToken,
});
await testEndpoint('Get User Jobs (PREMIUM)', 'GET', '/api/v1/jobs', {
token: premiumToken,
});
await testEndpoint('Get Job Status (Non-existent)', 'GET', '/api/v1/jobs/non-existent-id', {
token: freeToken,
expectedStatus: 404,
});
console.log('');
// PDF Tool Endpoints
console.log('📄 Testing PDF Tool Endpoints...');
// Test PDF Merge (Available to all)
await testEndpoint('PDF Merge (FREE)', 'POST', '/api/v1/tools/pdf/merge', {
token: freeToken,
data: {
fileIds: ['test-file-1', 'test-file-2'],
parameters: {},
},
expectedStatus: 202,
});
await testEndpoint('PDF Merge (PREMIUM)', 'POST', '/api/v1/tools/pdf/merge', {
token: premiumToken,
data: {
fileIds: ['test-file-1', 'test-file-2'],
parameters: {},
},
expectedStatus: 202,
});
// Test PDF Compress
await testEndpoint('PDF Compress (FREE)', 'POST', '/api/v1/tools/pdf/compress', {
token: freeToken,
data: {
fileIds: ['test-file-1'],
parameters: { optimizeLevel: 3 },
},
expectedStatus: 202,
});
// Test PDF Split
await testEndpoint('PDF Split (FREE)', 'POST', '/api/v1/tools/pdf/split', {
token: freeToken,
data: {
fileIds: ['test-file-1'],
parameters: {},
},
expectedStatus: 202,
});
// Test PDF Rotate
await testEndpoint('PDF Rotate (FREE)', 'POST', '/api/v1/tools/pdf/rotate', {
token: freeToken,
data: {
fileIds: ['test-file-1'],
parameters: { angle: 90 },
},
expectedStatus: 202,
});
// Test PDF OCR (Premium only - should fail for FREE)
await testEndpoint('PDF OCR (FREE - Should Fail)', 'POST', '/api/v1/tools/pdf/ocr', {
token: freeToken,
data: {
fileIds: ['test-file-1'],
parameters: { languages: ['eng'] },
},
expectedStatus: 403,
});
await testEndpoint('PDF OCR (PREMIUM)', 'POST', '/api/v1/tools/pdf/ocr', {
token: premiumToken,
data: {
fileIds: ['test-file-1'],
parameters: { languages: ['eng'] },
},
expectedStatus: 202,
});
// Test PDF Watermark
await testEndpoint('PDF Watermark (FREE)', 'POST', '/api/v1/tools/pdf/watermark', {
token: freeToken,
data: {
fileIds: ['test-file-1'],
parameters: {
watermarkType: 'text',
watermarkText: 'TEST',
},
},
expectedStatus: 202,
});
// Test PDF to Images
await testEndpoint('PDF to Images (FREE)', 'POST', '/api/v1/tools/pdf/to-images', {
token: freeToken,
data: {
fileIds: ['test-file-1'],
parameters: { imageFormat: 'png' },
},
expectedStatus: 202,
});
// Test Images to PDF
await testEndpoint('Images to PDF (FREE)', 'POST', '/api/v1/tools/pdf/from-images', {
token: freeToken,
data: {
fileIds: ['image-1', 'image-2'],
parameters: {},
},
expectedStatus: 202,
});
console.log('');
// Authentication Tests
console.log('🔐 Testing Authentication...');
await testEndpoint('Protected Endpoint (No Token)', 'GET', '/api/v1/user/profile', {
expectedStatus: 401,
});
await testEndpoint('Protected Endpoint (Invalid Token)', 'GET', '/api/v1/user/profile', {
token: 'invalid-token',
expectedStatus: 401,
});
console.log('');
// Summary
console.log('\n=================================================');
console.log('📊 Test Summary');
console.log('=================================================\n');
const total = results.length;
const passed = results.filter(r => r.success).length;
const failed = total - passed;
const avgDuration = Math.round(results.reduce((sum, r) => sum + r.duration, 0) / total);
console.log(`Total Tests: ${total}`);
console.log(`Passed: ✅ ${passed} (${((passed/total)*100).toFixed(1)}%)`);
console.log(`Failed: ❌ ${failed} (${((failed/total)*100).toFixed(1)}%)`);
console.log(`Average Response Time: ${avgDuration}ms\n`);
// Failed tests details
if (failed > 0) {
console.log('Failed Tests:');
console.log('---------------------------------------------------');
results.filter(r => !r.success).forEach(r => {
console.log(`${r.message}`);
console.log(` ${r.endpoint} - Status: ${r.status}`);
});
console.log('');
}
// Performance stats
console.log('Performance Stats:');
console.log('---------------------------------------------------');
const sortedByDuration = [...results].sort((a, b) => b.duration - a.duration);
console.log(`Fastest: ${sortedByDuration[sortedByDuration.length - 1].endpoint} (${sortedByDuration[sortedByDuration.length - 1].duration}ms)`);
console.log(`Slowest: ${sortedByDuration[0].endpoint} (${sortedByDuration[0].duration}ms)`);
console.log('\n=================================================\n');
// Exit with error code if tests failed
process.exit(failed > 0 ? 1 : 0);
}
// Run tests
runTests().catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});