Some checks failed
SourceFinder CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
SourceFinder CI/CD Pipeline / Unit Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Security Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Integration Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Performance Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Code Coverage Report (push) Has been cancelled
SourceFinder CI/CD Pipeline / Build & Deployment Validation (16.x) (push) Has been cancelled
SourceFinder CI/CD Pipeline / Build & Deployment Validation (18.x) (push) Has been cancelled
SourceFinder CI/CD Pipeline / Build & Deployment Validation (20.x) (push) Has been cancelled
SourceFinder CI/CD Pipeline / Regression Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Security Audit (push) Has been cancelled
SourceFinder CI/CD Pipeline / Notify Results (push) Has been cancelled
- Architecture modulaire avec injection de dépendances - Système de scoring intelligent multi-facteurs (spécificité, fraîcheur, qualité, réutilisation) - Moteur anti-injection 4 couches (preprocessing, patterns, sémantique, pénalités) - API REST complète avec validation et rate limiting - Repository JSON avec index mémoire et backup automatique - Provider LLM modulaire pour génération de contenu - Suite de tests complète (Jest) : * Tests unitaires pour sécurité et scoring * Tests d'intégration API end-to-end * Tests de sécurité avec simulation d'attaques * Tests de performance et charge - Pipeline CI/CD avec GitHub Actions - Logging structuré et monitoring - Configuration ESLint et environnement de test 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
219 lines
7.8 KiB
JavaScript
219 lines
7.8 KiB
JavaScript
/**
|
|
* Script de test pour JSONStockRepository
|
|
* Valide toutes les fonctionnalités avec données réelles
|
|
*/
|
|
require('dotenv').config();
|
|
|
|
const JSONStockRepository = require('./src/implementations/storage/JSONStockRepository');
|
|
const logger = require('./src/utils/logger');
|
|
|
|
// Données de test
|
|
const testArticles = [
|
|
{
|
|
title: "Nouvelle étude sur les Bergers Allemands",
|
|
content: "Une récente étude de l'université vétérinaire de Munich révèle des informations importantes sur la santé des Bergers Allemands...",
|
|
url: "https://centrale-canine.fr/etude-bergers-allemands-2025",
|
|
publishDate: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(), // 5 jours
|
|
sourceType: "premium",
|
|
sourceDomain: "centrale-canine.fr",
|
|
raceCode: "352-1",
|
|
race_tags: ["352-1", "bergers", "grands_chiens"],
|
|
angle_tags: ["sante", "recherche"],
|
|
finalScore: 285,
|
|
freshnessScore: 95,
|
|
qualityScore: 100,
|
|
specificityScore: 100,
|
|
reuseScore: 90
|
|
},
|
|
{
|
|
title: "Conseils dressage pour Golden Retriever",
|
|
content: "Les Golden Retrievers sont des chiens intelligents qui nécessitent une approche particulière pour l'éducation...",
|
|
url: "https://wamiz.com/conseils-dressage-golden-retriever",
|
|
publishDate: new Date(Date.now() - 15 * 24 * 60 * 60 * 1000).toISOString(), // 15 jours
|
|
sourceType: "standard",
|
|
sourceDomain: "wamiz.com",
|
|
raceCode: "111-1",
|
|
race_tags: ["111-1", "retrievers", "grands_chiens"],
|
|
angle_tags: ["education", "comportement"],
|
|
finalScore: 220,
|
|
freshnessScore: 70,
|
|
qualityScore: 80,
|
|
specificityScore: 100,
|
|
reuseScore: 70
|
|
},
|
|
{
|
|
title: "Actualités générales sur la santé canine",
|
|
content: "Les vaccinations annuelles restent essentielles pour maintenir la santé de votre compagnon à quatre pattes...",
|
|
url: "https://30millionsdamis.fr/actualites-sante-canine",
|
|
publishDate: new Date(Date.now() - 45 * 24 * 60 * 60 * 1000).toISOString(), // 45 jours
|
|
sourceType: "fallback",
|
|
sourceDomain: "30millionsdamis.fr",
|
|
raceCode: "general",
|
|
race_tags: ["chiens", "sante_generale"],
|
|
angle_tags: ["sante", "prevention"],
|
|
finalScore: 150,
|
|
freshnessScore: 40,
|
|
qualityScore: 60,
|
|
specificityScore: 25,
|
|
reuseScore: 85
|
|
},
|
|
{
|
|
title: "Législation sur les chiens dangereux",
|
|
content: "Les nouvelles réglementations concernant les chiens de catégorie entrent en vigueur ce mois-ci...",
|
|
url: "https://service-public.fr/legislation-chiens-dangereux",
|
|
publishDate: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString(), // 2 jours
|
|
sourceType: "premium",
|
|
sourceDomain: "service-public.fr",
|
|
raceCode: "legislation",
|
|
race_tags: ["legislation", "securite"],
|
|
angle_tags: ["legislation", "securite"],
|
|
finalScore: 270,
|
|
freshnessScore: 100,
|
|
qualityScore: 100,
|
|
specificityScore: 70,
|
|
reuseScore: 50
|
|
}
|
|
];
|
|
|
|
async function runTests() {
|
|
console.log('🧪 Testing JSONStockRepository...\n');
|
|
|
|
let repository;
|
|
|
|
try {
|
|
// 1. Initialisation
|
|
console.log('📦 1. Initializing repository...');
|
|
repository = new JSONStockRepository({
|
|
dataPath: './data/test-stock',
|
|
backupPath: './data/test-backup'
|
|
});
|
|
|
|
await repository.init();
|
|
console.log('✅ Repository initialized successfully');
|
|
|
|
// 2. Sauvegarde d'articles
|
|
console.log('\n💾 2. Saving test articles...');
|
|
const savedArticles = [];
|
|
|
|
for (const article of testArticles) {
|
|
const saved = await repository.save(article);
|
|
savedArticles.push(saved);
|
|
console.log(`✅ Saved: ${saved.title.substring(0, 50)}... (ID: ${saved.id})`);
|
|
}
|
|
|
|
// 3. Recherche par race
|
|
console.log('\n🔍 3. Testing search by race code...');
|
|
const bergersAllemands = await repository.findByRaceCode('352-1');
|
|
console.log(`✅ Found ${bergersAllemands.length} articles for Bergers Allemands (352-1)`);
|
|
|
|
const goldenRetrievers = await repository.findByRaceCode('111-1', {
|
|
minScore: 200,
|
|
limit: 2
|
|
});
|
|
console.log(`✅ Found ${goldenRetrievers.length} Golden Retrievers with score >= 200`);
|
|
|
|
// 4. Recherche par score
|
|
console.log('\n📊 4. Testing search by score...');
|
|
const highScoreArticles = await repository.findByScore(250);
|
|
console.log(`✅ Found ${highScoreArticles.length} articles with score >= 250`);
|
|
|
|
for (const article of highScoreArticles) {
|
|
console.log(` - ${article.title.substring(0, 40)}... (Score: ${article.finalScore})`);
|
|
}
|
|
|
|
// 5. Recherche par URL (unicité)
|
|
console.log('\n🔗 5. Testing search by URL...');
|
|
const foundByUrl = await repository.findByUrl(testArticles[0].url);
|
|
if (foundByUrl) {
|
|
console.log(`✅ Found article by URL: ${foundByUrl.title.substring(0, 50)}...`);
|
|
}
|
|
|
|
// Test doublon URL
|
|
try {
|
|
await repository.save({
|
|
...testArticles[0],
|
|
id: undefined, // Force nouveau ID
|
|
title: "Article doublon avec même URL"
|
|
});
|
|
console.log('❌ Duplicate URL should not be allowed');
|
|
} catch (error) {
|
|
console.log('✅ Duplicate URL correctly handled');
|
|
}
|
|
|
|
// 6. Mise à jour usage
|
|
console.log('\n📈 6. Testing usage updates...');
|
|
const firstArticle = savedArticles[0];
|
|
await repository.updateUsage(firstArticle.id, {
|
|
usageCount: 3,
|
|
lastUsed: new Date().toISOString(),
|
|
clientId: 'test-client'
|
|
});
|
|
|
|
const updatedArticle = await repository.findById(firstArticle.id);
|
|
console.log(`✅ Updated usage: ${updatedArticle.usageCount} uses, last used: ${updatedArticle.lastUsed}`);
|
|
|
|
// 7. Statistiques
|
|
console.log('\n📊 7. Testing statistics...');
|
|
const stats = await repository.getStats();
|
|
console.log('✅ Repository statistics:');
|
|
console.log(` - Total articles: ${stats.totalArticles}`);
|
|
console.log(` - By source type: ${JSON.stringify(stats.bySourceType)}`);
|
|
console.log(` - By race code: ${JSON.stringify(stats.byRaceCode)}`);
|
|
console.log(` - Average score: ${stats.avgScore}`);
|
|
console.log(` - Storage: ${stats.storage.totalSizeMB}MB`);
|
|
console.log(` - Operations: ${stats.operations}`);
|
|
console.log(` - Errors: ${stats.errors}`);
|
|
|
|
// 8. Backup
|
|
console.log('\n💾 8. Testing backup...');
|
|
await repository.createBackup();
|
|
console.log('✅ Backup created successfully');
|
|
|
|
// 9. Cleanup
|
|
console.log('\n🧹 9. Testing cleanup...');
|
|
const deletedCount = await repository.cleanup({
|
|
sourceTypes: ['fallback'], // Supprimer articles fallback
|
|
olderThan: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // Plus de 30 jours
|
|
});
|
|
console.log(`✅ Cleaned up ${deletedCount} articles`);
|
|
|
|
// 10. Test recherche complexe
|
|
console.log('\n🔍 10. Testing complex search...');
|
|
const complexResults = await repository.findByRaceCode('352-1', {
|
|
minScore: 200,
|
|
maxAge: 10, // Derniers 10 jours
|
|
sourceTypes: ['premium'],
|
|
sortBy: 'finalScore',
|
|
sortOrder: 'desc',
|
|
limit: 5
|
|
});
|
|
console.log(`✅ Complex search returned ${complexResults.length} articles`);
|
|
|
|
// 11. Final stats
|
|
console.log('\n📊 11. Final statistics...');
|
|
const finalStats = await repository.getStats();
|
|
console.log('✅ Final repository state:');
|
|
console.log(` - Total articles: ${finalStats.totalArticles}`);
|
|
console.log(` - Memory usage: ~${finalStats.memoryUsage} bytes`);
|
|
console.log(` - Operations performed: ${finalStats.operations}`);
|
|
|
|
console.log('\n🎉 All tests passed successfully!');
|
|
|
|
} catch (error) {
|
|
console.error('\n❌ Test failed:', error);
|
|
console.error(error.stack);
|
|
} finally {
|
|
// Cleanup
|
|
if (repository) {
|
|
await repository.close();
|
|
console.log('\n🔒 Repository closed');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Exécuter les tests
|
|
if (require.main === module) {
|
|
runTests().catch(console.error);
|
|
}
|
|
|
|
module.exports = { runTests, testArticles }; |