Files
rpa_vision_v3/tests/unit/test_screen_state.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

333 lines
11 KiB
Python

"""
Tests unitaires pour ScreenState
Property 2: ScreenState Multi-Level Consistency
Validates: Requirements 2.1, 2.2, 2.3, 2.4, 2.5
"""
import pytest
from datetime import datetime
from pathlib import Path
import tempfile
from core.models.screen_state import (
ScreenState,
RawLevel,
PerceptionLevel,
ContextLevel,
WindowContext,
EmbeddingRef
)
class TestEmbeddingRef:
"""Tests pour EmbeddingRef"""
def test_create_embedding_ref(self):
"""Test création EmbeddingRef"""
emb_ref = EmbeddingRef(
provider="openclip_ViT-B-32",
vector_id="data/embeddings/test.npy",
dimensions=512
)
assert emb_ref.provider == "openclip_ViT-B-32"
assert emb_ref.dimensions == 512
def test_embedding_ref_serialization(self):
"""Test sérialisation/désérialisation EmbeddingRef"""
emb_ref = EmbeddingRef(
provider="openclip_ViT-B-32",
vector_id="data/embeddings/test.npy",
dimensions=512
)
data = emb_ref.to_dict()
emb_ref2 = EmbeddingRef.from_dict(data)
assert emb_ref2.provider == emb_ref.provider
assert emb_ref2.vector_id == emb_ref.vector_id
assert emb_ref2.dimensions == emb_ref.dimensions
class TestRawLevel:
"""Tests pour RawLevel"""
def test_create_raw_level(self):
"""Test création RawLevel"""
raw = RawLevel(
screenshot_path="data/screens/test.png",
capture_method="mss",
file_size_bytes=245678
)
assert raw.screenshot_path == "data/screens/test.png"
assert raw.capture_method == "mss"
assert raw.file_size_bytes == 245678
def test_raw_level_serialization(self):
"""Test sérialisation/désérialisation RawLevel"""
raw = RawLevel(
screenshot_path="data/screens/test.png",
capture_method="mss",
file_size_bytes=245678
)
data = raw.to_dict()
raw2 = RawLevel.from_dict(data)
assert raw2.screenshot_path == raw.screenshot_path
assert raw2.capture_method == raw.capture_method
assert raw2.file_size_bytes == raw.file_size_bytes
class TestPerceptionLevel:
"""Tests pour PerceptionLevel"""
def test_create_perception_level(self):
"""Test création PerceptionLevel"""
emb_ref = EmbeddingRef(
provider="openclip_ViT-B-32",
vector_id="data/embeddings/test.npy",
dimensions=512
)
perception = PerceptionLevel(
embedding=emb_ref,
detected_text=["Button", "Submit", "Cancel"],
text_detection_method="qwen_vl",
confidence_avg=0.92
)
assert len(perception.detected_text) == 3
assert perception.confidence_avg == 0.92
def test_perception_level_serialization(self):
"""Test sérialisation/désérialisation PerceptionLevel"""
emb_ref = EmbeddingRef(
provider="openclip_ViT-B-32",
vector_id="data/embeddings/test.npy",
dimensions=512
)
perception = PerceptionLevel(
embedding=emb_ref,
detected_text=["Button", "Submit"],
text_detection_method="qwen_vl",
confidence_avg=0.92
)
data = perception.to_dict()
perception2 = PerceptionLevel.from_dict(data)
assert perception2.detected_text == perception.detected_text
assert perception2.confidence_avg == perception.confidence_avg
assert perception2.embedding.provider == perception.embedding.provider
class TestContextLevel:
"""Tests pour ContextLevel"""
def test_create_context_level(self):
"""Test création ContextLevel"""
context = ContextLevel(
current_workflow_candidate="WF_test",
workflow_step=2,
user_id="test_user",
tags=["test", "demo"],
business_variables={"customer": "Test Corp"}
)
assert context.current_workflow_candidate == "WF_test"
assert context.workflow_step == 2
assert len(context.tags) == 2
def test_context_level_defaults(self):
"""Test valeurs par défaut ContextLevel"""
context = ContextLevel()
assert context.current_workflow_candidate is None
assert context.workflow_step is None
assert context.user_id == ""
assert context.tags == []
assert context.business_variables == {}
def test_context_level_serialization(self):
"""Test sérialisation/désérialisation ContextLevel"""
context = ContextLevel(
current_workflow_candidate="WF_test",
user_id="test_user",
tags=["test"]
)
data = context.to_dict()
context2 = ContextLevel.from_dict(data)
assert context2.current_workflow_candidate == context.current_workflow_candidate
assert context2.user_id == context.user_id
assert context2.tags == context.tags
class TestWindowContext:
"""Tests pour WindowContext"""
def test_create_window_context(self):
"""Test création WindowContext"""
window = WindowContext(
app_name="test_app",
window_title="Test Window",
screen_resolution=[1920, 1080],
workspace="main"
)
assert window.app_name == "test_app"
assert window.screen_resolution == [1920, 1080]
def test_window_context_serialization(self):
"""Test sérialisation/désérialisation WindowContext"""
window = WindowContext(
app_name="test_app",
window_title="Test Window",
screen_resolution=[1920, 1080]
)
data = window.to_dict()
window2 = WindowContext.from_dict(data)
assert window2.app_name == window.app_name
assert window2.window_title == window.window_title
assert window2.screen_resolution == window.screen_resolution
class TestScreenState:
"""Tests pour ScreenState"""
def create_test_screen_state(self) -> ScreenState:
"""Helper pour créer un ScreenState de test"""
window = WindowContext(
app_name="test_app",
window_title="Test Window",
screen_resolution=[1920, 1080]
)
raw = RawLevel(
screenshot_path="data/screens/test.png",
capture_method="mss",
file_size_bytes=245678
)
emb_ref = EmbeddingRef(
provider="openclip_ViT-B-32",
vector_id="data/embeddings/test.npy",
dimensions=512
)
perception = PerceptionLevel(
embedding=emb_ref,
detected_text=["Button", "Submit"],
text_detection_method="qwen_vl",
confidence_avg=0.92
)
context = ContextLevel(
user_id="test_user",
tags=["test"]
)
return ScreenState(
screen_state_id="screen_test_001",
timestamp=datetime(2025, 11, 22, 10, 15, 32),
session_id="sess_test_001",
window=window,
raw=raw,
perception=perception,
context=context,
metadata={"test": "value"}
)
def test_create_screen_state(self):
"""Test création ScreenState"""
screen_state = self.create_test_screen_state()
assert screen_state.screen_state_id == "screen_test_001"
assert screen_state.session_id == "sess_test_001"
assert screen_state.raw is not None
assert screen_state.perception is not None
assert screen_state.context is not None
def test_screen_state_to_json(self):
"""Test sérialisation JSON"""
screen_state = self.create_test_screen_state()
data = screen_state.to_json()
assert data["screen_state_id"] == "screen_test_001"
assert data["timestamp"] == "2025-11-22T10:15:32"
assert "raw" in data
assert "perception" in data
assert "context" in data
assert "window" in data
def test_screen_state_from_json(self):
"""Test désérialisation JSON"""
screen_state = self.create_test_screen_state()
data = screen_state.to_json()
screen_state2 = ScreenState.from_json(data)
assert screen_state2.screen_state_id == screen_state.screen_state_id
assert screen_state2.timestamp == screen_state.timestamp
assert screen_state2.session_id == screen_state.session_id
def test_screen_state_round_trip(self):
"""Test round trip sérialisation/désérialisation"""
screen_state = self.create_test_screen_state()
data = screen_state.to_json()
screen_state2 = ScreenState.from_json(data)
# Vérifier tous les niveaux
assert screen_state2.raw.screenshot_path == screen_state.raw.screenshot_path
assert screen_state2.perception.confidence_avg == screen_state.perception.confidence_avg
assert screen_state2.context.user_id == screen_state.context.user_id
assert screen_state2.window.app_name == screen_state.window.app_name
def test_screen_state_validate_consistency(self):
"""
Property 2: ScreenState Multi-Level Consistency
Pour tout ScreenState, les 4 niveaux doivent référencer
le même screenshot et timestamp.
Validates: Requirements 2.1, 2.2, 2.3, 2.4, 2.5
"""
screen_state = self.create_test_screen_state()
# Tous les niveaux doivent être présents
assert screen_state.validate_consistency()
# Vérifier que tous les niveaux existent
assert screen_state.raw is not None
assert screen_state.perception is not None
assert screen_state.context is not None
assert screen_state.window is not None
# Vérifier cohérence du timestamp
assert screen_state.timestamp is not None
def test_save_and_load_file(self):
"""Test sauvegarde et chargement depuis fichier"""
screen_state = self.create_test_screen_state()
with tempfile.TemporaryDirectory() as tmpdir:
filepath = Path(tmpdir) / "test_screen_state.json"
# Sauvegarder
screen_state.save_to_file(filepath)
assert filepath.exists()
# Charger
screen_state2 = ScreenState.load_from_file(filepath)
assert screen_state2.screen_state_id == screen_state.screen_state_id
assert screen_state2.timestamp == screen_state.timestamp