seo-generator-server/tests/integration/api-consistency.test.js
StillHammer 4f60de68d6 Fix BatchProcessor initialization and add comprehensive test suite
- Fix BatchProcessor constructor to avoid server blocking during startup
- Add comprehensive integration tests for all modular combinations
- Enhance CLAUDE.md documentation with new test commands
- Update SelectiveLayers configuration for better LLM allocation
- Add AutoReporter system for test automation
- Include production workflow validation tests

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 14:17:49 +08:00

315 lines
12 KiB
JavaScript

import { AutoReporter } from '../reporters/AutoReporter.js';
import assert from 'node:assert';
import { test, describe, before, after } from 'node:test';
import axios from 'axios';
import { requireCommonJS } from '../_helpers/commonjs-bridge.js';
// ========================================
// TESTS D'INTÉGRATION - COHÉRENCE APIs
// Description: Valide que toutes les APIs utilisent le même système
// ========================================
// Imports système
const { ManualServer } = requireCommonJS('modes/ManualServer');
const { sessionManager } = requireCommonJS('StepByStepSessionManager');
// Auto-Reporter Configuration
const autoReporter = new AutoReporter();
describe('🔥 Tests cohérence APIs - Step-by-step vs Generate-simple vs Main', () => {
let server;
let baseURL = 'http://localhost:3002'; // Port test
before(async () => {
// Démarrer serveur test
server = new ManualServer({ port: 3002, wsPort: 8082 });
await server.start();
console.log('🚀 Serveur test démarré sur port 3002');
});
after(async () => {
if (server) {
await server.stop();
console.log('🛑 Serveur test arrêté');
}
});
// ========================================
// TEST: MÊME COMPORTEMENT STEP-BY-STEP vs API SIMPLE
// ========================================
test('🔥 CRITIQUE: Step-by-step et Generate-simple donnent des résultats cohérents', async () => {
console.log('🧪 Test cohérence step-by-step ↔ generate-simple...');
const testKeyword = 'plaque test cohérence';
// ============= TEST GENERATE-SIMPLE =============
console.log('📡 Test /api/generate-simple...');
const simpleResponse = await axios.post(`${baseURL}/api/generate-simple`, {
keyword: testKeyword
});
assert.ok(simpleResponse.data.success, 'Generate-simple doit réussir');
assert.ok(simpleResponse.data.article, 'Doit retourner un article');
const simpleArticle = simpleResponse.data.article;
console.log(`📊 Generate-simple: ${JSON.stringify(simpleArticle).length} chars`);
// ============= TEST STEP-BY-STEP =============
console.log('📡 Test step-by-step workflow...');
// Étape 1: Initialisation
const initResponse = await axios.post(`${baseURL}/api/step-by-step/init`, {
t0: `Guide complet sur ${testKeyword}`,
mc0: testKeyword,
personality: 'Marc'
});
assert.ok(initResponse.data.success, 'Step-by-step init doit réussir');
const sessionId = initResponse.data.sessionId;
console.log(`📊 Session step-by-step: ${sessionId}`);
// Étape 2: Génération initiale
const genResponse = await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId,
stepId: 1,
options: {}
});
assert.ok(genResponse.data.success, 'Step génération initiale doit réussir');
assert.ok(genResponse.data.result.content, 'Doit générer du contenu');
const stepContent = genResponse.data.result.content;
console.log(`📊 Step-by-step: ${Object.keys(stepContent).length} éléments`);
// ============= VALIDATIONS COHÉRENCE =============
// Valider que les deux approches génèrent du contenu
assert.ok(simpleArticle.content, 'Generate-simple doit avoir du contenu');
assert.ok(Object.keys(stepContent).length > 0, 'Step-by-step doit avoir des éléments');
// Valider cohérence du mot-clé
const simpleText = JSON.stringify(simpleArticle).toLowerCase();
const stepText = JSON.stringify(stepContent).toLowerCase();
assert.ok(simpleText.includes(testKeyword.toLowerCase()),
'Generate-simple doit contenir le mot-clé');
assert.ok(stepText.includes(testKeyword.toLowerCase()),
'Step-by-step doit contenir le mot-clé');
console.log('✅ Cohérence step-by-step ↔ generate-simple validée');
}, { timeout: 90000 });
// ========================================
// TEST: OPTIONS SELECTIVESTACK DANS STEP-BY-STEP
// ========================================
test('🔥 CRITIQUE: Options selectiveStack vraiment appliquées dans step-by-step', async () => {
console.log('🧪 Test options selectiveStack step-by-step...');
const testData = {
t0: 'Test options selective',
mc0: 'test selective stack',
personality: 'Marc'
};
// ============= TEST AVEC LIGHTENHANCEMENT =============
const initLight = await axios.post(`${baseURL}/api/step-by-step/init`, testData);
const sessionLight = initLight.data.sessionId;
// Génération initiale
const genLight = await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId: sessionLight,
stepId: 1
});
// Selective avec lightEnhancement
const selectiveLight = await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId: sessionLight,
stepId: 2,
options: { selectiveStack: 'lightEnhancement' }
});
// ============= TEST AVEC STANDARDENHANCEMENT =============
const initStandard = await axios.post(`${baseURL}/api/step-by-step/init`, testData);
const sessionStandard = initStandard.data.sessionId;
// Génération initiale
const genStandard = await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId: sessionStandard,
stepId: 1
});
// Selective avec standardEnhancement
const selectiveStandard = await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId: sessionStandard,
stepId: 2,
options: { selectiveStack: 'standardEnhancement' }
});
// ============= VALIDATIONS =============
assert.ok(selectiveLight.data.success, 'lightEnhancement doit réussir');
assert.ok(selectiveStandard.data.success, 'standardEnhancement doit réussir');
const lightResult = selectiveLight.data.result.content;
const standardResult = selectiveStandard.data.result.content;
console.log(`📊 Light enhancement: ${Object.keys(lightResult).length} éléments`);
console.log(`📊 Standard enhancement: ${Object.keys(standardResult).length} éléments`);
// Les deux doivent avoir du contenu
assert.ok(Object.keys(lightResult).length > 0, 'lightEnhancement doit générer du contenu');
assert.ok(Object.keys(standardResult).length > 0, 'standardEnhancement doit générer du contenu');
// Valider que les options sont bien passées (via logs ou différences)
const lightText = JSON.stringify(lightResult);
const standardText = JSON.stringify(standardResult);
console.log(`📊 Différence contenu: ${Math.abs(lightText.length - standardText.length)} chars`);
console.log('✅ Options selectiveStack appliquées dans step-by-step');
}, { timeout: 120000 });
// ========================================
// TEST: ADVERSARIAL MODE MAPPING
// ========================================
test('🔥 CRITIQUE: Adversarial mode mapping fonctionne dans APIs', async () => {
console.log('🧪 Test adversarial mode mapping...');
const testData = {
t0: 'Test adversarial mapping',
mc0: 'test adversarial mode',
personality: 'Marc'
};
// ============= INIT SESSION =============
const initResponse = await axios.post(`${baseURL}/api/step-by-step/init`, testData);
const sessionId = initResponse.data.sessionId;
// Génération initiale
await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId,
stepId: 1
});
// ============= TEST ADVERSARIAL LIGHT =============
const adversarialResponse = await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId,
stepId: 3, // adversarial step
options: { adversarialMode: 'light' }
});
// ============= VALIDATIONS =============
assert.ok(adversarialResponse.data.success, 'Adversarial mode=light doit réussir');
const result = adversarialResponse.data.result;
assert.ok(result.content, 'Adversarial doit retourner du contenu');
console.log(`📊 Adversarial result: ${Object.keys(result.content).length} éléments`);
// Valider que le mode 'light' est bien mappé vers 'lightDefense'
// (cela sera visible dans les logs de debug si activés)
console.log('✅ Adversarial mode mapping fonctionne');
}, { timeout: 90000 });
// ========================================
// TEST: STATUS ET MONITORING APIS
// ========================================
test('🔥 CRITIQUE: APIs status et monitoring fonctionnent', async () => {
console.log('🧪 Test APIs status et monitoring...');
// ============= TEST STATUS =============
const statusResponse = await axios.get(`${baseURL}/api/status`);
assert.ok(statusResponse.data.success, 'API status doit réussir');
assert.equal(statusResponse.data.mode, 'MANUAL', 'Doit être en mode MANUAL');
assert.equal(statusResponse.data.status, 'running', 'Serveur doit être running');
console.log(`📊 Uptime: ${statusResponse.data.uptime}ms`);
console.log(`📊 Requests: ${statusResponse.data.stats.requests}`);
// ============= TEST STATS =============
const statsResponse = await axios.get(`${baseURL}/api/stats`);
assert.ok(statsResponse.data.success, 'API stats doit réussir');
assert.ok(statsResponse.data.stats, 'Doit retourner des stats');
console.log(`📊 Memory: ${JSON.stringify(statsResponse.data.stats.memory).length} chars`);
// ============= TEST CONFIG MODULAIRE =============
const configResponse = await axios.get(`${baseURL}/api/modulaire-config`);
assert.ok(configResponse.data.success, 'API config doit réussir');
assert.ok(configResponse.data.config.selectiveStacks, 'Doit avoir config selective');
assert.ok(configResponse.data.config.adversarialModes, 'Doit avoir config adversarial');
const selectiveStacks = configResponse.data.config.selectiveStacks;
const adversarialModes = configResponse.data.config.adversarialModes;
console.log(`📊 Selective stacks: ${selectiveStacks.length}`);
console.log(`📊 Adversarial modes: ${adversarialModes.length}`);
// Valider que les stacks importantes sont présentes
const stackNames = selectiveStacks.map(s => s.value);
assert.ok(stackNames.includes('lightEnhancement'), 'lightEnhancement doit être disponible');
assert.ok(stackNames.includes('standardEnhancement'), 'standardEnhancement doit être disponible');
const modeNames = adversarialModes.map(m => m.value);
assert.ok(modeNames.includes('light'), 'Adversarial light doit être disponible');
assert.ok(modeNames.includes('standard'), 'Adversarial standard doit être disponible');
console.log('✅ APIs status et monitoring fonctionnent');
}, { timeout: 30000 });
// ========================================
// TEST: GESTION ERREURS ET ROBUSTESSE
// ========================================
test('🔥 CRITIQUE: Gestion erreurs APIs robuste', async () => {
console.log('🧪 Test gestion erreurs...');
// ============= TEST DONNÉES INVALIDES =============
try {
const invalidResponse = await axios.post(`${baseURL}/api/generate-simple`, {
keyword: '' // Mot-clé vide
});
// Doit retourner une erreur 400
assert.equal(invalidResponse.status, 400, 'Doit retourner erreur 400 pour données invalides');
} catch (error) {
assert.equal(error.response.status, 400, 'Doit capturer erreur 400');
assert.ok(error.response.data.error, 'Doit retourner message d\'erreur');
console.log(`📊 Erreur capturée: ${error.response.data.error}`);
}
// ============= TEST SESSION INEXISTANTE =============
try {
const invalidSession = await axios.post(`${baseURL}/api/step-by-step/execute`, {
sessionId: 'session_inexistante',
stepId: 1
});
// Doit échouer gracieusement
assert.ok(!invalidSession.data.success || invalidSession.status >= 400,
'Session inexistante doit échouer');
} catch (error) {
assert.ok(error.response.status >= 400, 'Doit retourner erreur pour session inexistante');
console.log(`📊 Session inexistante gérée: ${error.response.status}`);
}
console.log('✅ Gestion erreurs robuste');
}, { timeout: 30000 });
});