- 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>
299 lines
10 KiB
Python
299 lines
10 KiB
Python
"""
|
|
Tests unitaires pour UIElement
|
|
|
|
Property 3: UIElement Detection Confidence Bounds
|
|
Validates: Requirements 3.6
|
|
"""
|
|
|
|
import pytest
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Ajouter le répertoire racine au path pour les imports
|
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
|
|
|
from core.models.ui_element import (
|
|
UIElement,
|
|
UIElementEmbeddings,
|
|
VisualFeatures,
|
|
UI_ELEMENT_TYPES,
|
|
UI_ELEMENT_ROLES
|
|
)
|
|
|
|
|
|
class TestUIElementEmbeddings:
|
|
"""Tests pour UIElementEmbeddings"""
|
|
|
|
def test_create_embeddings(self):
|
|
"""Test création UIElementEmbeddings"""
|
|
embeddings = UIElementEmbeddings(
|
|
image={"provider": "openclip", "vector_id": "test_img.npy", "dimensions": 512},
|
|
text={"provider": "openclip", "vector_id": "test_txt.npy", "dimensions": 512}
|
|
)
|
|
|
|
assert embeddings.image is not None
|
|
assert embeddings.text is not None
|
|
|
|
def test_embeddings_serialization(self):
|
|
"""Test sérialisation/désérialisation UIElementEmbeddings"""
|
|
embeddings = UIElementEmbeddings(
|
|
image={"provider": "openclip", "vector_id": "test.npy", "dimensions": 512}
|
|
)
|
|
|
|
data = embeddings.to_dict()
|
|
embeddings2 = UIElementEmbeddings.from_dict(data)
|
|
|
|
assert embeddings2.image == embeddings.image
|
|
|
|
|
|
class TestVisualFeatures:
|
|
"""Tests pour VisualFeatures"""
|
|
|
|
def test_create_visual_features(self):
|
|
"""Test création VisualFeatures"""
|
|
features = VisualFeatures(
|
|
dominant_color="#4CAF50",
|
|
has_icon=False,
|
|
shape="rectangle",
|
|
size_category="medium"
|
|
)
|
|
|
|
assert features.dominant_color == "#4CAF50"
|
|
assert features.has_icon is False
|
|
assert features.shape == "rectangle"
|
|
|
|
def test_visual_features_serialization(self):
|
|
"""Test sérialisation/désérialisation VisualFeatures"""
|
|
features = VisualFeatures(
|
|
dominant_color="#4CAF50",
|
|
has_icon=True,
|
|
shape="rounded_rectangle",
|
|
size_category="large"
|
|
)
|
|
|
|
data = features.to_dict()
|
|
features2 = VisualFeatures.from_dict(data)
|
|
|
|
assert features2.dominant_color == features.dominant_color
|
|
assert features2.has_icon == features.has_icon
|
|
assert features2.shape == features.shape
|
|
assert features2.size_category == features.size_category
|
|
|
|
|
|
class TestUIElement:
|
|
"""Tests pour UIElement"""
|
|
|
|
def create_test_ui_element(self, confidence: float = 0.94) -> UIElement:
|
|
"""Helper pour créer un UIElement de test"""
|
|
embeddings = UIElementEmbeddings(
|
|
image={"provider": "openclip", "vector_id": "test_img.npy", "dimensions": 512},
|
|
text={"provider": "openclip", "vector_id": "test_txt.npy", "dimensions": 512}
|
|
)
|
|
|
|
visual_features = VisualFeatures(
|
|
dominant_color="#4CAF50",
|
|
has_icon=False,
|
|
shape="rectangle",
|
|
size_category="medium"
|
|
)
|
|
|
|
return UIElement(
|
|
element_id="el_btn_001",
|
|
type="button",
|
|
role="primary_action",
|
|
bbox=(100, 200, 150, 40),
|
|
center=(175, 220),
|
|
label="Submit",
|
|
label_confidence=0.96,
|
|
embeddings=embeddings,
|
|
visual_features=visual_features,
|
|
tags=["action", "primary"],
|
|
confidence=confidence
|
|
)
|
|
|
|
def test_create_ui_element(self):
|
|
"""Test création UIElement"""
|
|
element = self.create_test_ui_element()
|
|
|
|
assert element.element_id == "el_btn_001"
|
|
assert element.type == "button"
|
|
assert element.role == "primary_action"
|
|
assert element.label == "Submit"
|
|
assert element.confidence == 0.94
|
|
|
|
def test_ui_element_bbox(self):
|
|
"""Test bbox et center"""
|
|
element = self.create_test_ui_element()
|
|
|
|
assert element.bbox == (100, 200, 150, 40)
|
|
assert element.center == (175, 220)
|
|
|
|
def test_ui_element_confidence_validation(self):
|
|
"""
|
|
Property 3: UIElement Detection Confidence Bounds
|
|
|
|
Pour tout UIElement, le score de confiance doit être entre 0.0 et 1.0
|
|
|
|
Validates: Requirements 3.6
|
|
"""
|
|
# Confidence valide
|
|
element = self.create_test_ui_element(confidence=0.94)
|
|
assert 0.0 <= element.confidence <= 1.0
|
|
|
|
# Confidence à 0
|
|
element = self.create_test_ui_element(confidence=0.0)
|
|
assert element.confidence == 0.0
|
|
|
|
# Confidence à 1
|
|
element = self.create_test_ui_element(confidence=1.0)
|
|
assert element.confidence == 1.0
|
|
|
|
# Confidence invalide (> 1)
|
|
with pytest.raises(ValueError, match="Confidence must be between 0 and 1"):
|
|
self.create_test_ui_element(confidence=1.5)
|
|
|
|
# Confidence invalide (< 0)
|
|
with pytest.raises(ValueError, match="Confidence must be between 0 and 1"):
|
|
self.create_test_ui_element(confidence=-0.1)
|
|
|
|
def test_ui_element_to_dict(self):
|
|
"""Test sérialisation to_dict"""
|
|
element = self.create_test_ui_element()
|
|
|
|
data = element.to_dict()
|
|
|
|
assert data["element_id"] == "el_btn_001"
|
|
assert data["type"] == "button"
|
|
assert data["role"] == "primary_action"
|
|
assert data["label"] == "Submit"
|
|
assert data["confidence"] == 0.94
|
|
assert "embeddings" in data
|
|
assert "visual_features" in data
|
|
|
|
def test_ui_element_from_dict(self):
|
|
"""Test désérialisation from_dict"""
|
|
element = self.create_test_ui_element()
|
|
|
|
data = element.to_dict()
|
|
element2 = UIElement.from_dict(data)
|
|
|
|
assert element2.element_id == element.element_id
|
|
assert element2.type == element.type
|
|
assert element2.role == element.role
|
|
assert element2.bbox == element.bbox
|
|
assert element2.confidence == element.confidence
|
|
|
|
def test_ui_element_round_trip(self):
|
|
"""Test round trip sérialisation/désérialisation"""
|
|
element = self.create_test_ui_element()
|
|
|
|
data = element.to_dict()
|
|
element2 = UIElement.from_dict(data)
|
|
|
|
# Vérifier tous les champs
|
|
assert element2.element_id == element.element_id
|
|
assert element2.type == element.type
|
|
assert element2.role == element.role
|
|
assert element2.bbox == element.bbox
|
|
assert element2.center == element.center
|
|
assert element2.label == element.label
|
|
assert element2.label_confidence == element.label_confidence
|
|
assert element2.confidence == element.confidence
|
|
assert element2.tags == element.tags
|
|
|
|
# Vérifier embeddings
|
|
assert element2.embeddings.image == element.embeddings.image
|
|
assert element2.embeddings.text == element.embeddings.text
|
|
|
|
# Vérifier visual features
|
|
assert element2.visual_features.dominant_color == element.visual_features.dominant_color
|
|
assert element2.visual_features.has_icon == element.visual_features.has_icon
|
|
|
|
def test_ui_element_to_json_string(self):
|
|
"""Test sérialisation to_json (string)"""
|
|
element = self.create_test_ui_element()
|
|
|
|
json_str = element.to_json()
|
|
assert isinstance(json_str, str)
|
|
|
|
# Vérifier que c'est du JSON valide
|
|
data = json.loads(json_str)
|
|
assert data["element_id"] == "el_btn_001"
|
|
|
|
def test_ui_element_from_json_string(self):
|
|
"""Test désérialisation from_json (string)"""
|
|
element = self.create_test_ui_element()
|
|
|
|
json_str = element.to_json()
|
|
element2 = UIElement.from_json(json_str)
|
|
|
|
assert element2.element_id == element.element_id
|
|
assert element2.confidence == element.confidence
|
|
|
|
def test_ui_element_with_metadata(self):
|
|
"""Test UIElement avec métadonnées"""
|
|
element = self.create_test_ui_element()
|
|
element.metadata = {"detection_method": "qwen_vl", "detection_time_ms": 45}
|
|
|
|
data = element.to_dict()
|
|
element2 = UIElement.from_dict(data)
|
|
|
|
assert element2.metadata["detection_method"] == "qwen_vl"
|
|
assert element2.metadata["detection_time_ms"] == 45
|
|
|
|
def test_ui_element_types_defined(self):
|
|
"""Test que les types UI sont définis"""
|
|
assert "button" in UI_ELEMENT_TYPES
|
|
assert "text_input" in UI_ELEMENT_TYPES
|
|
assert "checkbox" in UI_ELEMENT_TYPES
|
|
assert len(UI_ELEMENT_TYPES) > 0
|
|
|
|
def test_ui_element_roles_defined(self):
|
|
"""Test que les rôles UI sont définis"""
|
|
assert "primary_action" in UI_ELEMENT_ROLES
|
|
assert "cancel" in UI_ELEMENT_ROLES
|
|
assert "form_input" in UI_ELEMENT_ROLES
|
|
assert len(UI_ELEMENT_ROLES) > 0
|
|
|
|
def test_ui_element_different_types(self):
|
|
"""Test création d'éléments de différents types"""
|
|
embeddings = UIElementEmbeddings()
|
|
visual_features = VisualFeatures(
|
|
dominant_color="#FFFFFF",
|
|
has_icon=False,
|
|
shape="rectangle",
|
|
size_category="small"
|
|
)
|
|
|
|
# Button
|
|
button = UIElement(
|
|
element_id="el_001",
|
|
type="button",
|
|
role="primary_action",
|
|
bbox=(0, 0, 100, 30),
|
|
center=(50, 15),
|
|
label="Click",
|
|
label_confidence=0.9,
|
|
embeddings=embeddings,
|
|
visual_features=visual_features,
|
|
confidence=0.9
|
|
)
|
|
assert button.type == "button"
|
|
|
|
# Text input
|
|
text_input = UIElement(
|
|
element_id="el_002",
|
|
type="text_input",
|
|
role="form_input",
|
|
bbox=(0, 0, 200, 30),
|
|
center=(100, 15),
|
|
label="Name",
|
|
label_confidence=0.85,
|
|
embeddings=embeddings,
|
|
visual_features=visual_features,
|
|
confidence=0.85
|
|
)
|
|
assert text_input.type == "text_input"
|
|
assert text_input.role == "form_input"
|