Files
rpa_vision_v3/visual_workflow_builder/test_documentation_debug.py
Dom a27b74cf22 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>
2026-01-29 11:23:51 +01:00

483 lines
19 KiB
Python

#!/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 = [
'<DocumentationTab',
'DocumentationTab',
'documentation'
]
render_found = sum(1 for pattern in render_patterns if pattern in content)
if render_found >= 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)