/** * Script de test des fonctionnalités admin * Test de connexion, statistiques et export marketing */ const API_URL = 'http://localhost:4000/api'; // Couleurs pour console const colors = { green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', reset: '\x1b[0m' }; function log(color, message) { console.log(`${color}${message}${colors.reset}`); } let authToken = null; // 1. Test de connexion admin async function testAdminLogin() { log(colors.blue, '\n========================================'); log(colors.blue, '1. TEST DE CONNEXION ADMIN'); log(colors.blue, '========================================\n'); try { const response = await fetch(`${API_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: 'admin@thetiptop.com', password: 'Admin123!' }) }); const data = await response.json(); if (response.ok && data.success) { authToken = data.token; log(colors.green, '✅ Connexion admin réussie'); log(colors.green, ` Token: ${authToken.substring(0, 50)}...`); log(colors.green, ` Role: ${data.user.role}`); log(colors.green, ` Email: ${data.user.email}`); log(colors.green, ` Nom: ${data.user.firstName} ${data.user.lastName}`); return true; } else { log(colors.red, '❌ Échec de la connexion admin'); log(colors.red, ` Message: ${data.message || 'Erreur inconnue'}`); return false; } } catch (error) { log(colors.red, `❌ Erreur lors de la connexion: ${error.message}`); return false; } } // 2. Test des statistiques globales async function testStatistics() { log(colors.blue, '\n========================================'); log(colors.blue, '2. TEST DES STATISTIQUES GLOBALES'); log(colors.blue, '========================================\n'); if (!authToken) { log(colors.red, '❌ Token manquant - connexion requise'); return false; } try { const response = await fetch(`${API_URL}/admin/statistics`, { method: 'GET', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json', } }); const data = await response.json(); if (response.ok && data.success) { log(colors.green, '✅ Statistiques récupérées avec succès\n'); // Statistiques utilisateurs log(colors.yellow, '👥 UTILISATEURS:'); log(colors.reset, ` Total: ${data.data.users.total}`); log(colors.reset, ` Clients: ${data.data.users.clients}`); log(colors.reset, ` Employés: ${data.data.users.employees}`); log(colors.reset, ` Admins: ${data.data.users.admins}`); log(colors.reset, ` Emails vérifiés: ${data.data.users.verifiedEmails}`); // Statistiques tickets log(colors.yellow, '\n🎫 TICKETS:'); log(colors.reset, ` Total: ${data.data.tickets.total}`); log(colors.reset, ` Distribués: ${data.data.tickets.distributed}`); log(colors.reset, ` Utilisés: ${data.data.tickets.used}`); log(colors.reset, ` En attente: ${data.data.tickets.pending}`); log(colors.reset, ` Réclamés: ${data.data.tickets.claimed}`); log(colors.reset, ` Rejetés: ${data.data.tickets.rejected}`); // Statistiques lots log(colors.yellow, '\n🎁 LOTS:'); log(colors.reset, ` Total types: ${data.data.prizes.total}`); log(colors.reset, ` Actifs: ${data.data.prizes.active}`); log(colors.reset, ` Stock total: ${data.data.prizes.totalStock}`); log(colors.reset, ` Distribués: ${data.data.prizes.distributed}`); // Distribution par catégorie if (data.data.prizes.byCategory && data.data.prizes.byCategory.length > 0) { log(colors.yellow, '\n Distribution par catégorie:'); data.data.prizes.byCategory.forEach(category => { log(colors.reset, ` - ${category.prizeName}: ${category.count} (${category.percentage.toFixed(2)}%)`); }); } // Démographie if (data.data.demographics) { log(colors.yellow, '\n📊 DÉMOGRAPHIE:'); if (data.data.demographics.gender) { log(colors.yellow, ' Par sexe:'); log(colors.reset, ` - Hommes: ${data.data.demographics.gender.male}`); log(colors.reset, ` - Femmes: ${data.data.demographics.gender.female}`); log(colors.reset, ` - Autre: ${data.data.demographics.gender.other}`); log(colors.reset, ` - Non spécifié: ${data.data.demographics.gender.notSpecified}`); } if (data.data.demographics.ageRanges && data.data.demographics.ageRanges.length > 0) { log(colors.yellow, '\n Par tranche d\'âge:'); data.data.demographics.ageRanges.forEach(range => { log(colors.reset, ` - ${range.range} ans: ${range.count} (${range.percentage.toFixed(2)}%)`); }); } if (data.data.demographics.topCities && data.data.demographics.topCities.length > 0) { log(colors.yellow, '\n Top 10 villes:'); data.data.demographics.topCities.forEach((city, index) => { log(colors.reset, ` ${index + 1}. ${city.city}: ${city.count} (${city.percentage.toFixed(2)}%)`); }); } } // Paramètres du jeu if (data.data.game) { log(colors.yellow, '\n🎮 JEU:'); log(colors.reset, ` Début: ${new Date(data.data.game.start_date).toLocaleDateString()}`); log(colors.reset, ` Fin: ${new Date(data.data.game.end_date).toLocaleDateString()}`); log(colors.reset, ` Actif: ${data.data.game.is_active ? 'Oui' : 'Non'}`); log(colors.reset, ` Tickets générés: ${data.data.game.tickets_generated} / ${data.data.game.total_tickets}`); } return true; } else { log(colors.red, '❌ Échec de récupération des statistiques'); log(colors.red, ` Status: ${response.status}`); log(colors.red, ` Message: ${data.message || 'Erreur inconnue'}`); return false; } } catch (error) { log(colors.red, `❌ Erreur lors de la récupération des statistiques: ${error.message}`); return false; } } // 3. Test des statistiques marketing async function testMarketingStats() { log(colors.blue, '\n========================================'); log(colors.blue, '3. TEST DES STATISTIQUES MARKETING'); log(colors.blue, '========================================\n'); if (!authToken) { log(colors.red, '❌ Token manquant - connexion requise'); return false; } try { const response = await fetch(`${API_URL}/admin/marketing/stats`, { method: 'GET', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json', } }); const data = await response.json(); if (response.ok && data.success) { log(colors.green, '✅ Statistiques marketing récupérées\n'); log(colors.yellow, '📈 STATISTIQUES MARKETING:'); log(colors.reset, ` Total clients: ${data.data.totalClients}`); log(colors.reset, ` Participants actifs: ${data.data.activeParticipants}`); log(colors.reset, ` Participants inactifs: ${data.data.inactiveParticipants}`); log(colors.reset, ` Gagnants: ${data.data.winners}`); log(colors.reset, ` Non-gagnants: ${data.data.nonWinners}`); if (data.data.geographicDistribution && data.data.geographicDistribution.length > 0) { log(colors.yellow, '\n Distribution géographique (Top 5):'); data.data.geographicDistribution.slice(0, 5).forEach((city, index) => { log(colors.reset, ` ${index + 1}. ${city.city}: ${city.count}`); }); } return true; } else { log(colors.red, '❌ Échec de récupération des stats marketing'); log(colors.red, ` Status: ${response.status}`); log(colors.red, ` Message: ${data.message || 'Erreur inconnue'}`); return false; } } catch (error) { log(colors.red, `❌ Erreur: ${error.message}`); return false; } } // 4. Test de l'export marketing async function testMarketingExport() { log(colors.blue, '\n========================================'); log(colors.blue, '4. TEST DE L\'EXPORT MARKETING'); log(colors.blue, '========================================\n'); if (!authToken) { log(colors.red, '❌ Token manquant - connexion requise'); return false; } try { // Test 1: Export de tous les participants actifs log(colors.yellow, 'Test 1: Export des participants actifs'); const response1 = await fetch(`${API_URL}/admin/marketing/export`, { method: 'POST', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ hasPlayed: true }) }); const data1 = await response1.json(); if (response1.ok && data1.success) { log(colors.green, `✅ Export réussi: ${data1.data.length} participants actifs`); if (data1.data.length > 0) { const sample = data1.data[0]; log(colors.reset, ' Exemple de données exportées:'); log(colors.reset, ` - Email: ${sample.email}`); log(colors.reset, ` - Nom: ${sample.first_name} ${sample.last_name}`); log(colors.reset, ` - Tickets joués: ${sample.tickets_played}`); log(colors.reset, ` - Lots gagnés: ${sample.prizes_won}`); } } else { log(colors.red, '❌ Échec export participants actifs'); log(colors.red, ` Message: ${data1.message || 'Erreur inconnue'}`); } // Test 2: Export des gagnants uniquement log(colors.yellow, '\nTest 2: Export des gagnants uniquement'); const response2 = await fetch(`${API_URL}/admin/marketing/export`, { method: 'POST', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ hasWon: true }) }); const data2 = await response2.json(); if (response2.ok && data2.success) { log(colors.green, `✅ Export réussi: ${data2.data.length} gagnants`); } else { log(colors.red, '❌ Échec export gagnants'); } // Test 3: Export avec filtre email vérifié log(colors.yellow, '\nTest 3: Export emails vérifiés'); const response3 = await fetch(`${API_URL}/admin/marketing/export`, { method: 'POST', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ verified: true }) }); const data3 = await response3.json(); if (response3.ok && data3.success) { log(colors.green, `✅ Export réussi: ${data3.data.length} utilisateurs vérifiés`); } else { log(colors.red, '❌ Échec export vérifiés'); } return true; } catch (error) { log(colors.red, `❌ Erreur lors de l'export: ${error.message}`); return false; } } // 5. Test du rapport marketing async function testMarketingReport() { log(colors.blue, '\n========================================'); log(colors.blue, '5. TEST DU RAPPORT MARKETING'); log(colors.blue, '========================================\n'); if (!authToken) { log(colors.red, '❌ Token manquant - connexion requise'); return false; } try { const response = await fetch(`${API_URL}/admin/marketing/report`, { method: 'GET', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json', } }); const data = await response.json(); if (response.ok && data.success) { log(colors.green, '✅ Rapport marketing généré\n'); if (data.data.globalStats) { log(colors.yellow, '📊 STATISTIQUES GLOBALES:'); log(colors.reset, ` Total clients: ${data.data.globalStats.totalClients}`); log(colors.reset, ` Participants actifs: ${data.data.globalStats.activeParticipants}`); log(colors.reset, ` Taux de participation: ${data.data.globalStats.participationRate?.toFixed(2)}%`); log(colors.reset, ` Taux de conversion: ${data.data.globalStats.conversionRate?.toFixed(2)}%`); } if (data.data.recommendations && data.data.recommendations.length > 0) { log(colors.yellow, '\n💡 RECOMMANDATIONS:'); data.data.recommendations.forEach(rec => { log(colors.reset, ` - ${rec}`); }); } return true; } else { log(colors.red, '❌ Échec de génération du rapport'); log(colors.red, ` Status: ${response.status}`); log(colors.red, ` Message: ${data.message || 'Erreur inconnue'}`); return false; } } catch (error) { log(colors.red, `❌ Erreur: ${error.message}`); return false; } } // 6. Test des participants éligibles au tirage async function testEligibleParticipants() { log(colors.blue, '\n========================================'); log(colors.blue, '6. TEST DES PARTICIPANTS ÉLIGIBLES'); log(colors.blue, '========================================\n'); if (!authToken) { log(colors.red, '❌ Token manquant - connexion requise'); return false; } try { const response = await fetch(`${API_URL}/draw/eligible-participants?minTickets=1`, { method: 'GET', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'application/json', } }); const data = await response.json(); if (response.ok && data.success) { log(colors.green, `✅ Participants éligibles: ${data.data.length}\n`); if (data.data.length > 0) { log(colors.yellow, ' Top 5 participants:'); data.data.slice(0, 5).forEach((participant, index) => { log(colors.reset, ` ${index + 1}. ${participant.email} - ${participant.tickets_played} tickets joués`); }); } return true; } else { log(colors.red, '❌ Échec de récupération des participants'); log(colors.red, ` Status: ${response.status}`); log(colors.red, ` Message: ${data.message || 'Erreur inconnue'}`); return false; } } catch (error) { log(colors.red, `❌ Erreur: ${error.message}`); return false; } } // Exécution de tous les tests async function runAllTests() { log(colors.green, '\n╔════════════════════════════════════════╗'); log(colors.green, '║ TESTS DES FONCTIONNALITÉS ADMIN ║'); log(colors.green, '╚════════════════════════════════════════╝'); const results = { login: false, statistics: false, marketingStats: false, marketingExport: false, marketingReport: false, eligibleParticipants: false }; // Test 1: Connexion results.login = await testAdminLogin(); if (!results.login) { log(colors.red, '\n❌ Tests arrêtés - échec de la connexion admin'); process.exit(1); } // Test 2: Statistiques results.statistics = await testStatistics(); // Test 3: Stats marketing results.marketingStats = await testMarketingStats(); // Test 4: Export marketing results.marketingExport = await testMarketingExport(); // Test 5: Rapport marketing results.marketingReport = await testMarketingReport(); // Test 6: Participants éligibles results.eligibleParticipants = await testEligibleParticipants(); // Résumé final log(colors.blue, '\n========================================'); log(colors.blue, 'RÉSUMÉ DES TESTS'); log(colors.blue, '========================================\n'); const allPassed = Object.values(results).every(r => r === true); Object.entries(results).forEach(([test, passed]) => { const icon = passed ? '✅' : '❌'; const color = passed ? colors.green : colors.red; log(color, `${icon} ${test}`); }); log(colors.blue, '\n========================================\n'); if (allPassed) { log(colors.green, '🎉 TOUS LES TESTS SONT PASSÉS !'); log(colors.green, '\n✅ Les fonctionnalités admin sont opérationnelles:'); log(colors.green, ' - Connexion admin'); log(colors.green, ' - Visualisation des statistiques'); log(colors.green, ' - Export des données pour emailing'); log(colors.green, ' - Rapport marketing'); log(colors.green, ' - Gestion du tirage au sort'); } else { log(colors.red, '⚠️ CERTAINS TESTS ONT ÉCHOUÉ'); log(colors.yellow, '\nVérifiez les logs ci-dessus pour plus de détails.'); } process.exit(allPassed ? 0 : 1); } // Lancer les tests runAllTests().catch(error => { log(colors.red, `\n❌ Erreur fatale: ${error.message}`); console.error(error); process.exit(1); });