Files
Geniusia_v2/test_ui_element_phase1.py
2026-03-05 00:20:25 +01:00

380 lines
12 KiB
Python

"""
Tests d'intégration pour Phase 1 - Mode Light des structures UI Element.
Vérifie que toutes les structures de données fonctionnent correctement ensemble.
"""
import sys
import numpy as np
from pathlib import Path
from datetime import datetime
# Ajouter le chemin du module
sys.path.insert(0, str(Path(__file__).parent))
from geniusia2.core import (
UIElement,
UIElementType,
VisualData,
TextData,
ElementProperties,
ElementContext,
EnrichedScreenState,
WindowInfo,
RawData,
PerceptionData,
StateEmbedding,
ContextData,
ScreenStateManager
)
from geniusia2.core.logger import Logger
from geniusia2.core.workflow_state_adapter import WorkflowStateAdapter
from geniusia2.core.workflow_detector import WorkflowStep
def test_uielement_creation():
"""Test création et sérialisation d'UIElement."""
print("\n" + "=" * 70)
print("TEST 1: Création et sérialisation d'UIElement")
print("=" * 70)
# Créer un UIElement
element_id = UIElement.generate_element_id(
app_name="test_app",
bbox=(100, 200, 300, 250),
label="Valider"
)
element = UIElement(
element_id=element_id,
type=UIElementType.BUTTON,
role="validate_action",
bbox=(100, 200, 300, 250),
label="Valider",
visual=VisualData(
screenshot_path="data/elements/el_001.png",
embedding_provider="openclip_ViT-B-32",
embedding_vector_id="data/embeddings/el_001.npy"
),
text=TextData(
raw="Valider",
normalized="valider",
embedding_provider="clip_text",
embedding_vector_id="data/embeddings/el_001_text.npy"
),
properties=ElementProperties(
is_clickable=True,
is_focusable=True,
is_dangerous=False
),
context=ElementContext(
app_name="test_app",
window_title="Test Window",
workflow_hint="WF_test"
),
tags=["primary_action"],
confidence=0.95,
detection_method="heuristic_rectangle"
)
print(f"✓ UIElement créé: {element.element_id}")
print(f" Type: {element.type.value}")
print(f" Label: {element.label}")
print(f" Confidence: {element.confidence}")
# Test sérialisation
json_str = element.to_json()
element_restored = UIElement.from_json(json_str)
assert element_restored.element_id == element.element_id
assert element_restored.type == element.type
assert element_restored.label == element.label
print(f"✓ Sérialisation/désérialisation réussie")
# Test stabilité de l'ID
element_id_2 = UIElement.generate_element_id(
app_name="test_app",
bbox=(100, 200, 300, 250),
label="Valider"
)
assert element_id == element_id_2
print(f"✓ Stabilité de l'element_id vérifiée")
return element
def test_enriched_screen_state_light_mode():
"""Test création d'EnrichedScreenState en mode light."""
print("\n" + "=" * 70)
print("TEST 2: EnrichedScreenState en mode light")
print("=" * 70)
window = WindowInfo(
app_name="test_app",
window_title="Test Window",
screen_resolution=(1920, 1080)
)
screen_state = EnrichedScreenState.create_light_mode(
screen_state_id="screen_test_001",
session_id="session_001",
window=window,
screenshot_path="data/screens/screen_001.png",
image_embedding_provider="openclip_ViT-B-32",
image_embedding_vector_id="data/embeddings/screen_001.npy"
)
print(f"✓ EnrichedScreenState créé: {screen_state.screen_state_id}")
print(f" Mode: {screen_state.mode}")
print(f" UI Elements: {len(screen_state.ui_elements)}")
print(f" State Embedding Provider: {screen_state.state_embedding.provider}")
# Vérifier les propriétés du mode light
assert screen_state.mode == "light"
assert len(screen_state.ui_elements) == 0
assert screen_state.state_embedding.components is None
print(f"✓ Mode light vérifié (ui_elements vide, pas de composantes)")
# Test sérialisation
json_str = screen_state.to_json()
screen_state_restored = EnrichedScreenState.from_json(json_str)
assert screen_state_restored.screen_state_id == screen_state.screen_state_id
assert screen_state_restored.mode == screen_state.mode
print(f"✓ Sérialisation/désérialisation réussie")
return screen_state
def test_screen_state_manager():
"""Test du ScreenStateManager."""
print("\n" + "=" * 70)
print("TEST 3: ScreenStateManager")
print("=" * 70)
logger = Logger(log_dir="test_logs")
manager = ScreenStateManager(
logger=logger,
data_dir="test_data",
mode="light"
)
print(f"✓ ScreenStateManager initialisé en mode: {manager.mode}")
# Créer un screen state
screen_state = manager.create_screen_state(
session_id="test_session_001",
window_title="Test Window",
app_name="test_app",
screenshot_path="test_data/screens/test_001.png",
screen_resolution=(1920, 1080),
detected_text=["Test", "Button"],
context_tags=["test"]
)
print(f"✓ Screen state créé: {screen_state.screen_state_id}")
# Sauvegarder avec embedding
test_embedding = np.random.rand(512)
state_file = manager.save_screen_state(
screen_state,
save_embedding=True,
embedding_vector=test_embedding
)
print(f"✓ Screen state sauvegardé: {state_file}")
# Charger
loaded_state = manager.load_screen_state(screen_state.screen_state_id)
assert loaded_state is not None
assert loaded_state.screen_state_id == screen_state.screen_state_id
print(f"✓ Screen state chargé: {loaded_state.screen_state_id}")
# Charger l'embedding
loaded_embedding = manager.load_embedding(screen_state.state_embedding.vector_id)
assert loaded_embedding is not None
assert np.allclose(test_embedding, loaded_embedding)
print(f"✓ Embedding chargé et vérifié")
# Lister
state_ids = manager.list_screen_states(session_id="test_session_001")
assert len(state_ids) > 0
print(f"✓ Listage: {len(state_ids)} screen states trouvés")
return manager
def test_workflow_adapter():
"""Test de l'adaptateur de workflow."""
print("\n" + "=" * 70)
print("TEST 4: WorkflowStateAdapter (compatibilité arrière)")
print("=" * 70)
logger = Logger(log_dir="test_logs")
manager = ScreenStateManager(
logger=logger,
data_dir="test_data",
mode="light"
)
adapter = WorkflowStateAdapter(
screen_state_manager=manager,
logger=logger
)
print(f"✓ WorkflowStateAdapter initialisé")
# Créer un WorkflowStep (ancien format)
step = WorkflowStep(
step_id=1,
action_type="click",
target_description="Valider Button",
position=(100, 200),
window="Test App - Main Window",
embedding=np.random.rand(512),
screenshot=None
)
print(f"✓ WorkflowStep créé (ancien format)")
# Convertir en EnrichedScreenState
screen_state = adapter.workflow_step_to_screen_state(
step=step,
session_id="test_session",
screenshot_path="test_data/screens/step_1.png"
)
assert screen_state.window.window_title == step.window
assert step.target_description in screen_state.perception.detected_text
print(f"✓ Conversion WorkflowStep → EnrichedScreenState réussie")
# Convertir en WorkflowStep (pour compatibilité)
converted_step = adapter.screen_state_to_workflow_step(
screen_state=screen_state,
step_id=1,
action_type="click",
position=(100, 200)
)
assert converted_step.step_id == step.step_id
assert converted_step.action_type == step.action_type
assert converted_step.window == step.window
print(f"✓ Conversion EnrichedScreenState → WorkflowStep réussie")
print(f"✓ Compatibilité arrière vérifiée")
def test_compatibility():
"""Test de compatibilité avec différents formats."""
print("\n" + "=" * 70)
print("TEST 5: Compatibilité multi-format")
print("=" * 70)
# Test lecture de différents modes
modes = ["light", "enriched", "complete"]
for mode in modes:
window = WindowInfo(
app_name="test_app",
window_title="Test Window",
screen_resolution=(1920, 1080)
)
if mode == "light":
screen_state = EnrichedScreenState.create_light_mode(
screen_state_id=f"screen_{mode}",
session_id="session_001",
window=window,
screenshot_path="data/screens/screen.png",
image_embedding_provider="openclip_ViT-B-32",
image_embedding_vector_id="data/embeddings/screen.npy"
)
else:
screen_state = EnrichedScreenState(
screen_state_id=f"screen_{mode}",
timestamp=datetime.now(),
session_id="session_001",
window=window,
raw=RawData(screenshot_path="data/screens/screen.png"),
perception=PerceptionData(detected_text=[]),
ui_elements=[],
state_embedding=StateEmbedding(
provider="openclip_ViT-B-32",
vector_id="data/embeddings/screen.npy",
components=None
),
context=ContextData(),
mode=mode
)
# Sérialiser et désérialiser
json_str = screen_state.to_json()
restored = EnrichedScreenState.from_json(json_str)
assert restored.mode == mode
assert restored.screen_state_id == screen_state.screen_state_id
print(f"✓ Mode '{mode}' compatible")
print(f"✓ Tous les modes sont compatibles")
def cleanup():
"""Nettoie les fichiers de test."""
import shutil
if Path("test_data").exists():
shutil.rmtree("test_data")
if Path("test_logs").exists():
shutil.rmtree("test_logs")
def main():
"""Exécute tous les tests."""
print("\n" + "=" * 70)
print("TESTS D'INTÉGRATION - PHASE 1 MODE LIGHT")
print("UI Element Detection - Structures de Données de Base")
print("=" * 70)
try:
# Test 1: UIElement
element = test_uielement_creation()
# Test 2: EnrichedScreenState
screen_state = test_enriched_screen_state_light_mode()
# Test 3: ScreenStateManager
manager = test_screen_state_manager()
# Test 4: WorkflowStateAdapter
test_workflow_adapter()
# Test 5: Compatibilité
test_compatibility()
print("\n" + "=" * 70)
print("✓ TOUS LES TESTS RÉUSSIS!")
print("=" * 70)
print("\nRésumé:")
print(" ✓ UIElement: Création, sérialisation, stabilité d'ID")
print(" ✓ EnrichedScreenState: Mode light, sérialisation")
print(" ✓ ScreenStateManager: Création, sauvegarde, chargement")
print(" ✓ WorkflowStateAdapter: Compatibilité arrière")
print(" ✓ Compatibilité: Lecture multi-format")
print("\nPhase 1 (Mode Light) implémentée avec succès!")
print("Les workflows existants continuent de fonctionner.")
print("=" * 70)
return True
except Exception as e:
print(f"\n✗ ÉCHEC DU TEST: {e}")
import traceback
traceback.print_exc()
return False
finally:
cleanup()
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)