seogeneratorserver/tests/llm/pipeline-dryrun.test.js
StillHammer dbf1a3de8c Add technical plan for multi-format export system
Added plan.md with complete architecture for format-agnostic content generation:
- Support for Markdown, HTML, Plain Text, JSON formats
- New FormatExporter module with neutral data structure
- Integration strategy with existing ContentAssembly and ArticleStorage
- Bonus features: SEO metadata generation, readability scoring, WordPress Gutenberg format
- Implementation roadmap with 4 phases (6h total estimated)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 16:14:29 +08:00

82 lines
3.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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('ContentGeneration');
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 ContentGeneration = 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 ContentGeneration accepte un LLM param, on lutilise, sinon on simule simple:
const parts = await (ContentGeneration.generateArticleParts
? ContentGeneration.generateArticleParts({ inputs, elements, llm })
: (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');
});