Initial commit

This commit is contained in:
Dom
2026-03-05 00:20:25 +01:00
commit dcd4de9945
1954 changed files with 669380 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
"""
Tests d'intégration pour la récupération d'erreurs
Teste les scénarios complets de gestion d'erreurs :
- Récupération après échec de matching
- Récupération après target introuvable avec fallbacks
- Récupération après violation de post-conditions
- Détection et gestion de changements UI
- Rollback d'actions
"""
import pytest
import numpy as np
from pathlib import Path
from datetime import datetime
from unittest.mock import Mock, patch
import tempfile
import shutil
from core.execution.error_handler import ErrorHandler, RecoveryStrategy
from core.execution.action_executor import ActionExecutor, ExecutionStatus
from core.execution.target_resolver import TargetResolver
from core.graph.node_matcher import NodeMatcher
from core.models.screen_state import ScreenState, RawLevel, PerceptionLevel
from core.models.workflow_graph import WorkflowNode, WorkflowEdge, Action, ActionType
from core.models.ui_element import UIElement
from core.embedding.state_embedding_builder import StateEmbeddingBuilder
@pytest.fixture
def temp_dirs():
"""Créer des répertoires temporaires pour les tests."""
error_dir = tempfile.mkdtemp()
failed_matches_dir = tempfile.mkdtemp()
yield error_dir, failed_matches_dir
shutil.rmtree(error_dir)
shutil.rmtree(failed_matches_dir)
@pytest.fixture
def error_handler(temp_dirs):
"""Créer ErrorHandler pour les tests."""
error_dir, _ = temp_dirs
return ErrorHandler(error_log_dir=error_dir)
@pytest.fixture
def action_executor(error_handler):
"""Créer ActionExecutor avec ErrorHandler."""
target_resolver = TargetResolver()
return ActionExecutor(
target_resolver=target_resolver,
error_handler=error_handler,
verify_postconditions=True
)
@pytest.fixture
def node_matcher(error_handler, temp_dirs):
"""Créer NodeMatcher avec ErrorHandler."""
_, failed_matches_dir = temp_dirs
embedding_builder = StateEmbeddingBuilder()
return NodeMatcher(
embedding_builder=embedding_builder,
error_handler=error_handler,
failed_matches_dir=failed_matches_dir
)
@pytest.fixture
def mock_screen_state_with_button():
"""Créer un ScreenState avec un bouton."""
raw_level = RawLevel(
window_title="Test App",
screenshot_path=Path("/tmp/test.png"),
timestamp=datetime.now()
)
button = UIElement(
element_id="btn_1",
role="button",
text="Submit",
bbox=(100, 100, 200, 150)
)
perception_level = PerceptionLevel(
ui_elements=[button],
timestamp=datetime.now()
)
return ScreenState(
raw_level=raw_level,
perception_level=perception_level
)
class TestActionExecutorErrorRecovery:
"""Tests de récupération d'erreurs dans ActionExecutor."""
def test_target_not_found_triggers_error_handler(
self, action_executor
):
"""Test que target introuvable déclenche ErrorHandler."""
# Créer un état sans le bouton attendu
raw_level = RawLevel(
window_title="Test App",
screenshot_path=Path("/tmp/test.png"),
timestamp=datetime.now()
)
perception_level = PerceptionLevel(ui_elements=[], timestamp=datetime.now())
screen_state = ScreenState(raw_level=raw_level, perception_level=perception_level)
action = Action(
type=ActionType.MOUSE_CLICK,
target=Mock(role="button", text_pattern="Submit")
)
edge = WorkflowEdge(from_node="node_1", to_node="node_2", action=action)
result = action_executor.execute_edge(edge=edge, screen_state=screen_state)
assert result.status == ExecutionStatus.TARGET_NOT_FOUND
stats = action_executor.get_error_statistics()
assert stats['total_errors'] >= 1
class TestNodeMatcherErrorRecovery:
"""Tests de récupération d'erreurs dans NodeMatcher."""
def test_matching_failure_triggers_error_handler(
self, node_matcher, mock_screen_state_with_button
):
"""Test que l'échec de matching déclenche ErrorHandler."""
node = WorkflowNode(node_id="node_1", label="Different State")
node.matches = Mock(return_value=(False, 0.50))
result = node_matcher.match(
current_state=mock_screen_state_with_button,
candidate_nodes=[node]
)
assert result is None
stats = node_matcher.get_error_statistics()
assert stats['total_errors'] >= 1
if __name__ == '__main__':
pytest.main([__file__, '-v'])