Files
rpa_vision_v3/tests/integration/test_vwb_stability_simple.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

233 lines
8.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Tests de stabilité simplifiés - Visual Workflow Builder Frontend V2
Auteur : Dom, Alice, Kiro - 09 janvier 2026
Script de validation sans dépendance pytest.
"""
import os
import re
import sys
from pathlib import Path
# Chemin vers le frontend VWB
SCRIPT_DIR = Path(__file__).parent
PROJECT_ROOT = SCRIPT_DIR.parent.parent
FRONTEND_PATH = PROJECT_ROOT / "visual_workflow_builder" / "frontend"
SRC_PATH = FRONTEND_PATH / "src"
def test_api_client_initial_state_is_offline():
"""Vérifie que l'état initial du client API est 'offline'."""
api_client_path = SRC_PATH / "services" / "apiClient.ts"
if not api_client_path.exists():
return False, f"Fichier non trouvé: {api_client_path}"
content = api_client_path.read_text(encoding='utf-8')
# Vérifier que l'état initial est 'offline' et non 'checking'
if "connectionState: ConnectionState = 'offline'" not in content:
return False, "L'état initial du client API doit être 'offline'"
if "connectionState: ConnectionState = 'checking'" in content:
return False, "L'état initial ne doit PAS être 'checking'"
return True, "OK"
def test_api_client_lazy_initialization():
"""Vérifie que l'initialisation est paresseuse (lazy)."""
api_client_path = SRC_PATH / "services" / "apiClient.ts"
content = api_client_path.read_text(encoding='utf-8')
# Vérifier la présence du commentaire sur l'initialisation paresseuse
if "paresseuse" not in content.lower() and "lazy" not in content.lower():
return False, "Le code doit mentionner l'initialisation paresseuse (lazy)"
return True, "OK"
def test_api_client_async_notifications():
"""Vérifie que les notifications sont asynchrones (setTimeout)."""
api_client_path = SRC_PATH / "services" / "apiClient.ts"
content = api_client_path.read_text(encoding='utf-8')
# Vérifier la présence de setTimeout pour les notifications
if 'setTimeout' not in content:
return False, "Les notifications doivent être asynchrones (setTimeout)"
return True, "OK"
def test_connection_status_hook_initial_state():
"""Vérifie que useConnectionStatus a un état initial 'offline'."""
hook_path = SRC_PATH / "hooks" / "useConnectionStatus.ts"
if not hook_path.exists():
return False, f"Fichier non trouvé: {hook_path}"
content = hook_path.read_text(encoding='utf-8')
# Vérifier que l'état initial est 'offline'
if "status: 'offline'" not in content:
return False, "L'état initial du hook doit être 'offline'"
return True, "OK"
def test_connection_status_hook_uses_refs():
"""Vérifie que le hook utilise des refs pour les callbacks."""
hook_path = SRC_PATH / "hooks" / "useConnectionStatus.ts"
content = hook_path.read_text(encoding='utf-8')
if 'useRef' not in content:
return False, "Le hook doit utiliser useRef pour éviter les re-renders"
return True, "OK"
def test_connection_status_hook_initial_state_constant():
"""Vérifie que l'état initial est une constante stable."""
hook_path = SRC_PATH / "hooks" / "useConnectionStatus.ts"
content = hook_path.read_text(encoding='utf-8')
if 'INITIAL_STATE' not in content:
return False, "L'état initial doit être une constante INITIAL_STATE"
return True, "OK"
def test_use_api_client_hook_initial_offline():
"""Vérifie que useConnectionState a un état initial 'offline'."""
hook_path = SRC_PATH / "hooks" / "useApiClient.ts"
if not hook_path.exists():
return False, f"Fichier non trouvé: {hook_path}"
content = hook_path.read_text(encoding='utf-8')
# Vérifier que l'état initial est 'offline'
if "'offline'" not in content:
return False, "useConnectionState doit avoir un état initial 'offline'"
return True, "OK"
def test_workflow_manager_uses_connection_state():
"""Vérifie que WorkflowManager utilise useConnectionState."""
component_path = SRC_PATH / "components" / "WorkflowManager" / "index.tsx"
if not component_path.exists():
return False, f"Fichier non trouvé: {component_path}"
content = component_path.read_text(encoding='utf-8')
if 'useConnectionState' not in content:
return False, "WorkflowManager doit utiliser useConnectionState"
return True, "OK"
def test_executor_uses_connection_status():
"""Vérifie que Executor utilise useConnectionStatus."""
component_path = SRC_PATH / "components" / "Executor" / "index.tsx"
if not component_path.exists():
return False, f"Fichier non trouvé: {component_path}"
content = component_path.read_text(encoding='utf-8')
if 'useConnectionStatus' not in content:
return False, "Executor doit utiliser useConnectionStatus"
return True, "OK"
def test_french_comments_in_api_client():
"""Vérifie que apiClient.ts a des commentaires en français."""
api_client_path = SRC_PATH / "services" / "apiClient.ts"
content = api_client_path.read_text(encoding='utf-8')
french_words = ['Auteur', 'janvier', 'gestion', 'connexion', 'hors ligne']
found_french = any(word in content for word in french_words)
if not found_french:
return False, "apiClient.ts doit avoir des commentaires en français"
return True, "OK"
def test_typescript_syntax_balanced():
"""Vérifie la syntaxe TypeScript basique."""
files_to_check = [
SRC_PATH / "services" / "apiClient.ts",
SRC_PATH / "hooks" / "useApiClient.ts",
SRC_PATH / "hooks" / "useConnectionStatus.ts",
]
for file_path in files_to_check:
if not file_path.exists():
continue
content = file_path.read_text(encoding='utf-8')
if content.count('{') != content.count('}'):
return False, f"Accolades non équilibrées dans {file_path.name}"
if content.count('(') != content.count(')'):
return False, f"Parenthèses non équilibrées dans {file_path.name}"
return True, "OK"
def run_all_tests():
"""Exécute tous les tests et affiche les résultats."""
tests = [
("État initial apiClient = 'offline'", test_api_client_initial_state_is_offline),
("Initialisation paresseuse (lazy)", test_api_client_lazy_initialization),
("Notifications asynchrones (setTimeout)", test_api_client_async_notifications),
("useConnectionStatus état initial 'offline'", test_connection_status_hook_initial_state),
("useConnectionStatus utilise useRef", test_connection_status_hook_uses_refs),
("useConnectionStatus INITIAL_STATE constant", test_connection_status_hook_initial_state_constant),
("useApiClient état initial 'offline'", test_use_api_client_hook_initial_offline),
("WorkflowManager utilise useConnectionState", test_workflow_manager_uses_connection_state),
("Executor utilise useConnectionStatus", test_executor_uses_connection_status),
("Commentaires français dans apiClient", test_french_comments_in_api_client),
("Syntaxe TypeScript équilibrée", test_typescript_syntax_balanced),
]
print("=" * 70)
print("Tests de Stabilité - Visual Workflow Builder Frontend V2")
print("Auteur : Dom, Alice, Kiro - 09 janvier 2026")
print("=" * 70)
print()
passed = 0
failed = 0
for name, test_func in tests:
try:
success, message = test_func()
if success:
print(f"✅ PASS: {name}")
passed += 1
else:
print(f"❌ FAIL: {name}")
print(f" Raison: {message}")
failed += 1
except Exception as e:
print(f"❌ ERROR: {name}")
print(f" Exception: {e}")
failed += 1
print()
print("=" * 70)
print(f"Résultats: {passed} passés, {failed} échoués sur {len(tests)} tests")
print("=" * 70)
return failed == 0
if __name__ == "__main__":
success = run_all_tests()
sys.exit(0 if success else 1)