- 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>
315 lines
12 KiB
JavaScript
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 });
|
|
|
|
}); |