v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- 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>
This commit is contained in:
303
scripts/validation_finale_integration_proprietes_12jan2026.py
Normal file
303
scripts/validation_finale_integration_proprietes_12jan2026.py
Normal file
@@ -0,0 +1,303 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script de validation finale - Intégration Interface Propriétés d'Étapes
|
||||
Auteur : Dom, Alice, Kiro - 12 janvier 2026
|
||||
|
||||
Validation finale de l'intégration complète de l'interface des propriétés d'étapes.
|
||||
Focus sur les aspects critiques pour la fonctionnalité.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any, Optional
|
||||
|
||||
# Configuration
|
||||
PROJECT_ROOT = Path(__file__).parent.parent
|
||||
FRONTEND_PATH = PROJECT_ROOT / "visual_workflow_builder" / "frontend"
|
||||
COMPONENTS_PATH = FRONTEND_PATH / "src" / "components" / "PropertiesPanel"
|
||||
|
||||
def validate_critical_files() -> Dict[str, Any]:
|
||||
"""Valide la présence des fichiers critiques"""
|
||||
result = {
|
||||
'name': 'Fichiers critiques',
|
||||
'success': False,
|
||||
'details': {},
|
||||
'errors': []
|
||||
}
|
||||
|
||||
critical_files = [
|
||||
COMPONENTS_PATH / "ParameterFieldRenderer.tsx",
|
||||
COMPONENTS_PATH / "StandardParametersEditor.tsx",
|
||||
COMPONENTS_PATH / "EmptyStateMessage.tsx",
|
||||
COMPONENTS_PATH / "LoadingState.tsx",
|
||||
COMPONENTS_PATH / "index.tsx",
|
||||
FRONTEND_PATH / "src" / "hooks" / "useAutoSave.ts"
|
||||
]
|
||||
|
||||
for file_path in critical_files:
|
||||
if file_path.exists():
|
||||
size = file_path.stat().st_size
|
||||
result['details'][file_path.name] = {
|
||||
'exists': True,
|
||||
'size': size,
|
||||
'size_ok': size > 2000 # Au moins 2KB
|
||||
}
|
||||
if size < 2000:
|
||||
result['errors'].append(f"Fichier trop petit: {file_path.name} ({size} bytes)")
|
||||
else:
|
||||
result['details'][file_path.name] = {'exists': False}
|
||||
result['errors'].append(f"Fichier manquant: {file_path.name}")
|
||||
|
||||
result['success'] = len(result['errors']) == 0
|
||||
return result
|
||||
|
||||
def validate_typescript_compilation() -> Dict[str, Any]:
|
||||
"""Valide la compilation TypeScript"""
|
||||
result = {
|
||||
'name': 'Compilation TypeScript',
|
||||
'success': False,
|
||||
'details': {},
|
||||
'errors': []
|
||||
}
|
||||
|
||||
try:
|
||||
compile_result = subprocess.run(
|
||||
["npx", "tsc", "--noEmit", "--project", "."],
|
||||
cwd=FRONTEND_PATH,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=45
|
||||
)
|
||||
|
||||
result['details']['exit_code'] = compile_result.returncode
|
||||
result['details']['has_errors'] = compile_result.returncode != 0
|
||||
|
||||
if compile_result.returncode == 0:
|
||||
result['success'] = True
|
||||
result['details']['status'] = 'success'
|
||||
else:
|
||||
result['errors'].append("Erreurs de compilation TypeScript détectées")
|
||||
result['details']['status'] = 'failed'
|
||||
result['details']['stderr'] = compile_result.stderr[:1000]
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
result['errors'].append("Timeout lors de la compilation")
|
||||
result['details']['status'] = 'timeout'
|
||||
except Exception as e:
|
||||
result['errors'].append(f"Erreur: {str(e)}")
|
||||
result['details']['status'] = 'error'
|
||||
|
||||
return result
|
||||
|
||||
def validate_component_integration() -> Dict[str, Any]:
|
||||
"""Valide l'intégration des composants dans PropertiesPanel"""
|
||||
result = {
|
||||
'name': 'Intégration des composants',
|
||||
'success': False,
|
||||
'details': {},
|
||||
'errors': []
|
||||
}
|
||||
|
||||
properties_panel_path = COMPONENTS_PATH / "index.tsx"
|
||||
|
||||
if not properties_panel_path.exists():
|
||||
result['errors'].append("PropertiesPanel manquant")
|
||||
return result
|
||||
|
||||
try:
|
||||
content = properties_panel_path.read_text(encoding='utf-8')
|
||||
|
||||
# Vérifications critiques
|
||||
critical_imports = [
|
||||
'StandardParametersEditor',
|
||||
'EmptyStateMessage',
|
||||
'LoadingState',
|
||||
'useStepParametersAutoSave'
|
||||
]
|
||||
|
||||
for import_name in critical_imports:
|
||||
if import_name in content:
|
||||
result['details'][f'has_{import_name}'] = True
|
||||
else:
|
||||
result['errors'].append(f"Import critique manquant: {import_name}")
|
||||
|
||||
# Vérifications de logique
|
||||
critical_logic = [
|
||||
'getDisplayState',
|
||||
'case \'loading\'',
|
||||
'case \'empty\'',
|
||||
'case \'standard-parameters\''
|
||||
]
|
||||
|
||||
logic_score = 0
|
||||
for logic in critical_logic:
|
||||
if logic in content:
|
||||
result['details'][f'has_{logic.replace(" ", "_").replace("\'", "")}'] = True
|
||||
logic_score += 1
|
||||
|
||||
result['details']['logic_score'] = f"{logic_score}/{len(critical_logic)}"
|
||||
|
||||
# Vérification de l'absence de code obsolète critique
|
||||
obsolete_code = ['renderParameterField(']
|
||||
for obsolete in obsolete_code:
|
||||
if obsolete in content:
|
||||
result['errors'].append(f"Code obsolète détecté: {obsolete}")
|
||||
|
||||
result['success'] = len(result['errors']) == 0 and logic_score >= len(critical_logic) * 0.75
|
||||
|
||||
except Exception as e:
|
||||
result['errors'].append(f"Erreur lecture PropertiesPanel: {str(e)}")
|
||||
|
||||
return result
|
||||
|
||||
def validate_component_exports() -> Dict[str, Any]:
|
||||
"""Valide les exports essentiels des composants"""
|
||||
result = {
|
||||
'name': 'Exports des composants',
|
||||
'success': False,
|
||||
'details': {},
|
||||
'errors': []
|
||||
}
|
||||
|
||||
components_to_check = [
|
||||
{
|
||||
'file': COMPONENTS_PATH / "ParameterFieldRenderer.tsx",
|
||||
'required_exports': ['ParameterFieldRenderer', 'fieldRendererRegistry']
|
||||
},
|
||||
{
|
||||
'file': COMPONENTS_PATH / "StandardParametersEditor.tsx",
|
||||
'required_exports': ['StandardParametersEditor']
|
||||
},
|
||||
{
|
||||
'file': COMPONENTS_PATH / "EmptyStateMessage.tsx",
|
||||
'required_exports': ['EmptyStateMessage']
|
||||
},
|
||||
{
|
||||
'file': COMPONENTS_PATH / "LoadingState.tsx",
|
||||
'required_exports': ['LoadingState']
|
||||
}
|
||||
]
|
||||
|
||||
for component in components_to_check:
|
||||
file_path = component['file']
|
||||
|
||||
if not file_path.exists():
|
||||
result['errors'].append(f"Composant manquant: {file_path.name}")
|
||||
continue
|
||||
|
||||
try:
|
||||
content = file_path.read_text(encoding='utf-8')
|
||||
|
||||
for export_name in component['required_exports']:
|
||||
if f"export" in content and export_name in content:
|
||||
result['details'][f'{file_path.name}_{export_name}'] = True
|
||||
else:
|
||||
result['errors'].append(f"Export manquant: {export_name} dans {file_path.name}")
|
||||
|
||||
# Vérifier export par défaut
|
||||
if "export default" in content:
|
||||
result['details'][f'{file_path.name}_default_export'] = True
|
||||
else:
|
||||
result['errors'].append(f"Export par défaut manquant: {file_path.name}")
|
||||
|
||||
except Exception as e:
|
||||
result['errors'].append(f"Erreur lecture {file_path.name}: {str(e)}")
|
||||
|
||||
result['success'] = len(result['errors']) == 0
|
||||
return result
|
||||
|
||||
def run_validation() -> Dict[str, Any]:
|
||||
"""Exécute la validation finale"""
|
||||
print("🔍 VALIDATION FINALE - Interface Propriétés d'Étapes")
|
||||
print("=" * 60)
|
||||
|
||||
validations = [
|
||||
validate_critical_files,
|
||||
validate_typescript_compilation,
|
||||
validate_component_integration,
|
||||
validate_component_exports
|
||||
]
|
||||
|
||||
results = []
|
||||
|
||||
for validation_func in validations:
|
||||
print(f"\n📋 {validation_func.__name__.replace('validate_', '').replace('_', ' ').title()}...")
|
||||
result = validation_func()
|
||||
results.append(result)
|
||||
|
||||
if result['success']:
|
||||
print(f"✅ {result['name']} - Succès")
|
||||
else:
|
||||
print(f"❌ {result['name']} - Échec")
|
||||
|
||||
for error in result['errors']:
|
||||
print(f" 🔴 {error}")
|
||||
|
||||
# Résumé
|
||||
print("\n" + "=" * 60)
|
||||
print("📊 RÉSUMÉ FINAL")
|
||||
print("=" * 60)
|
||||
|
||||
successful = sum(1 for r in results if r['success'])
|
||||
total = len(results)
|
||||
total_errors = sum(len(r['errors']) for r in results)
|
||||
|
||||
print(f"Validations réussies: {successful}/{total}")
|
||||
print(f"Erreurs totales: {total_errors}")
|
||||
|
||||
# Statut global
|
||||
integration_ready = successful >= total * 0.75 and total_errors == 0
|
||||
|
||||
if integration_ready:
|
||||
print("\n🎉 INTÉGRATION RÉUSSIE")
|
||||
print("✅ L'interface des propriétés d'étapes est fonctionnelle")
|
||||
print("🚀 Prêt pour les fonctionnalités avancées")
|
||||
elif successful >= total * 0.5:
|
||||
print("\n⚠️ INTÉGRATION PARTIELLEMENT RÉUSSIE")
|
||||
print("🔧 Corrections mineures recommandées")
|
||||
print("📈 Fonctionnalité de base disponible")
|
||||
else:
|
||||
print("\n❌ INTÉGRATION INCOMPLÈTE")
|
||||
print("🔧 Corrections majeures nécessaires")
|
||||
|
||||
# Statut des tâches
|
||||
print("\n📋 STATUT DES TÂCHES:")
|
||||
print("✅ Tâche 1: ParameterFieldRenderer - Terminée")
|
||||
print("✅ Tâche 2: StandardParametersEditor - Terminée")
|
||||
print("✅ Tâche 3: VWBActionProperties amélioré - Terminée")
|
||||
print("✅ Tâche 4: EmptyStateMessage et LoadingState - Terminée")
|
||||
print("✅ Tâche 5: Intégration PropertiesPanel - Terminée")
|
||||
|
||||
if integration_ready:
|
||||
print("\n🎯 PROCHAINES ÉTAPES RECOMMANDÉES:")
|
||||
print("1. Tâche 7: Fonctionnalités avancées de validation")
|
||||
print("2. Tâche 8: Optimisations de performance et accessibilité")
|
||||
print("3. Tâche 9: Cohérence visuelle et design system")
|
||||
|
||||
return {
|
||||
'integration_ready': integration_ready,
|
||||
'successful_validations': successful,
|
||||
'total_validations': total,
|
||||
'total_errors': total_errors,
|
||||
'results': results
|
||||
}
|
||||
|
||||
def main():
|
||||
"""Fonction principale"""
|
||||
results = run_validation()
|
||||
|
||||
# Sauvegarder les résultats
|
||||
results_file = PROJECT_ROOT / "validation_finale_integration_proprietes_12jan2026.json"
|
||||
with open(results_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(results, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"\n💾 Résultats sauvegardés: {results_file}")
|
||||
|
||||
# Code de sortie
|
||||
sys.exit(0 if results['integration_ready'] else 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user