""" Tests pour le dashboard web RPA Vision V3. Vérifie que les routes principales répondent correctement et que le template se rend sans erreur. """ import sys from pathlib import Path import pytest # Ajouter le répertoire racine au path sys.path.insert(0, str(Path(__file__).parent.parent.parent)) from web_dashboard.app import app @pytest.fixture def client(): """Client de test Flask.""" app.config['TESTING'] = True with app.test_client() as c: yield c class TestDashboardRoutes: """Tests des routes du dashboard.""" def test_index_renders(self, client): """La page d'accueil se rend correctement.""" resp = client.get('/') assert resp.status_code == 200 assert b'RPA Vision V3' in resp.data def test_healthz(self, client): """Le healthcheck retourne OK.""" resp = client.get('/healthz') assert resp.status_code == 200 data = resp.get_json() assert data['status'] == 'ok' def test_system_status(self, client): """L'API system/status retourne les compteurs.""" resp = client.get('/api/system/status') assert resp.status_code == 200 data = resp.get_json() assert 'sessions_count' in data assert 'workflows_count' in data assert 'tests' in data def test_system_performance(self, client): """L'API system/performance retourne les metriques.""" resp = client.get('/api/system/performance') assert resp.status_code == 200 data = resp.get_json() assert 'faiss' in data assert 'metrics' in data def test_version(self, client): """L'API version retourne la version actuelle.""" resp = client.get('/api/version') assert resp.status_code == 200 data = resp.get_json() assert 'version' in data # version est un dict avec la clé 'version' (string) assert 'version' in data['version'] def test_version_system_info(self, client): """L'API version/system-info retourne les infos systeme.""" resp = client.get('/api/version/system-info') assert resp.status_code == 200 data = resp.get_json() assert 'system_info' in data si = data['system_info'] assert 'system' in si assert 'python_version' in si['system'] def test_version_backups(self, client): """L'API version/backups retourne la liste.""" resp = client.get('/api/version/backups') assert resp.status_code == 200 data = resp.get_json() assert 'backups' in data assert isinstance(data['backups'], list) def test_services_list(self, client): """L'API services retourne la liste des services.""" resp = client.get('/api/services') assert resp.status_code == 200 data = resp.get_json() assert 'services' in data services = data['services'] assert len(services) >= 5 # Au moins 5 services configurés # Vérifier que le dashboard est dans la liste ids = [s['service_id'] for s in services] assert 'web_dashboard' in ids def test_config_get(self, client): """L'API config retourne la configuration.""" resp = client.get('/api/config') assert resp.status_code == 200 data = resp.get_json() assert data['success'] is True assert 'config' in data def test_backup_stats(self, client): """L'API backup/stats retourne les statistiques.""" resp = client.get('/api/backup/stats') assert resp.status_code == 200 data = resp.get_json() assert 'stats' in data stats = data['stats'] assert 'workflows' in stats def test_workflows_list(self, client): """L'API workflows retourne la liste.""" resp = client.get('/api/workflows') assert resp.status_code == 200 data = resp.get_json() assert 'workflows' in data def test_sessions_list(self, client): """L'API sessions retourne la liste.""" resp = client.get('/api/agent/sessions') assert resp.status_code == 200 data = resp.get_json() assert 'sessions' in data def test_tests_list(self, client): """L'API tests retourne la liste des tests.""" resp = client.get('/api/tests') assert resp.status_code == 200 data = resp.get_json() assert 'tests' in data assert 'total' in data def test_logs(self, client): """L'API logs retourne les logs.""" resp = client.get('/api/logs') assert resp.status_code == 200 data = resp.get_json() assert 'logs' in data def test_chains(self, client): """L'API chains retourne la liste.""" resp = client.get('/api/chains') assert resp.status_code == 200 data = resp.get_json() assert 'chains' in data def test_triggers(self, client): """L'API triggers retourne la liste.""" resp = client.get('/api/triggers') assert resp.status_code == 200 data = resp.get_json() assert 'triggers' in data def test_automation_status(self, client): """L'API automation/status retourne le statut.""" resp = client.get('/api/automation/status') assert resp.status_code == 200 def test_metrics_endpoint(self, client): """L'endpoint Prometheus /metrics fonctionne.""" resp = client.get('/metrics') assert resp.status_code == 200 def test_no_rollback_route(self, client): """La route /api/version/rollback n'existe pas (non implementee).""" resp = client.post('/api/version/rollback/test-id') assert resp.status_code == 404 or resp.status_code == 405 class TestGesturesRoutes: """Tests des routes du catalogue de gestes.""" def test_gestures_page_renders(self, client): """La page /gestures se rend correctement.""" resp = client.get('/gestures') assert resp.status_code == 200 assert b'Gestes Primitifs' in resp.data def test_gestures_page_has_categories(self, client): """La page /gestures affiche les catégories de gestes.""" resp = client.get('/gestures') assert resp.status_code == 200 # Vérifier qu'au moins une catégorie est présente assert b'windows' in resp.data or b'chrome' in resp.data def test_gestures_page_has_shortcuts(self, client): """La page /gestures affiche les raccourcis clavier.""" resp = client.get('/gestures') assert resp.status_code == 200 assert b'Ctrl' in resp.data or b'Alt' in resp.data def test_api_gestures(self, client): """L'API /api/gestures retourne les gestes en JSON.""" resp = client.get('/api/gestures') assert resp.status_code == 200 data = resp.get_json() assert 'gestures' in data assert 'total' in data assert 'categories' in data assert data['total'] > 0 assert isinstance(data['gestures'], list) assert len(data['gestures']) == data['total'] def test_api_gestures_structure(self, client): """Chaque geste a les champs requis.""" resp = client.get('/api/gestures') data = resp.get_json() for gesture in data['gestures']: assert 'name' in gesture assert 'category' in gesture assert 'description' in gesture def test_api_gestures_categories(self, client): """Les catégories sont bien structurées.""" resp = client.get('/api/gestures') data = resp.get_json() categories = data['categories'] assert len(categories) >= 4 # windows, chrome, edition, system au minimum for cat in categories: assert 'id' in cat assert 'name' in cat assert 'count' in cat assert cat['count'] > 0 class TestStreamingRoutes: """Tests des routes streaming.""" def test_streaming_page_renders(self, client): """La page /streaming se rend correctement.""" resp = client.get('/streaming') assert resp.status_code == 200 assert b'Streaming' in resp.data def test_streaming_page_has_stats_section(self, client): """La page /streaming contient les sections de stats.""" resp = client.get('/streaming') assert resp.status_code == 200 assert b'Sessions actives' in resp.data assert b'Serveur streaming' in resp.data def test_api_streaming_status(self, client): """L'API /api/streaming/status retourne un résultat (même si serveur offline).""" resp = client.get('/api/streaming/status') # Le serveur streaming peut ne pas être lancé (502) ou répondre (200) assert resp.status_code in (200, 502) data = resp.get_json() assert isinstance(data, dict) class TestExtractionsRoutes: """Tests des routes extractions.""" def test_extractions_page_renders(self, client): """La page /extractions se rend correctement.""" resp = client.get('/extractions') assert resp.status_code == 200 assert b'Extractions' in resp.data def test_extractions_page_module_unavailable(self, client): """La page /extractions affiche un message si le module n'est pas disponible.""" resp = client.get('/extractions') assert resp.status_code == 200 # Le module core.extraction n'existe pas, on doit voir le message assert b'non disponible' in resp.data or b'Module' in resp.data def test_api_extractions(self, client): """L'API /api/extractions retourne un résultat valide.""" resp = client.get('/api/extractions') assert resp.status_code == 200 data = resp.get_json() assert 'available' in data assert 'extractions' in data assert isinstance(data['extractions'], list) def test_api_extractions_module_status(self, client): """L'API /api/extractions indique si le module est disponible.""" resp = client.get('/api/extractions') data = resp.get_json() # Le module n'existe pas dans ce contexte assert data['available'] is False assert 'message' in data def test_api_extraction_export_no_module(self, client): """L'export CSV retourne 501 si le module n'est pas disponible.""" resp = client.get('/api/extractions/test-id/export?format=csv') assert resp.status_code == 501 data = resp.get_json() assert 'error' in data class TestNavigationLinks: """Tests de la navigation entre pages.""" def test_index_has_gestures_link(self, client): """La page d'accueil contient un lien vers /gestures.""" resp = client.get('/') assert resp.status_code == 200 assert b'/gestures' in resp.data def test_index_has_streaming_link(self, client): """La page d'accueil contient un lien vers /streaming.""" resp = client.get('/') assert resp.status_code == 200 assert b'/streaming' in resp.data def test_index_has_extractions_link(self, client): """La page d'accueil contient un lien vers /extractions.""" resp = client.get('/') assert resp.status_code == 200 assert b'/extractions' in resp.data def test_gestures_has_back_link(self, client): """La page gestures contient un lien retour vers le dashboard.""" resp = client.get('/gestures') assert resp.status_code == 200 assert b'href="/"' in resp.data or b"href='/'" in resp.data