""" Tests pour Fiche #8 - Anti-bugs terrain : Labels dupliqués Auteur: Dom, Alice Kiro - 15 décembre 2024 Objectif: Valider la gestion des labels dupliqués avec choix du bon anchor Tests: 1. Deux labels "Username" dans différents panels 2. Choix du meilleur anchor selon le contexte 3. Préférence pour containers plus spécifiques """ import pytest # Marquer tous les tests de ce fichier comme fiche8 pytestmark = pytest.mark.fiche8 from datetime import datetime from core.execution.target_resolver import TargetResolver, ResolutionContext from core.models.workflow_graph import TargetSpec from core.models.screen_state import ScreenState, RawLevel, PerceptionLevel, ContextLevel, WindowContext, EmbeddingRef from core.models.ui_element import UIElement, UIElementEmbeddings, VisualFeatures def E(eid, role, bbox, label="", etype="ui", conf=0.9): """Helper pour créer un UIElement rapidement""" return UIElement( element_id=eid, type=etype, role=role, bbox=bbox, center=(bbox[0] + bbox[2]//2, bbox[1] + bbox[3]//2), label=label, label_confidence=1.0, embeddings=UIElementEmbeddings(image=None, text=None), visual_features=VisualFeatures(dominant_color="n/a", has_icon=False, shape="rectangle", size_category="medium"), confidence=conf, tags=[], metadata={} ) def S(elements): """Helper pour créer un ScreenState rapidement""" return ScreenState( screen_state_id="s", timestamp=datetime.now(), session_id="sess", window=WindowContext(app_name="app", window_title="win", screen_resolution=[1920,1080]), raw=RawLevel(screenshot_path="x", capture_method="test", file_size_bytes=1), perception=PerceptionLevel( embedding=EmbeddingRef(provider="p", vector_id="v", dimensions=1), detected_text=[], text_detection_method="none", confidence_avg=0.0 ), context=ContextLevel(), ui_elements=elements ) def test_duplicate_labels_chooses_best_container(): """Test que le resolver choisit le bon anchor quand il y a des labels dupliqués""" # Panel A (petit, spécifique) panelA = E("panelA", "panel", (50, 50, 300, 200), etype="panel", conf=1.0) lblA = E("lblA", "label", (80, 100, 120, 20), "Username", conf=1.0) inpA = E("inpA", "input", (210, 95, 120, 30), "", etype="text_input") # Panel B (grand, moins spécifique) panelB = E("panelB", "panel", (400, 50, 800, 600), etype="panel", conf=1.0) lblB = E("lblB", "label", (430, 100, 120, 20), "Username", conf=1.0) inpB = E("inpB", "input", (560, 95, 120, 30), "", etype="text_input") screen = S([panelA, panelB, lblA, inpA, lblB, inpB]) spec = TargetSpec(by_role="input", context_hints={"right_of_text": "Username"}) r = TargetResolver() res = r.resolve_target(spec, screen, ResolutionContext(screen_state=screen, previous_target=None)) assert res is not None # Doit choisir l'input du panel A (plus petit/spécifique) assert res.element.element_id == "inpA" def test_duplicate_labels_with_no_container(): """Test avec labels dupliqués mais sans containers""" # Deux labels "Password" sans containers lbl1 = E("lbl1", "label", (100, 100, 120, 20), "Password", conf=1.0) inp1 = E("inp1", "input", (100, 140, 120, 30), "", etype="text_input") lbl2 = E("lbl2", "label", (400, 100, 120, 20), "Password", conf=1.0) inp2 = E("inp2", "input", (400, 140, 120, 30), "", etype="text_input") screen = S([lbl1, inp1, lbl2, inp2]) spec = TargetSpec(by_role="input", context_hints={"below_text": "Password"}) r = TargetResolver() res = r.resolve_target(spec, screen, ResolutionContext(screen_state=screen, previous_target=None)) assert res is not None # Doit choisir un des inputs (le premier trouvé avec la logique actuelle) assert res.element.element_id in ["inp1", "inp2"] def test_single_label_still_works(): """Test que le cas simple (un seul label) fonctionne toujours""" lbl = E("lbl", "label", (100, 100, 120, 20), "Password", conf=1.0) inp = E("inp", "input", (100, 140, 120, 30), "", etype="text_input") screen = S([lbl, inp]) spec = TargetSpec(by_role="input", context_hints={"below_text": "Password"}) r = TargetResolver() res = r.resolve_target(spec, screen, ResolutionContext(screen_state=screen, previous_target=None)) assert res is not None assert res.element.element_id == "inp" if __name__ == "__main__": pytest.main([__file__, "-v"])