import { AutoReporter } from '../reporters/AutoReporter.js';
/**
* TESTS EDGE CASES - API Controller
* Tests des cas limites, erreurs et comportements extrêmes
*/
const { describe, it, before, after } = require('node:test');
const assert = require('node:assert');
const http = require('node:http');
const { ManualServer } = require('../../lib/modes/ManualServer');
// Helper pour requêtes HTTP
function makeRequest(options, postData = null) {
return new Promise((resolve, reject) => {
const req = http.request(options, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
try {
const parsed = res.headers['content-type']?.includes('application/json')
? JSON.parse(data)
: data;
resolve({ statusCode: res.statusCode, headers: res.headers, data: parsed });
} catch (e) {
resolve({ statusCode: res.statusCode, headers: res.headers, data });
}
});
});
req.on('error', reject);
req.setTimeout(10000, () => {
req.destroy();
reject(new Error('Request timeout'));
});
if (postData) {
req.write(typeof postData === 'object' ? JSON.stringify(postData) : postData);
}
req.end();
});
}
// Auto-Reporter Configuration
const autoReporter = new AutoReporter();
describe('API Edge Cases - Tests des Cas Limites', () => {
let server;
let baseUrl;
const testPort = 3098; // Port différent pour éviter conflits
before(async () => {
server = new ManualServer({ port: testPort, wsPort: 8098 });
await server.start();
baseUrl = `http://localhost:${testPort}`;
console.log(`🧪 Serveur edge cases démarré sur ${baseUrl}`);
});
after(async () => {
if (server) {
await server.stop();
console.log('🛑 Serveur edge cases arrêté');
}
});
describe('🔥 Paramètres Extrêmes', () => {
it('should handle very long project names', async () => {
const longName = 'A'.repeat(10000); // 10KB de nom
const response = await makeRequest({
hostname: 'localhost',
port: testPort,
path: '/api/projects',
method: 'POST',
headers: { 'Content-Type': 'application/json' }
}, {
name: longName,
description: 'Test nom très long'
});
// L'API doit gérer les noms longs gracieusement
assert.ok([201, 400].includes(response.statusCode));
if (response.statusCode === 201) {
assert.strictEqual(response.data.success, true);
assert.strictEqual(response.data.data.name, longName);
} else {
assert.strictEqual(response.data.success, false);
}
});
it('should handle pagination with extreme values', async () => {
// Test avec des valeurs de pagination extrêmes
const testCases = [
{ limit: -1, offset: 0 },
{ limit: 999999, offset: 0 },
{ limit: 50, offset: -1 },
{ limit: 'invalid', offset: 'invalid' },
{ limit: 0, offset: 999999 }
];
for (const testCase of testCases) {
const response = await makeRequest({
hostname: 'localhost',
port: testPort,
path: `/api/articles?limit=${testCase.limit}&offset=${testCase.offset}`,
method: 'GET'
});
// L'API doit soit réussir avec des valeurs normalisées, soit échouer gracieusement
assert.ok([200, 400, 500].includes(response.statusCode));
if (response.statusCode === 200) {
assert.ok(response.data.data.limit >= 0);
assert.ok(response.data.data.offset >= 0);
}
}
});
it('should handle special characters in all fields', async () => {
const specialChars = {
name: '🚀 Test "Special" & émojis 中文',
description: 'Description avec \n\t\r caractères spéciaux \\n "quotes" \'single\' & symbols €£¥',
config: {
special: '<>&"\'{}[]()=+-*/\\',
unicode: '🎯🔥💯✨🌟⭐',
mixed: 'Normal text avec 中文 и русский'
}
};
const response = await makeRequest({
hostname: 'localhost',
port: testPort,
path: '/api/projects',
method: 'POST',
headers: { 'Content-Type': 'application/json' }
}, specialChars);
assert.ok([201, 400].includes(response.statusCode));
if (response.statusCode === 201) {
assert.strictEqual(response.data.data.name, specialChars.name);
assert.strictEqual(response.data.data.description, specialChars.description);
}
});
});
describe('🛡️ Sécurité et Injection', () => {
it('should reject SQL injection attempts', async () => {
const sqlInjections = [
"'; DROP TABLE projects; --",
"1' OR '1'='1",
"admin'/*",
"1; SELECT * FROM users; --"
];
for (const injection of sqlInjections) {
const response = await makeRequest({
hostname: 'localhost',
port: testPort,
path: '/api/projects',
method: 'POST',
headers: { 'Content-Type': 'application/json' }
}, {
name: injection,
description: 'Test injection SQL'
});
// L'API doit traiter cela comme une chaîne normale, pas d'injection
assert.ok([201, 400].includes(response.statusCode));
if (response.statusCode === 201) {
assert.strictEqual(response.data.data.name, injection); // Stocké tel quel
}
}
});
it('should handle XSS attempts gracefully', async () => {
const xssPayloads = [
'',
'javascript:alert(1)',
'
',
'