seo-generator-server/tests/llm/pipeline-dryrun.test.js

82 lines
3.2 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert';
import { safeImport } from '../_helpers/path.js';
import { MemoryArticleStorage } from '../_helpers/memoryStorage.js';
import { MockLLMManager } from '../_helpers/mockLLMManager.js';
function skip(msg) { console.warn('[SKIP]', msg); }
test('Pipeline dry-run with mock LLM returns structured article', async (t) => {
const extr = safeImport('ElementExtraction');
const gen = safeImport('selective-enhancement/SelectiveUtils');
const asm = safeImport('ContentAssembly');
const enh = safeImport('SelectiveEnhancement');
const miss = safeImport('MissingKeywords');
const utils= safeImport('Utils');
const stor = new MemoryArticleStorage();
const llm = new MockLLMManager();
if (![extr,gen,asm,enh,miss].every(r=>r.ok)) {
skip('One or more pipeline modules missing; dry-run skipped.');
return;
}
const ElementExtraction = extr.mod;
const SelectiveUtils = gen.mod;
const ContentAssembly = asm.mod;
const SelectiveEnh = enh.mod;
const MissingKeywords = miss.mod;
// Inputs minimaux (adapte selon tes contrats)
const inputs = {
instructions: 'Write about hunting jackets: materials, weatherproofing, sizes.',
persona: { name: 'Persona A', tone: 'pragmatic' },
template: '<article><h1>{{title}}</h1>{{body}}</article>',
seed: 42
};
// Étape 1: extraction
const elements = await (ElementExtraction.extractElements
? ElementExtraction.extractElements(inputs)
: { topics: ['materials', 'weatherproofing', 'sizes'] });
assert.ok(elements, 'elements should be produced');
// Étape 2: génération (mock via injection simple si API supporte un client)
// Si SelectiveUtils accepte un LLM param, on l'utilise, sinon on simule simple:
const parts = await (SelectiveUtils.generateSimple
? SelectiveUtils.generateSimple(elements, inputs)
: (Array.isArray(elements.topics) ? elements.topics : Object.keys(elements))
.map(t => ({ key:String(t), text:`MOCK SECTION ${t}` })));
assert.ok(parts && Array.isArray(parts), 'parts array expected');
assert.ok(parts.length > 0, 'non-empty parts');
// Étape 3: enhancement sélectif (facultatif)
const enhanced = await (SelectiveEnh.enhanceParts
? SelectiveEnh.enhanceParts({ parts, llm })
: parts);
assert.ok(enhanced && Array.isArray(enhanced), 'enhanced parts array');
// Étape 4: missing keywords
const completed = await (MissingKeywords.fillMissingKeywords
? MissingKeywords.fillMissingKeywords({ parts: enhanced, targetKeywords:['chasse','imperméable'] , llm })
: enhanced);
// Étape 5: assemblage
const html = await (ContentAssembly.assembleArticle
? ContentAssembly.assembleArticle({ template: inputs.template, parts: completed, meta:{title:'Veste de chasse: guide complet'} })
: `<article>${completed.map(p=>`<section>${p.text}</section>`).join('')}</article>`);
assert.equal(typeof html, 'string');
assert.ok(html.includes('<article'), 'html should be article-like');
// “Stockage final” simulé
const key = JSON.stringify(inputs); // simplifié
await stor.writeFinal(key, { html });
assert.ok(await stor.hasFinal(key), 'final should be stored');
});