#!/usr/bin/env python3 """ Test de diagnostic pour la documentation interactive Vérifie si le service de documentation fonctionne correctement """ import sys import os import json import requests import time from pathlib import Path # Ajouter le répertoire backend au path sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'backend')) def test_backend_running(): """Test si le backend est accessible et retourne des données valides""" try: # Test endpoint principal response = requests.get('http://localhost:5001/api/workflows', timeout=5) print(f"✓ Backend accessible - Status: {response.status_code}") # Vérifier que la réponse est du JSON valide if response.status_code == 200: try: data = response.json() print(f"✓ Réponse JSON valide: {type(data)}") except json.JSONDecodeError: print("⚠ Réponse non-JSON du backend") return False # Test endpoint spécifique à la documentation si disponible try: doc_response = requests.get('http://localhost:5001/api/documentation/tools', timeout=3) if doc_response.status_code == 200: print("✓ Endpoint documentation accessible") else: print(f"⚠ Endpoint documentation: {doc_response.status_code}") except requests.exceptions.RequestException: print("⚠ Endpoint documentation non disponible (optionnel)") return True except requests.exceptions.RequestException as e: print(f"✗ Backend non accessible: {e}") return False def test_documentation_data(): """Test si les données de documentation sont correctes""" try: # Vérifier que le fichier de documentation existe doc_file = Path(__file__).parent / 'frontend' / 'src' / 'data' / 'toolDocumentation.ts' if not doc_file.exists(): print(f"✗ Fichier de documentation manquant: {doc_file}") return False print(f"✓ Fichier de documentation trouvé: {doc_file}") # Lire le contenu content = doc_file.read_text() # Vérifier que les exports sont présents if 'export const TOOLS_DOCUMENTATION' in content: print("✓ TOOLS_DOCUMENTATION exporté") else: print("✗ TOOLS_DOCUMENTATION manquant") return False if 'export const GENERAL_DOCUMENTATION' in content: print("✓ GENERAL_DOCUMENTATION exporté") else: print("✗ GENERAL_DOCUMENTATION manquant") return False # Vérifier quelques outils de base avec validation plus approfondie tools_to_check = [ ('click', 'Cliquer sur un élément'), ('type', 'Saisir du texte'), ('wait', 'Attendre'), ('navigate', 'Naviguer') ] for tool, expected_desc in tools_to_check: if f"'{tool}':" in content or f'"{tool}":' in content or f'{tool}:' in content: print(f"✓ Outil {tool} trouvé dans la documentation") # Vérifier qu'il y a une description substantielle tool_section_start = max( content.find(f'"{tool}":'), content.find(f"'{tool}':"), content.find(f'{tool}:') ) if tool_section_start > 0: tool_section = content[tool_section_start:tool_section_start + 500] if 'description' in tool_section: desc_start = tool_section.find('description') if desc_start > 0: desc_content = tool_section[desc_start:desc_start + 200] if len(desc_content.split(':')[1][:100].strip()) > 10: print(f" ✓ Description substantielle trouvée pour {tool}") else: print(f" ⚠ Description courte pour {tool}") else: print(f" ⚠ Pas de champ description pour {tool}") else: print(f"✗ Outil {tool} manquant dans la documentation") return False # Vérifier la syntaxe TypeScript basique brace_balance = content.count('{') - content.count('}') if brace_balance != 0: print(f"✗ Syntaxe TypeScript invalide (déséquilibre d'accolades: {brace_balance})") return False # Compter approximativement le nombre d'outils documentés tool_entries = content.count('description:') + content.count('"description"') if tool_entries >= 4: print(f"✓ {tool_entries} outils documentés détectés") else: print(f"⚠ Seulement {tool_entries} outils documentés détectés") print("✓ Syntaxe TypeScript semble valide") return True except Exception as e: print(f"✗ Erreur lors de la vérification des données: {e}") return False def test_documentation_service_integration(): """Test l'intégration réelle du service de documentation""" try: # Importer et tester le service de documentation réel service_file = Path(__file__).parent / 'frontend' / 'src' / 'services' / 'DocumentationService.ts' if not service_file.exists(): print("✗ DocumentationService.ts manquant") return False service_content = service_file.read_text() # Vérifier les méthodes essentielles required_methods = [ 'getToolDocumentation', 'getGeneralDocumentation', 'preloadDocumentation' ] for method in required_methods: if method in service_content: print(f"✓ Méthode {method} trouvée") else: print(f"✗ Méthode {method} manquante") return False # Vérifier l'import des données if 'toolDocumentation' in service_content: print("✓ Import des données de documentation détecté") else: print("✗ Import des données manquant") return False return True except Exception as e: print(f"✗ Erreur lors du test du service: {e}") return False def test_frontend_files(): """Test si les fichiers frontend de documentation existent et sont valides""" frontend_dir = Path(__file__).parent / 'frontend' / 'src' files_to_check = [ ('services/DocumentationService.ts', ['class DocumentationService', 'getToolDocumentation', 'export']), ('components/DocumentationTab/index.tsx', ['DocumentationTab', 'React', 'export default']), ('components/DocumentationPopup/index.tsx', ['DocumentationPopup', 'React', 'export default']), ('types/documentation.ts', ['interface', 'export', 'ToolDocumentation']) ] all_valid = True for file_path, required_content in files_to_check: full_path = frontend_dir / file_path if full_path.exists(): print(f"✓ {file_path} existe") # Vérifier le contenu réel du fichier try: content = full_path.read_text() missing_content = [] for required in required_content: if required not in content: missing_content.append(required) if missing_content: print(f" ⚠ Contenu manquant dans {file_path}: {missing_content}") all_valid = False else: print(f" ✓ Contenu valide pour {file_path}") # Vérifier la taille du fichier (doit être substantiel) if len(content) < 100: print(f" ⚠ Fichier {file_path} semble trop petit ({len(content)} caractères)") all_valid = False except Exception as e: print(f" ✗ Erreur lecture {file_path}: {e}") all_valid = False else: print(f"✗ {file_path} manquant") all_valid = False return all_valid def test_app_integration(): """Test si App.tsx intègre correctement la documentation avec validation du code réel""" try: app_file = Path(__file__).parent / 'frontend' / 'src' / 'App.tsx' if not app_file.exists(): print("✗ App.tsx manquant") return False content = app_file.read_text() # Vérifier l'import du service de documentation import_patterns = [ 'documentationService', 'DocumentationService', 'from.*DocumentationService' ] import_found = any(pattern.replace('.*', '') in content for pattern in import_patterns) if import_found: print("✓ DocumentationService importé dans App.tsx") else: print("✗ DocumentationService non importé dans App.tsx") return False # Vérifier l'initialisation ou utilisation usage_patterns = [ 'preloadDocumentation', 'documentationService', 'useEffect', 'Documentation' ] usage_found = sum(1 for pattern in usage_patterns if pattern in content) if usage_found >= 2: print(f"✓ Utilisation de la documentation détectée ({usage_found} patterns)") else: print(f"⚠ Utilisation limitée de la documentation ({usage_found} patterns)") # Vérifier que le fichier est un composant React valide react_indicators = ['import React', 'export default', 'function App', 'const App'] if any(indicator in content for indicator in react_indicators): print("✓ App.tsx est un composant React valide") else: print("✗ App.tsx ne semble pas être un composant React valide") return False return True except Exception as e: print(f"✗ Erreur lors de la vérification d'App.tsx: {e}") return False def test_properties_panel_integration(): """Test si PropertiesPanel intègre l'onglet Documentation avec validation complète""" try: props_file = Path(__file__).parent / 'frontend' / 'src' / 'components' / 'PropertiesPanel' / 'index.tsx' if not props_file.exists(): print("✗ PropertiesPanel/index.tsx manquant") return False content = props_file.read_text() # Vérifier l'import de DocumentationTab if 'DocumentationTab' in content: print("✓ DocumentationTab importé dans PropertiesPanel") else: print("✗ DocumentationTab non importé dans PropertiesPanel") return False # Vérifier la structure des onglets avec validation plus robuste tab_indicators = ['Tab', 'TabPanel', 'Tabs', 'Documentation'] tab_score = sum(1 for indicator in tab_indicators if indicator in content) if tab_score >= 3: print(f"✓ Structure d'onglets détectée (score: {tab_score}/4)") else: print(f"⚠ Structure d'onglets incomplète (score: {tab_score}/4)") # Vérifier le rendu conditionnel ou la gestion d'état state_patterns = [ 'activeTab', 'selectedTab', 'useState', 'tabIndex', 'value=' ] state_found = any(pattern in content for pattern in state_patterns) if state_found: print("✓ Gestion d'état des onglets détectée") else: print("⚠ Gestion d'état des onglets non détectée") # Vérifier que DocumentationTab est effectivement rendu render_patterns = [ '= 2: print("✓ Rendu de DocumentationTab confirmé") else: print("⚠ Rendu de DocumentationTab incertain") # Vérifier que c'est un composant React valide if 'export default' in content and ('function' in content or 'const' in content): print("✓ PropertiesPanel est un composant React valide") return True else: print("✗ PropertiesPanel ne semble pas être un composant React valide") return False except Exception as e: print(f"✗ Erreur lors de la vérification de PropertiesPanel: {e}") return False def test_documentation_performance(): """Test les performances de chargement de la documentation""" try: import time print("\n--- Test de performance ---") # Mesurer le temps de lecture des données start_time = time.time() doc_file = Path(__file__).parent / 'frontend' / 'src' / 'data' / 'toolDocumentation.ts' if doc_file.exists(): content = doc_file.read_text() file_size = len(content) read_time = time.time() - start_time print(f"✓ Fichier de documentation lu en {read_time:.3f}s") print(f"✓ Taille du fichier: {file_size} caractères ({file_size/1024:.1f} KB)") if read_time > 1.0: print("⚠ Temps de lecture élevé (>1s)") return False if file_size > 100000: # 100KB print("⚠ Fichier de documentation très volumineux (>100KB)") # Test de parsing basique start_parse = time.time() tool_count = content.count('description:') parse_time = time.time() - start_parse print(f"✓ Parsing basique en {parse_time:.3f}s ({tool_count} outils détectés)") return True else: print("✗ Fichier de documentation non trouvé") return False except Exception as e: print(f"✗ Erreur dans le test de performance: {e}") return False def test_end_to_end_documentation_flow(): """Test le flux complet de documentation de bout en bout""" try: print("\n--- Test du flux complet de documentation ---") # 1. Vérifier que les données existent et sont parsables doc_file = Path(__file__).parent / 'frontend' / 'src' / 'data' / 'toolDocumentation.ts' if not doc_file.exists(): print("✗ Données de documentation manquantes") return False content = doc_file.read_text() # 2. Extraire un outil spécifique pour test test_tools = ['click', 'type', 'wait'] found_tool = None for tool in test_tools: if f'"{tool}":' in content or f"'{tool}':" in content: found_tool = tool break if not found_tool: print("✗ Aucun outil de test trouvé dans les données") return False print(f"✓ Outil de test trouvé: {found_tool}") # 3. Vérifier que le service peut être importé (simulation d'import) service_file = Path(__file__).parent / 'frontend' / 'src' / 'services' / 'DocumentationService.ts' if service_file.exists(): service_content = service_file.read_text() if 'getToolDocumentation' in service_content and 'toolDocumentation' in service_content: print("✓ Service de documentation correctement configuré") else: print("⚠ Service de documentation incomplet") return False # 4. Vérifier que les composants peuvent consommer les données tab_file = Path(__file__).parent / 'frontend' / 'src' / 'components' / 'DocumentationTab' / 'index.tsx' if tab_file.exists(): tab_content = tab_file.read_text() if 'documentationService' in tab_content or 'DocumentationService' in tab_content: print("✓ DocumentationTab connecté au service") else: print("⚠ DocumentationTab non connecté au service") # 5. Test de cohérence des types types_file = Path(__file__).parent / 'frontend' / 'src' / 'types' / 'documentation.ts' if types_file.exists(): types_content = types_file.read_text() if 'ToolDocumentation' in types_content and 'interface' in types_content: print("✓ Types de documentation définis") else: print("⚠ Types de documentation incomplets") print("✓ Flux de documentation validé de bout en bout") return True except Exception as e: print(f"✗ Erreur dans le test de flux complet: {e}") return False def main(): """Fonction principale de diagnostic""" print("=== DIAGNOSTIC DE LA DOCUMENTATION INTERACTIVE ===\n") tests = [ ("Données de documentation", test_documentation_data), ("Service de documentation", test_documentation_service_integration), ("Fichiers frontend", test_frontend_files), ("Intégration App.tsx", test_app_integration), ("Intégration PropertiesPanel", test_properties_panel_integration), ("Performance documentation", test_documentation_performance), ("Flux complet de documentation", test_end_to_end_documentation_flow), ("Backend accessible", test_backend_running), ] results = [] for test_name, test_func in tests: print(f"\n--- {test_name} ---") result = test_func() results.append((test_name, result)) print("\n=== RÉSUMÉ ===") all_passed = True for test_name, result in results: status = "✓ PASS" if result else "✗ FAIL" print(f"{status} {test_name}") if not result: all_passed = False if all_passed: print("\n🎉 Tous les tests sont passés ! La documentation devrait fonctionner.") print("\nPour tester l'interface:") print("1. Démarrez le backend: cd backend && python app.py") print("2. Démarrez le frontend: cd frontend && npm start") print("3. Ouvrez http://localhost:3000") print("4. Ajoutez un nœud et cliquez dessus") print("5. Cliquez sur l'onglet 'Documentation' dans le panneau de propriétés") else: print("\n❌ Certains tests ont échoué. Vérifiez les erreurs ci-dessus.") return all_passed if __name__ == "__main__": success = main() sys.exit(0 if success else 1)