Files
rpa_vision_v3/tests/unit/test_monitor_router.py
Dom 6582a69d31 feat(qw1): MonitorRouter — résolution de l'écran cible pour le replay
Module isolé qui choisit l'écran cible avec stratégie en cascade :
1. action.monitor_index (session source) → cible explicite
2. session.last_focused_monitor → fallback focus actif
3. composite (offset 0,0) → backward compat (comportement actuel)

Backward 100% : actions sans monitor_index → fallback composite identique
au comportement mss.monitors[0] actuel.

Tests : 4 cas (cible OK, fallback focus, fallback composite, index invalide).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 22:50:22 +02:00

52 lines
2.0 KiB
Python

# tests/unit/test_monitor_router.py
"""Tests unitaires pour MonitorRouter (QW1)."""
import pytest
from agent_v0.server_v1.monitor_router import resolve_target_monitor, MonitorTarget
# Geometry de référence pour les 3 tests : 2 écrans côte à côte
TWO_MONITORS = [
{"idx": 0, "x": 0, "y": 0, "w": 1920, "h": 1080, "primary": True},
{"idx": 1, "x": 1920, "y": 0, "w": 1920, "h": 1080, "primary": False},
]
def test_resolve_uses_action_monitor_index_when_present():
"""Si action.monitor_index présent et valide → cible cet écran."""
action = {"monitor_index": 1}
session_state = {"monitors_geometry": TWO_MONITORS, "last_focused_monitor": 0}
result = resolve_target_monitor(action, session_state)
assert result.idx == 1
assert result.offset_x == 1920
assert result.offset_y == 0
assert result.source == "action"
def test_resolve_falls_back_to_focused_monitor_when_action_missing():
"""Si action.monitor_index absent → fallback focus actif."""
action = {} # pas de monitor_index
session_state = {"monitors_geometry": TWO_MONITORS, "last_focused_monitor": 1}
result = resolve_target_monitor(action, session_state)
assert result.idx == 1
assert result.source == "focus"
def test_resolve_falls_back_to_composite_when_geometry_empty():
"""Si geometry vide (vieux Agent V1) → fallback composite (idx=-1, offset=0)."""
action = {}
session_state = {"monitors_geometry": [], "last_focused_monitor": None}
result = resolve_target_monitor(action, session_state)
assert result.source == "composite_fallback"
assert result.offset_x == 0
assert result.offset_y == 0
def test_resolve_falls_back_when_action_index_out_of_range():
"""Si action.monitor_index hors limites (écran débranché) → fallback focus."""
action = {"monitor_index": 5} # n'existe pas
session_state = {"monitors_geometry": TWO_MONITORS, "last_focused_monitor": 0}
result = resolve_target_monitor(action, session_state)
assert result.idx == 0
assert result.source == "focus"