#!/usr/bin/env python3 """ Script de Validation Finale - Intégration Propriétés VWB Auteur : Dom, Alice, Kiro - 10 janvier 2026 Ce script valide l'intégration complète des propriétés d'étapes VWB dans le Visual Workflow Builder sans dépendances pytest. """ import json import time import requests import subprocess import os import sys from pathlib import Path from typing import Dict, Any, List, Optional # Configuration des chemins PROJECT_ROOT = Path(__file__).parent.parent VWB_FRONTEND_PATH = PROJECT_ROOT / "visual_workflow_builder" / "frontend" VWB_BACKEND_PATH = PROJECT_ROOT / "visual_workflow_builder" / "backend" class ValidationFinaleProprietesVWB: """Validation finale de l'intégration des propriétés VWB""" def __init__(self): self.backend_url = "http://localhost:5004" self.backend_process = None self.tests_passed = 0 self.tests_failed = 0 self.errors = [] def run_all_validations(self): """Exécuter toutes les validations""" print("🚀 VALIDATION FINALE - INTÉGRATION PROPRIÉTÉS VWB") print("=" * 60) try: # Étape 1: Vérifier l'environnement self.validate_environment() # Étape 2: Démarrer le backend self.start_backend() # Étape 3: Valider les fichiers frontend self.validate_frontend_files() # Étape 4: Valider l'API backend self.validate_backend_api() # Étape 5: Valider l'intégration complète self.validate_integration() except Exception as e: self.log_error(f"Erreur critique: {e}") finally: # Nettoyage self.cleanup() # Rapport final self.print_final_report() def validate_environment(self): """Valider l'environnement de développement""" print("\n🔍 ÉTAPE 1: Validation de l'environnement") # Vérifier l'environnement virtuel if "venv_v3" not in sys.executable: self.log_error("Environnement virtuel venv_v3 non activé") return self.log_success("Environnement virtuel venv_v3 activé") # Vérifier les dépendances Python try: import flask import requests self.log_success("Dépendances Python disponibles") except ImportError as e: self.log_error(f"Dépendances manquantes: {e}") def start_backend(self): """Démarrer le backend VWB""" print("\n🔍 ÉTAPE 2: Démarrage du backend VWB") try: # Vérifier si le backend est déjà en cours d'exécution try: response = requests.get(f"{self.backend_url}/api/health", timeout=2) if response.status_code == 200: self.log_success("Backend VWB déjà en cours d'exécution") return except requests.exceptions.RequestException: pass # Démarrer le backend script_path = PROJECT_ROOT / "scripts" / "start_vwb_backend_catalogue_complet_10jan2026.py" if script_path.exists(): self.backend_process = subprocess.Popen([ sys.executable, str(script_path) ], cwd=str(PROJECT_ROOT)) else: # Fallback self.backend_process = subprocess.Popen([ sys.executable, "-m", "visual_workflow_builder.backend.app_catalogue_simple" ], cwd=str(PROJECT_ROOT)) # Attendre que le backend soit prêt max_attempts = 30 for attempt in range(max_attempts): try: response = requests.get(f"{self.backend_url}/api/health", timeout=2) if response.status_code == 200: self.log_success(f"Backend VWB démarré (PID: {self.backend_process.pid})") return except requests.exceptions.RequestException: pass time.sleep(1) self.log_error("Backend VWB non accessible après 30 secondes") except Exception as e: self.log_error(f"Impossible de démarrer le backend VWB: {e}") def validate_frontend_files(self): """Valider les fichiers frontend""" print("\n🔍 ÉTAPE 3: Validation des fichiers frontend") # Fichiers essentiels à vérifier essential_files = [ # Types VWB_FRONTEND_PATH / "src" / "types" / "catalog.ts", VWB_FRONTEND_PATH / "src" / "types" / "index.ts", # Services VWB_FRONTEND_PATH / "src" / "services" / "catalogService.ts", # Hooks VWB_FRONTEND_PATH / "src" / "hooks" / "useVWBStepIntegration.ts", # Composants VWB_FRONTEND_PATH / "src" / "components" / "PropertiesPanel" / "VWBActionProperties.tsx", VWB_FRONTEND_PATH / "src" / "components" / "PropertiesPanel" / "index.tsx", VWB_FRONTEND_PATH / "src" / "components" / "Canvas" / "StepNode.tsx", VWB_FRONTEND_PATH / "src" / "components" / "Palette" / "index.tsx", ] for file_path in essential_files: if file_path.exists(): self.log_success(f"Fichier présent: {file_path.name}") else: self.log_error(f"Fichier manquant: {file_path}") # Vérifier le contenu des fichiers clés self.validate_file_content() def validate_file_content(self): """Valider le contenu des fichiers clés""" print("\n🔍 Validation du contenu des fichiers") # Vérifier catalog.ts catalog_types_file = VWB_FRONTEND_PATH / "src" / "types" / "catalog.ts" if catalog_types_file.exists(): content = catalog_types_file.read_text() required_types = ["VWBCatalogAction", "VWBActionParameter", "VWBVisualAnchor"] for type_name in required_types: if type_name in content: self.log_success(f"Type {type_name} présent") else: self.log_error(f"Type {type_name} manquant") # Vérifier VWBActionProperties.tsx vwb_props_file = VWB_FRONTEND_PATH / "src" / "components" / "PropertiesPanel" / "VWBActionProperties.tsx" if vwb_props_file.exists(): content = vwb_props_file.read_text() required_elements = ["VWBActionProperties", "VisualAnchorEditor", "onParameterChange"] for element in required_elements: if element in content: self.log_success(f"Élément {element} présent dans VWBActionProperties") else: self.log_error(f"Élément {element} manquant dans VWBActionProperties") # Vérifier l'intégration dans PropertiesPanel/index.tsx main_props_file = VWB_FRONTEND_PATH / "src" / "components" / "PropertiesPanel" / "index.tsx" if main_props_file.exists(): content = main_props_file.read_text() integration_elements = ["import VWBActionProperties", "useVWBStepIntegration", "isVWBCatalogAction"] for element in integration_elements: if element in content: self.log_success(f"Intégration {element} présente") else: self.log_error(f"Intégration {element} manquante") def validate_backend_api(self): """Valider l'API backend""" print("\n🔍 ÉTAPE 4: Validation de l'API backend") try: # Test de l'endpoint catalogue response = requests.get(f"{self.backend_url}/api/vwb/catalog/actions", timeout=5) if response.status_code == 200: self.log_success("Endpoint catalogue accessible") catalog_data = response.json() if "actions" in catalog_data: actions = catalog_data["actions"] self.log_success(f"Catalogue contient {len(actions)} actions") # Vérifier les actions essentielles action_ids = [action["id"] for action in actions] required_actions = ["click_anchor", "type_text", "wait_for_anchor"] for action_id in required_actions: if action_id in action_ids: self.log_success(f"Action {action_id} disponible") else: self.log_error(f"Action {action_id} manquante") else: self.log_error("Structure de catalogue invalide") else: self.log_error(f"Endpoint catalogue non accessible: {response.status_code}") except requests.exceptions.RequestException as e: self.log_error(f"Erreur de connexion API: {e}") def validate_integration(self): """Valider l'intégration complète""" print("\n🔍 ÉTAPE 5: Validation de l'intégration complète") try: # Test de validation d'action validation_request = { "type": "click_anchor", "parameters": { "visual_anchor": { "anchor_type": "screenshot", "screenshot_base64": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==", "confidence_threshold": 0.8 } } } response = requests.post( f"{self.backend_url}/api/vwb/catalog/validate", json=validation_request, timeout=5 ) if response.status_code == 200: validation_result = response.json() if validation_result.get("is_valid"): self.log_success("Validation d'action fonctionnelle") else: self.log_error("Validation d'action échouée") else: self.log_error(f"Endpoint de validation non accessible: {response.status_code}") except requests.exceptions.RequestException as e: self.log_error(f"Erreur de validation: {e}") def cleanup(self): """Nettoyage des ressources""" if self.backend_process: try: self.backend_process.terminate() self.backend_process.wait(timeout=5) except subprocess.TimeoutExpired: self.backend_process.kill() def log_success(self, message: str): """Enregistrer un succès""" print(f"✅ {message}") self.tests_passed += 1 def log_error(self, message: str): """Enregistrer une erreur""" print(f"❌ {message}") self.tests_failed += 1 self.errors.append(message) def print_final_report(self): """Imprimer le rapport final""" print("\n" + "=" * 60) print("📊 RAPPORT FINAL DE VALIDATION") print("=" * 60) print(f"✅ Tests réussis: {self.tests_passed}") print(f"❌ Tests échoués: {self.tests_failed}") print(f"📈 Taux de réussite: {(self.tests_passed / (self.tests_passed + self.tests_failed) * 100):.1f}%") if self.errors: print("\n🔧 ERREURS À CORRIGER:") for i, error in enumerate(self.errors, 1): print(f" {i}. {error}") if self.tests_failed == 0: print("\n🎉 VALIDATION COMPLÈTE RÉUSSIE!") print("✨ L'intégration des propriétés d'étapes VWB est fonctionnelle") return True else: print("\n⚠️ VALIDATION INCOMPLÈTE") print("🔧 Veuillez corriger les erreurs identifiées") return False def main(): """Fonction principale""" validator = ValidationFinaleProprietesVWB() success = validator.run_all_validations() return 0 if success else 1 if __name__ == "__main__": exit(main())