- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
426 lines
18 KiB
Python
426 lines
18 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test des États Visuels Canvas VWB - Validation des animations et indicateurs
|
|
Auteur : Dom, Alice, Kiro - 10 janvier 2026
|
|
|
|
Ce script teste l'implémentation des états visuels sur le Canvas pour les actions VWB,
|
|
vérifiant les animations, indicateurs de progression et feedback en temps réel.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import time
|
|
from pathlib import Path
|
|
from typing import Dict, List, Any, Optional
|
|
|
|
class TestEtatsVisuelsCanvasVWB:
|
|
"""Test des états visuels Canvas VWB"""
|
|
|
|
def __init__(self):
|
|
self.resultats_test = {
|
|
'composants_canvas': {},
|
|
'animations_css': {},
|
|
'etats_visuels': {},
|
|
'integration_vwb': {},
|
|
'performance': {},
|
|
'score_global': 0
|
|
}
|
|
|
|
def afficher_banniere(self):
|
|
"""Afficher la bannière de test"""
|
|
print("🎨" + "="*70 + "🎨")
|
|
print("🚀 TEST DES ÉTATS VISUELS CANVAS VWB")
|
|
print("="*74)
|
|
print("📅 Date : 10 janvier 2026")
|
|
print("👥 Auteur : Dom, Alice, Kiro")
|
|
print("🎯 Objectif : Valider les animations et états visuels VWB")
|
|
print("="*74)
|
|
print()
|
|
|
|
def verifier_composants_canvas(self) -> bool:
|
|
"""Vérifier les composants Canvas VWB"""
|
|
print("🔍 Vérification des composants Canvas...")
|
|
|
|
composants_requis = {
|
|
'StepNode Principal': {
|
|
'path': 'visual_workflow_builder/frontend/src/components/Canvas/StepNode.tsx',
|
|
'checks': ['VWBStepNodeExtension', 'useVWBExecutionService', 'isVWBAction']
|
|
},
|
|
'Extension VWB StepNode': {
|
|
'path': 'visual_workflow_builder/frontend/src/components/Canvas/VWBStepNodeExtension.tsx',
|
|
'checks': ['VWBStepNodeExtension', 'pulseAnimation', 'glowAnimation', 'successPulse']
|
|
},
|
|
}
|
|
|
|
composants_valides = 0
|
|
|
|
for nom, config in composants_requis.items():
|
|
chemin = Path(config['path'])
|
|
|
|
if not chemin.exists():
|
|
print(f"❌ {nom} manquant: {chemin}")
|
|
self.resultats_test['composants_canvas'][nom] = False
|
|
continue
|
|
|
|
try:
|
|
with open(chemin, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
checks_reussis = 0
|
|
for check in config['checks']:
|
|
if check in contenu:
|
|
checks_reussis += 1
|
|
else:
|
|
print(f" ❌ {check} manquant dans {nom}")
|
|
|
|
if checks_reussis == len(config['checks']):
|
|
print(f"✅ {nom} validé ({checks_reussis}/{len(config['checks'])})")
|
|
self.resultats_test['composants_canvas'][nom] = True
|
|
composants_valides += 1
|
|
else:
|
|
print(f"❌ {nom} incomplet ({checks_reussis}/{len(config['checks'])})")
|
|
self.resultats_test['composants_canvas'][nom] = False
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur lecture {nom}: {e}")
|
|
self.resultats_test['composants_canvas'][nom] = False
|
|
|
|
return composants_valides == len(composants_requis)
|
|
|
|
def verifier_animations_css(self) -> bool:
|
|
"""Vérifier les animations CSS-in-JS"""
|
|
print("\n🔍 Vérification des animations CSS...")
|
|
|
|
extension_file = Path("visual_workflow_builder/frontend/src/components/Canvas/VWBStepNodeExtension.tsx")
|
|
if not extension_file.exists():
|
|
print("❌ Extension VWB StepNode manquante")
|
|
return False
|
|
|
|
try:
|
|
with open(extension_file, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
# Vérifications des animations
|
|
animations_requises = [
|
|
('pulseAnimation', 'Animation de pulsation'),
|
|
('glowAnimation', 'Animation de lueur'),
|
|
('successPulse', 'Animation de succès'),
|
|
('errorShake', 'Animation d\'erreur'),
|
|
('keyframes', 'Définitions keyframes'),
|
|
('LinearProgress', 'Barre de progression'),
|
|
('CircularProgress', 'Indicateur circulaire'),
|
|
('Fade', 'Animation de fondu'),
|
|
('Zoom', 'Animation de zoom'),
|
|
]
|
|
|
|
animations_trouvees = 0
|
|
for animation, description in animations_requises:
|
|
if animation in contenu:
|
|
print(f" ✅ {description}")
|
|
animations_trouvees += 1
|
|
else:
|
|
print(f" ❌ {description} manquante")
|
|
|
|
self.resultats_test['animations_css']['total'] = len(animations_requises)
|
|
self.resultats_test['animations_css']['trouvees'] = animations_trouvees
|
|
self.resultats_test['animations_css']['valide'] = animations_trouvees >= len(animations_requises) * 0.8
|
|
|
|
if animations_trouvees >= len(animations_requises) * 0.8:
|
|
print(f"✅ Animations CSS validées ({animations_trouvees}/{len(animations_requises)})")
|
|
return True
|
|
else:
|
|
print(f"❌ Animations incomplètes ({animations_trouvees}/{len(animations_requises)})")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur vérification animations: {e}")
|
|
return False
|
|
|
|
def verifier_etats_visuels(self) -> bool:
|
|
"""Vérifier les états visuels"""
|
|
print("\n🔍 Vérification des états visuels...")
|
|
|
|
extension_file = Path("visual_workflow_builder/frontend/src/components/Canvas/VWBStepNodeExtension.tsx")
|
|
if not extension_file.exists():
|
|
print("❌ Extension VWB StepNode manquante")
|
|
return False
|
|
|
|
try:
|
|
with open(extension_file, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
# Vérifications des états visuels
|
|
etats_requis = [
|
|
('StepExecutionState.IDLE', 'État inactif'),
|
|
('StepExecutionState.RUNNING', 'État en cours'),
|
|
('StepExecutionState.SUCCESS', 'État succès'),
|
|
('StepExecutionState.ERROR', 'État erreur'),
|
|
('StepExecutionState.PAUSED', 'État en pause'),
|
|
('vwbExecutionStateColors', 'Couleurs d\'état'),
|
|
('vwbExecutionStateIcons', 'Icônes d\'état'),
|
|
('getBorderColor', 'Couleur de bordure dynamique'),
|
|
('getBackgroundColor', 'Couleur de fond dynamique'),
|
|
('getAnimationStyles', 'Styles d\'animation'),
|
|
]
|
|
|
|
etats_trouves = 0
|
|
for etat, description in etats_requis:
|
|
if etat in contenu:
|
|
print(f" ✅ {description}")
|
|
etats_trouves += 1
|
|
else:
|
|
print(f" ❌ {description} manquant")
|
|
|
|
self.resultats_test['etats_visuels']['total'] = len(etats_requis)
|
|
self.resultats_test['etats_visuels']['trouves'] = etats_trouves
|
|
self.resultats_test['etats_visuels']['valide'] = etats_trouves >= len(etats_requis) * 0.8
|
|
|
|
if etats_trouves >= len(etats_requis) * 0.8:
|
|
print(f"✅ États visuels validés ({etats_trouves}/{len(etats_requis)})")
|
|
return True
|
|
else:
|
|
print(f"❌ États visuels incomplets ({etats_trouves}/{len(etats_requis)})")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur vérification états: {e}")
|
|
return False
|
|
|
|
def verifier_integration_vwb(self) -> bool:
|
|
"""Vérifier l'intégration VWB"""
|
|
print("\n🔍 Vérification de l'intégration VWB...")
|
|
|
|
stepnode_file = Path("visual_workflow_builder/frontend/src/components/Canvas/StepNode.tsx")
|
|
if not stepnode_file.exists():
|
|
print("❌ StepNode principal manquant")
|
|
return False
|
|
|
|
try:
|
|
with open(stepnode_file, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
# Vérifications d'intégration
|
|
integrations_requises = [
|
|
('VWBStepNodeExtension', 'Import extension VWB'),
|
|
('useVWBExecutionService', 'Service VWB'),
|
|
('isVWBStep', 'Détection étapes VWB'),
|
|
('isVWBAction', 'Variable de détection'),
|
|
('tempStep', 'Objet Step temporaire'),
|
|
('StandardStepNode', 'Composant standard'),
|
|
]
|
|
|
|
integrations_trouvees = 0
|
|
for integration, description in integrations_requises:
|
|
if integration in contenu:
|
|
print(f" ✅ {description}")
|
|
integrations_trouvees += 1
|
|
else:
|
|
print(f" ❌ {description} manquant")
|
|
|
|
self.resultats_test['integration_vwb']['total'] = len(integrations_requises)
|
|
self.resultats_test['integration_vwb']['trouvees'] = integrations_trouvees
|
|
self.resultats_test['integration_vwb']['valide'] = integrations_trouvees >= len(integrations_requises) * 0.7
|
|
|
|
if integrations_trouvees >= len(integrations_requises) * 0.7:
|
|
print(f"✅ Intégration VWB validée ({integrations_trouvees}/{len(integrations_requises)})")
|
|
return True
|
|
else:
|
|
print(f"❌ Intégration VWB incomplète ({integrations_trouvees}/{len(integrations_requises)})")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur vérification intégration: {e}")
|
|
return False
|
|
|
|
def verifier_performance(self) -> bool:
|
|
"""Vérifier les optimisations de performance"""
|
|
print("\n🔍 Vérification des optimisations de performance...")
|
|
|
|
# Vérifier les mémorisations et optimisations
|
|
fichiers_a_verifier = [
|
|
'visual_workflow_builder/frontend/src/components/Canvas/StepNode.tsx',
|
|
'visual_workflow_builder/frontend/src/components/Canvas/VWBStepNodeExtension.tsx'
|
|
]
|
|
|
|
optimisations_trouvees = 0
|
|
optimisations_totales = 0
|
|
|
|
for fichier in fichiers_a_verifier:
|
|
if not Path(fichier).exists():
|
|
continue
|
|
|
|
try:
|
|
with open(fichier, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
# Vérifications de performance
|
|
checks_performance = [
|
|
('memo', 'Mémorisation React'),
|
|
('useCallback', 'Callbacks mémorisés'),
|
|
('useMemo', 'Valeurs mémorisées'),
|
|
('transition', 'Transitions CSS optimisées'),
|
|
]
|
|
|
|
for check, description in checks_performance:
|
|
optimisations_totales += 1
|
|
if check in contenu:
|
|
print(f" ✅ {description} dans {Path(fichier).name}")
|
|
optimisations_trouvees += 1
|
|
else:
|
|
print(f" ❌ {description} manquant dans {Path(fichier).name}")
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur lecture {fichier}: {e}")
|
|
|
|
self.resultats_test['performance']['total'] = optimisations_totales
|
|
self.resultats_test['performance']['trouvees'] = optimisations_trouvees
|
|
self.resultats_test['performance']['valide'] = optimisations_trouvees >= optimisations_totales * 0.6
|
|
|
|
if optimisations_trouvees >= optimisations_totales * 0.6:
|
|
print(f"✅ Optimisations de performance validées ({optimisations_trouvees}/{optimisations_totales})")
|
|
return True
|
|
else:
|
|
print(f"❌ Optimisations insuffisantes ({optimisations_trouvees}/{optimisations_totales})")
|
|
return False
|
|
|
|
def calculer_score_global(self) -> int:
|
|
"""Calculer le score global"""
|
|
score = 0
|
|
total = 5
|
|
|
|
if self.resultats_test['composants_canvas'].get('StepNode Principal', False) and \
|
|
self.resultats_test['composants_canvas'].get('Extension VWB StepNode', False):
|
|
score += 1
|
|
|
|
if self.resultats_test['animations_css'].get('valide', False):
|
|
score += 1
|
|
|
|
if self.resultats_test['etats_visuels'].get('valide', False):
|
|
score += 1
|
|
|
|
if self.resultats_test['integration_vwb'].get('valide', False):
|
|
score += 1
|
|
|
|
if self.resultats_test['performance'].get('valide', False):
|
|
score += 1
|
|
|
|
self.resultats_test['score_global'] = score
|
|
return score
|
|
|
|
def generer_rapport_final(self):
|
|
"""Générer le rapport final"""
|
|
print("\n" + "🎯" + "="*70 + "🎯")
|
|
print("📊 RAPPORT FINAL - ÉTATS VISUELS CANVAS VWB")
|
|
print("="*74)
|
|
|
|
score = self.resultats_test['score_global']
|
|
total = 5
|
|
pourcentage = (score / total) * 100
|
|
|
|
print(f"\n🎯 SCORE GLOBAL: {score}/{total} ({pourcentage:.1f}%)")
|
|
|
|
if score == total:
|
|
print("🎉 ÉTATS VISUELS COMPLÈTEMENT IMPLÉMENTÉS!")
|
|
print("✅ Toutes les animations et indicateurs VWB sont opérationnels")
|
|
elif score >= 4:
|
|
print("✅ ÉTATS VISUELS MAJORITAIREMENT IMPLÉMENTÉS")
|
|
print("⚠️ Quelques ajustements mineurs possibles")
|
|
else:
|
|
print("❌ IMPLÉMENTATION INCOMPLÈTE")
|
|
print("🔧 Des corrections importantes sont nécessaires")
|
|
|
|
print(f"\n📋 DÉTAILS DE L'IMPLÉMENTATION:")
|
|
|
|
composants_valides = sum(1 for v in self.resultats_test['composants_canvas'].values() if v)
|
|
print(f" Composants Canvas: {composants_valides}/2")
|
|
|
|
animations_score = self.resultats_test['animations_css'].get('trouvees', 0)
|
|
animations_total = self.resultats_test['animations_css'].get('total', 9)
|
|
print(f" Animations CSS: {animations_score}/{animations_total}")
|
|
|
|
etats_score = self.resultats_test['etats_visuels'].get('trouves', 0)
|
|
etats_total = self.resultats_test['etats_visuels'].get('total', 10)
|
|
print(f" États Visuels: {etats_score}/{etats_total}")
|
|
|
|
integration_score = self.resultats_test['integration_vwb'].get('trouvees', 0)
|
|
integration_total = self.resultats_test['integration_vwb'].get('total', 6)
|
|
print(f" Intégration VWB: {integration_score}/{integration_total}")
|
|
|
|
perf_score = self.resultats_test['performance'].get('trouvees', 0)
|
|
perf_total = self.resultats_test['performance'].get('total', 8)
|
|
print(f" Optimisations: {perf_score}/{perf_total}")
|
|
|
|
print(f"\n🎯 PROCHAINES ÉTAPES:")
|
|
if score == total:
|
|
print(" 🚀 Continuer avec la Tâche 3.1.3 : Intégration Evidence Viewer")
|
|
print(" 📋 Implémenter l'affichage des Evidence pendant l'exécution")
|
|
else:
|
|
print(" 🔧 Corriger les composants manquants ou incomplets")
|
|
print(" 🎨 Améliorer les animations et états visuels")
|
|
|
|
print(f"\n📄 Rapport sauvegardé dans: tests/results/etats_visuels_canvas_vwb_10jan2026.json")
|
|
|
|
def sauvegarder_resultats(self):
|
|
"""Sauvegarder les résultats"""
|
|
resultats_complets = {
|
|
'timestamp': time.time(),
|
|
'date': time.strftime('%Y-%m-%d %H:%M:%S'),
|
|
'test': self.resultats_test,
|
|
'statut': 'SUCCÈS' if self.resultats_test['score_global'] >= 4 else 'PARTIEL'
|
|
}
|
|
|
|
os.makedirs('tests/results', exist_ok=True)
|
|
|
|
with open('tests/results/etats_visuels_canvas_vwb_10jan2026.json', 'w', encoding='utf-8') as f:
|
|
json.dump(resultats_complets, f, indent=2, ensure_ascii=False)
|
|
|
|
def executer_test_complet(self):
|
|
"""Exécuter le test complet"""
|
|
self.afficher_banniere()
|
|
|
|
# Étapes de test
|
|
etapes = [
|
|
("Composants Canvas", self.verifier_composants_canvas),
|
|
("Animations CSS", self.verifier_animations_css),
|
|
("États Visuels", self.verifier_etats_visuels),
|
|
("Intégration VWB", self.verifier_integration_vwb),
|
|
("Performance", self.verifier_performance),
|
|
]
|
|
|
|
for nom_etape, fonction_test in etapes:
|
|
try:
|
|
fonction_test()
|
|
except Exception as e:
|
|
print(f"❌ Erreur lors de {nom_etape}: {e}")
|
|
|
|
# Calcul du score
|
|
score = self.calculer_score_global()
|
|
|
|
# Rapport final
|
|
self.generer_rapport_final()
|
|
|
|
# Sauvegarde
|
|
self.sauvegarder_resultats()
|
|
|
|
return score >= 4
|
|
|
|
def main():
|
|
"""Fonction principale"""
|
|
print("Test des États Visuels Canvas VWB - 10 janvier 2026")
|
|
print("Auteur : Dom, Alice, Kiro")
|
|
print()
|
|
|
|
# Vérifier qu'on est dans le bon répertoire
|
|
if not os.path.exists('visual_workflow_builder'):
|
|
print("❌ Erreur: Exécuter depuis la racine du projet RPA Vision V3")
|
|
sys.exit(1)
|
|
|
|
# Créer et exécuter le test
|
|
test = TestEtatsVisuelsCanvasVWB()
|
|
succes = test.executer_test_complet()
|
|
|
|
sys.exit(0 if succes else 1)
|
|
|
|
if __name__ == "__main__":
|
|
main() |